Compare commits

..

9 Commits

Author SHA1 Message Date
Ricardo Guzman f7c9201830 now LEAFET is local flash 2026-07-14 00:33:54 -04:00
Ricardo Guzman 1a042b7d0e blockeando leafet 1 2026-07-14 00:17:56 -04:00
Ricardo Guzman aaa44200b5 test query callsign fix 2026-07-06 13:09:19 -04:00
Ricardo Guzman c17ad32650 2026 update in copywrite info 2026-06-29 13:06:58 -04:00
Ricardo Guzman (Richonguzman) 26b5df1bd7 update delete of star in digipeated packet 2026-06-22 22:16:14 -04:00
Ricardo Guzman (Richonguzman) 0c3555bdbe new digimode added 2026-06-18 13:58:10 -04:00
Ricardo Guzman (Richonguzman) cf858ffad2 digi patch 2 2026-06-16 11:29:32 -04:00
Ricardo Guzman (Richonguzman) cbac8b0365 digi patch 1 2026-06-16 10:41:44 -04:00
Ricardo Guzman (Richonguzman) b76aed4d57 cambio digi modes de 2 y 3 a 1 y 2 para agregar patch 2026-06-16 10:25:22 -04:00
109 changed files with 940 additions and 140 deletions
+1
View File
@@ -51,6 +51,7 @@ ____________________________________________________
<br /> <br />
# Timeline (Versions): # Timeline (Versions):
- 2026-06-29 New UI (Web) and also Live View over a Map to see Rx stations.
- 2026-06-10 CAD (Channel Activity Detection) and DIFS (Distributed Inter-Frame Space) added. - 2026-06-10 CAD (Channel Activity Detection) and DIFS (Distributed Inter-Frame Space) added.
- 2026-03-25 More Boards, SDK update, OTA fix, GPS process update. - 2026-03-25 More Boards, SDK update, OTA fix, GPS process update.
- 2026-02-26 9M2IBR ESP32 1W (400M30S) + GPS board added. - 2026-02-26 9M2IBR ESP32 1W (400M30S) + GPS board added.
+8 -4
View File
@@ -7,7 +7,7 @@
<title>LoRa iGate & Digi software &minus; Ricardo Guzman CA2RXU</title> <title>LoRa iGate & Digi software &minus; Ricardo Guzman CA2RXU</title>
<link rel="stylesheet" href="/bootstrap.css" /> <link rel="stylesheet" href="/bootstrap.css" />
<link rel="stylesheet" href="/style.css" /> <link rel="stylesheet" href="/style.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" /> <link rel="stylesheet" href="/leaflet.css" />
<link rel="icon" href="/favicon.png" type="image/x-icon"> <link rel="icon" href="/favicon.png" type="image/x-icon">
<script>(function(){try{var t=localStorage.getItem("igateTheme");if(!t)t=window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").matches?"light":"dark";var r=document.documentElement;if(t==="night"){r.setAttribute("data-bs-theme","dark");r.setAttribute("data-variant","night");}else{r.setAttribute("data-bs-theme",t);}}catch(e){}})();</script> <script>(function(){try{var t=localStorage.getItem("igateTheme");if(!t)t=window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").matches?"light":"dark";var r=document.documentElement;if(t==="night"){r.setAttribute("data-bs-theme","dark");r.setAttribute("data-variant","night");}else{r.setAttribute("data-bs-theme",t);}}catch(e){}})();</script>
<style> <style>
@@ -1007,10 +1007,14 @@ body{background:var(--msh-bg);color:var(--msh-text);font-family:"Inter",system-u
id="digi.mode" id="digi.mode"
> >
<option value="0" selected>OFF</option> <option value="0" selected>OFF</option>
<option value="2">WIDE1 (fill-in) Digi</option> <option value="1">WIDE1 (fill-in) Digi</option>
<option value="3">WIDE2 (+WIDE1) Digi</option> <option value="2">WIDE2 (+WIDE1) Digi</option>
<option value="3">Own Callsign Path Digi</option>
</select> </select>
</div> </div>
<div class="col-12 mt-2">
+ <small class="text-muted">Mode 4 digipeats packets whose path already contains your callsign, preserving the path and appending a * to your callsign.</small>
+ </div>
<div class="col-12 mt-3"> <div class="col-12 mt-3">
<label <label
for="digi.ecoMode" for="digi.ecoMode"
@@ -2382,7 +2386,7 @@ body{background:var(--msh-bg);color:var(--msh-text);font-family:"Inter",system-u
</div> </div>
</body> </body>
<script src="/bootstrap.js"></script> <script src="/bootstrap.js"></script>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script> <script src="/leaflet.js"></script>
<script src="/script.js"></script> <script src="/script.js"></script>
</html> </html>
<script> <script>
+661
View File
@@ -0,0 +1,661 @@
/* required styles */
.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-container,
.leaflet-pane > svg,
.leaflet-pane > canvas,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
.leaflet-container {
overflow: hidden;
}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
}
/* Prevents IE11 from highlighting tiles in blue */
.leaflet-tile::selection {
background: transparent;
}
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
.leaflet-safari .leaflet-tile {
image-rendering: -webkit-optimize-contrast;
}
/* hack that prevents hw layers "stretching" when loading new tiles */
.leaflet-safari .leaflet-tile-container {
width: 1600px;
height: 1600px;
-webkit-transform-origin: 0 0;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container .leaflet-overlay-pane svg {
max-width: none !important;
max-height: none !important;
}
.leaflet-container .leaflet-marker-pane img,
.leaflet-container .leaflet-shadow-pane img,
.leaflet-container .leaflet-tile-pane img,
.leaflet-container img.leaflet-image-layer,
.leaflet-container .leaflet-tile {
max-width: none !important;
max-height: none !important;
width: auto;
padding: 0;
}
.leaflet-container img.leaflet-tile {
/* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */
mix-blend-mode: plus-lighter;
}
.leaflet-container.leaflet-touch-zoom {
-ms-touch-action: pan-x pan-y;
touch-action: pan-x pan-y;
}
.leaflet-container.leaflet-touch-drag {
-ms-touch-action: pinch-zoom;
/* Fallback for FF which doesn't support pinch-zoom */
touch-action: none;
touch-action: pinch-zoom;
}
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
-ms-touch-action: none;
touch-action: none;
}
.leaflet-container {
-webkit-tap-highlight-color: transparent;
}
.leaflet-container a {
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
}
.leaflet-tile-loaded {
visibility: inherit;
}
.leaflet-zoom-box {
width: 0;
height: 0;
-moz-box-sizing: border-box;
box-sizing: border-box;
z-index: 800;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-pane { z-index: 400; }
.leaflet-tile-pane { z-index: 200; }
.leaflet-overlay-pane { z-index: 400; }
.leaflet-shadow-pane { z-index: 500; }
.leaflet-marker-pane { z-index: 600; }
.leaflet-tooltip-pane { z-index: 650; }
.leaflet-popup-pane { z-index: 700; }
.leaflet-map-pane canvas { z-index: 100; }
.leaflet-map-pane svg { z-index: 200; }
.leaflet-vml-shape {
width: 1px;
height: 1px;
}
.lvml {
behavior: url(#default#VML);
display: inline-block;
position: absolute;
}
/* control positioning */
.leaflet-control {
position: relative;
z-index: 800;
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
.leaflet-top,
.leaflet-bottom {
position: absolute;
z-index: 1000;
pointer-events: none;
}
.leaflet-top {
top: 0;
}
.leaflet-right {
right: 0;
}
.leaflet-bottom {
bottom: 0;
}
.leaflet-left {
left: 0;
}
.leaflet-control {
float: left;
clear: both;
}
.leaflet-right .leaflet-control {
float: right;
}
.leaflet-top .leaflet-control {
margin-top: 10px;
}
.leaflet-bottom .leaflet-control {
margin-bottom: 10px;
}
.leaflet-left .leaflet-control {
margin-left: 10px;
}
.leaflet-right .leaflet-control {
margin-right: 10px;
}
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-animated {
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
}
svg.leaflet-zoom-animated {
will-change: transform;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile {
-webkit-transition: none;
-moz-transition: none;
transition: none;
}
.leaflet-zoom-anim .leaflet-zoom-hide {
visibility: hidden;
}
/* cursors */
.leaflet-interactive {
cursor: pointer;
}
.leaflet-grab {
cursor: -webkit-grab;
cursor: -moz-grab;
cursor: grab;
}
.leaflet-crosshair,
.leaflet-crosshair .leaflet-interactive {
cursor: crosshair;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-grab,
.leaflet-dragging .leaflet-grab .leaflet-interactive,
.leaflet-dragging .leaflet-marker-draggable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
cursor: grabbing;
}
/* marker & overlays interactivity */
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-image-layer,
.leaflet-pane > svg path,
.leaflet-tile-container {
pointer-events: none;
}
.leaflet-marker-icon.leaflet-interactive,
.leaflet-image-layer.leaflet-interactive,
.leaflet-pane > svg path.leaflet-interactive,
svg.leaflet-image-layer.leaflet-interactive path {
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
/* visual tweaks */
.leaflet-container {
background: #ddd;
outline-offset: 1px;
}
.leaflet-container a {
color: #0078A8;
}
.leaflet-zoom-box {
border: 2px dotted #38f;
background: rgba(255,255,255,0.5);
}
/* general typography */
.leaflet-container {
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
font-size: 12px;
font-size: 0.75rem;
line-height: 1.5;
}
/* general toolbar styles */
.leaflet-bar {
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
border-radius: 4px;
}
.leaflet-bar a {
background-color: #fff;
border-bottom: 1px solid #ccc;
width: 26px;
height: 26px;
line-height: 26px;
display: block;
text-align: center;
text-decoration: none;
color: black;
}
.leaflet-bar a,
.leaflet-control-layers-toggle {
background-position: 50% 50%;
background-repeat: no-repeat;
display: block;
}
.leaflet-bar a:hover,
.leaflet-bar a:focus {
background-color: #f4f4f4;
}
.leaflet-bar a:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.leaflet-bar a:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom: none;
}
.leaflet-bar a.leaflet-disabled {
cursor: default;
background-color: #f4f4f4;
color: #bbb;
}
.leaflet-touch .leaflet-bar a {
width: 30px;
height: 30px;
line-height: 30px;
}
.leaflet-touch .leaflet-bar a:first-child {
border-top-left-radius: 2px;
border-top-right-radius: 2px;
}
.leaflet-touch .leaflet-bar a:last-child {
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
/* zoom control */
.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
font: bold 18px 'Lucida Console', Monaco, monospace;
text-indent: 1px;
}
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
font-size: 22px;
}
/* layers control */
.leaflet-control-layers {
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
background: #fff;
border-radius: 5px;
}
.leaflet-control-layers-toggle {
background-image: url(images/layers.png);
width: 36px;
height: 36px;
}
.leaflet-retina .leaflet-control-layers-toggle {
background-image: url(images/layers-2x.png);
background-size: 26px 26px;
}
.leaflet-touch .leaflet-control-layers-toggle {
width: 44px;
height: 44px;
}
.leaflet-control-layers .leaflet-control-layers-list,
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
display: none;
}
.leaflet-control-layers-expanded .leaflet-control-layers-list {
display: block;
position: relative;
}
.leaflet-control-layers-expanded {
padding: 6px 10px 6px 6px;
color: #333;
background: #fff;
}
.leaflet-control-layers-scrollbar {
overflow-y: scroll;
overflow-x: hidden;
padding-right: 5px;
}
.leaflet-control-layers-selector {
margin-top: 2px;
position: relative;
top: 1px;
}
.leaflet-control-layers label {
display: block;
font-size: 13px;
font-size: 1.08333em;
}
.leaflet-control-layers-separator {
height: 0;
border-top: 1px solid #ddd;
margin: 5px -10px 5px -6px;
}
/* Default icon URLs */
.leaflet-default-icon-path { /* used only in path-guessing heuristic, see L.Icon.Default */
background-image: url(images/marker-icon.png);
}
/* attribution and scale controls */
.leaflet-container .leaflet-control-attribution {
background: #fff;
background: rgba(255, 255, 255, 0.8);
margin: 0;
}
.leaflet-control-attribution,
.leaflet-control-scale-line {
padding: 0 5px;
color: #333;
line-height: 1.4;
}
.leaflet-control-attribution a {
text-decoration: none;
}
.leaflet-control-attribution a:hover,
.leaflet-control-attribution a:focus {
text-decoration: underline;
}
.leaflet-attribution-flag {
display: inline !important;
vertical-align: baseline !important;
width: 1em;
height: 0.6669em;
}
.leaflet-left .leaflet-control-scale {
margin-left: 5px;
}
.leaflet-bottom .leaflet-control-scale {
margin-bottom: 5px;
}
.leaflet-control-scale-line {
border: 2px solid #777;
border-top: none;
line-height: 1.1;
padding: 2px 5px 1px;
white-space: nowrap;
-moz-box-sizing: border-box;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.8);
text-shadow: 1px 1px #fff;
}
.leaflet-control-scale-line:not(:first-child) {
border-top: 2px solid #777;
border-bottom: none;
margin-top: -2px;
}
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
border-bottom: 2px solid #777;
}
.leaflet-touch .leaflet-control-attribution,
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
box-shadow: none;
}
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
}
/* popup */
.leaflet-popup {
position: absolute;
text-align: center;
margin-bottom: 20px;
}
.leaflet-popup-content-wrapper {
padding: 1px;
text-align: left;
border-radius: 12px;
}
.leaflet-popup-content {
margin: 13px 24px 13px 20px;
line-height: 1.3;
font-size: 13px;
font-size: 1.08333em;
min-height: 1px;
}
.leaflet-popup-content p {
margin: 17px 0;
margin: 1.3em 0;
}
.leaflet-popup-tip-container {
width: 40px;
height: 20px;
position: absolute;
left: 50%;
margin-top: -1px;
margin-left: -20px;
overflow: hidden;
pointer-events: none;
}
.leaflet-popup-tip {
width: 17px;
height: 17px;
padding: 1px;
margin: -10px auto 0;
pointer-events: auto;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: white;
color: #333;
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
}
.leaflet-container a.leaflet-popup-close-button {
position: absolute;
top: 0;
right: 0;
border: none;
text-align: center;
width: 24px;
height: 24px;
font: 16px/24px Tahoma, Verdana, sans-serif;
color: #757575;
text-decoration: none;
background: transparent;
}
.leaflet-container a.leaflet-popup-close-button:hover,
.leaflet-container a.leaflet-popup-close-button:focus {
color: #585858;
}
.leaflet-popup-scrolled {
overflow: auto;
}
.leaflet-oldie .leaflet-popup-content-wrapper {
-ms-zoom: 1;
}
.leaflet-oldie .leaflet-popup-tip {
width: 24px;
margin: 0 auto;
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}
.leaflet-oldie .leaflet-control-zoom,
.leaflet-oldie .leaflet-control-layers,
.leaflet-oldie .leaflet-popup-content-wrapper,
.leaflet-oldie .leaflet-popup-tip {
border: 1px solid #999;
}
/* div icon */
.leaflet-div-icon {
background: #fff;
border: 1px solid #666;
}
/* Tooltip */
/* Base styles for the element that has a tooltip */
.leaflet-tooltip {
position: absolute;
padding: 6px;
background-color: #fff;
border: 1px solid #fff;
border-radius: 3px;
color: #222;
white-space: nowrap;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
pointer-events: none;
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.leaflet-tooltip.leaflet-interactive {
cursor: pointer;
pointer-events: auto;
}
.leaflet-tooltip-top:before,
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
position: absolute;
pointer-events: none;
border: 6px solid transparent;
background: transparent;
content: "";
}
/* Directions */
.leaflet-tooltip-bottom {
margin-top: 6px;
}
.leaflet-tooltip-top {
margin-top: -6px;
}
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-top:before {
left: 50%;
margin-left: -6px;
}
.leaflet-tooltip-top:before {
bottom: 0;
margin-bottom: -12px;
border-top-color: #fff;
}
.leaflet-tooltip-bottom:before {
top: 0;
margin-top: -12px;
margin-left: -6px;
border-bottom-color: #fff;
}
.leaflet-tooltip-left {
margin-left: -6px;
}
.leaflet-tooltip-right {
margin-left: 6px;
}
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
top: 50%;
margin-top: -6px;
}
.leaflet-tooltip-left:before {
right: 0;
margin-right: -12px;
border-left-color: #fff;
}
.leaflet-tooltip-right:before {
left: 0;
margin-left: -12px;
border-right-color: #fff;
}
/* Printing */
@media print {
/* Prevent printers from removing background-images of controls. */
.leaflet-control {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
}
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+18
View File
@@ -1,3 +1,21 @@
/* Copyright (C) 2026 Ricardo Guzman - CA2RXU
*
* This file is part of LoRa APRS iGate.
*
* LoRa APRS iGate is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/
#include <Arduino.h> #include <Arduino.h>
#include <SPI.h> #include <SPI.h>
#include <WiFi.h> #include <WiFi.h>
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+2
View File
@@ -26,6 +26,8 @@ board_build.embed_files =
data_embed/script.js.gz data_embed/script.js.gz
data_embed/bootstrap.css.gz data_embed/bootstrap.css.gz
data_embed/bootstrap.js.gz data_embed/bootstrap.js.gz
data_embed/leaflet.css.gz
data_embed/leaflet.js.gz
data_embed/favicon.png.gz data_embed/favicon.png.gz
extra_scripts = extra_scripts =
pre:tools/compress.py pre:tools/compress.py
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+3 -3
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -68,7 +68,7 @@ ___________________________________________________________________*/
#endif #endif
String versionDate = "2026-06-12"; String versionDate = "2026-07-14";
String versionNumber = "4.0.0"; String versionNumber = "4.0.0";
Configuration Config; Configuration Config;
WiFiClient aprsIsClient; WiFiClient aprsIsClient;
@@ -196,7 +196,7 @@ void loop() {
APRS_IS_Utils::processLoRaPacket(packet); // Send received packet to APRSIS APRS_IS_Utils::processLoRaPacket(packet); // Send received packet to APRSIS
} }
if (Config.loramodule.txActive && (Config.digi.mode == 2 || Config.digi.mode == 3 || backupDigiMode)) { // If Digi enabled if (Config.loramodule.txActive && (Config.digi.mode == 1 || Config.digi.mode == 2 || Config.digi.mode == 3 || backupDigiMode)) { // If Digi enabled
DIGI_Utils::processLoRaPacket(packet); // Send received packet to Digi DIGI_Utils::processLoRaPacket(packet); // Send received packet to Digi
} }
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+11 -8
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -570,14 +570,17 @@ void Configuration::setDefaultValues() {
void Configuration::setup() { void Configuration::setup() {
if (!SPIFFS.begin(false)) { if (!SPIFFS.begin(false)) {
Serial.println("SPIFFS Mount Failed"); Serial.println("SPIFFS Mount Failed, formatting...");
return;
} else {
Serial.println("SPIFFS Mounted");
}
bool exists = SPIFFS.exists("/igate_conf.json"); if (!SPIFFS.begin(true)) {
if (!exists) { Serial.println("SPIFFS Format Failed");
return;
}
}
Serial.println("SPIFFS Ready");
if (!SPIFFS.exists("/igate_conf.json")) {
Serial.println("Config not found, creating default...");
setDefaultValues(); setDefaultValues();
writeFile(); writeFile();
delay(1000); delay(1000);
+48 -10
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -42,8 +42,8 @@ extern bool backupDigiMode;
namespace DIGI_Utils { namespace DIGI_Utils {
String cleanPathAsterisks(String path) { String cleanPath(String path) {
String terms[] = {",WIDE1*", ",WIDE2*", "*"}; String terms[] = {"WIDE1*,", "WIDE2*,", "*"};
for (String term : terms) { for (String term : terms) {
int index = path.indexOf(term); int index = path.indexOf(term);
if (index != -1) path.remove(index, term.length()); // less memory than: tempPath.replace("*", ""); if (index != -1) path.remove(index, term.length()); // less memory than: tempPath.replace("*", "");
@@ -51,6 +51,35 @@ namespace DIGI_Utils {
return path; return path;
} }
String processMode3Path(const String& path, const String& stationCallsign) {
int start = 0;
bool prevTokensAllStar = true;
int ownTokenEnd = -1;
while (start < path.length()) {
int delim = path.indexOf(',', start);
if (delim == -1) delim = path.length(); // busca todo hasta lograr encontra una coma o el final del string
String token = path.substring(start, delim);
bool tokenIsOwn = (token == stationCallsign) || (token == stationCallsign + "*");
bool tokenStar = token.endsWith("*");
if (tokenIsOwn) {
if (tokenStar) return ""; // already digipeated
if (!prevTokensAllStar) return ""; // earlier tokens must be marked
ownTokenEnd = delim;
break;
}
if (!tokenStar) prevTokensAllStar = false;
start = delim + 1;
}
if (ownTokenEnd == -1) return "";
String tempPacket = cleanPath(path.substring(0, ownTokenEnd));
return tempPacket + "*" + path.substring(ownTokenEnd);
}
String buildPacket(const String& path, const String& packet, bool thirdParty, bool crossFreq) { String buildPacket(const String& path, const String& packet, bool thirdParty, bool crossFreq) {
String stationCallsign = (Config.tacticalCallsign == "" ? Config.callsign : Config.tacticalCallsign); String stationCallsign = (Config.tacticalCallsign == "" ? Config.callsign : Config.tacticalCallsign);
String suffix = thirdParty ? ":}" : ":"; String suffix = thirdParty ? ":}" : ":";
@@ -60,11 +89,11 @@ namespace DIGI_Utils {
int digiMode = Config.digi.mode; int digiMode = Config.digi.mode;
String tempPath = path; String tempPath = path;
if (tempPath.indexOf("WIDE1-1") != -1 && (digiMode == 2 || digiMode == 3)) { // WIDE1-1 if (tempPath.indexOf("WIDE1-1") != -1 && (digiMode == 1 || digiMode == 2)) { // WIDE1-1
if (tempPath.indexOf("*") != -1 ) return ""; // "*" shouldn't be in WIDE1-1 (only) type of packet if (tempPath.indexOf("*") != -1 ) return ""; // "*" shouldn't be in WIDE1-1 (only) type of packet
tempPath.replace("WIDE1-1", stationCallsign + "*"); tempPath.replace("WIDE1-1", stationCallsign + "*");
} else if (tempPath.indexOf("WIDE2-") != -1 && digiMode == 3) { // WIDE2-n Digipeater } else if (tempPath.indexOf("WIDE2-") != -1 && digiMode == 2) { // WIDE2-n Digipeater
tempPath = cleanPathAsterisks(path); tempPath = cleanPath(path);
if (tempPath.indexOf("WIDE2-1") != -1) { if (tempPath.indexOf("WIDE2-1") != -1) {
tempPath.replace("WIDE2-1", stationCallsign + "*"); tempPath.replace("WIDE2-1", stationCallsign + "*");
} else if (tempPath.indexOf("WIDE2-2") != -1) { } else if (tempPath.indexOf("WIDE2-2") != -1) {
@@ -72,11 +101,14 @@ namespace DIGI_Utils {
} else { } else {
return ""; return "";
} }
} else if (digiMode == 3) { // Repeat if station callsign is in path (free to repeat).
tempPath = processMode3Path(tempPath, stationCallsign);
if (tempPath == "") return "";
} }
packetToRepeat = packet.substring(0, packet.indexOf(",") + 1); packetToRepeat = packet.substring(0, packet.indexOf(",") + 1);
packetToRepeat += tempPath; packetToRepeat += tempPath;
} else { // CrossFreq Digipeater } else { // CrossFreq Digipeater
packetToRepeat = cleanPathAsterisks(packet.substring(0, suffixIndex)); packetToRepeat = cleanPath(packet.substring(0, suffixIndex));
if (packetToRepeat.indexOf(stationCallsign) != -1) return ""; // stationCallsign shouldn't be in path if (packetToRepeat.indexOf(stationCallsign) != -1) return ""; // stationCallsign shouldn't be in path
packetToRepeat += ","; packetToRepeat += ",";
packetToRepeat += stationCallsign; packetToRepeat += stationCallsign;
@@ -100,14 +132,14 @@ namespace DIGI_Utils {
if (commaIndex > 2) { // "path" found if (commaIndex > 2) { // "path" found
const String& path = temp.substring(commaIndex + 1); const String& path = temp.substring(commaIndex + 1);
if (digiMode == 2 || backupDigiMode) { if (digiMode == 1 || backupDigiMode) {
bool hasWide = path.indexOf("WIDE1-1") != -1; bool hasWide = path.indexOf("WIDE1-1") != -1;
if (hasWide || crossFreq) { if (hasWide || crossFreq) {
return buildPacket(path, packet, thirdParty, !hasWide); return buildPacket(path, packet, thirdParty, !hasWide);
} }
return ""; return "";
} }
if (digiMode == 3) { if (digiMode == 2) {
int wide1Index = path.indexOf("WIDE1-1"); int wide1Index = path.indexOf("WIDE1-1");
int wide2Index = path.indexOf("WIDE2-"); int wide2Index = path.indexOf("WIDE2-");
bool hasWide1 = wide1Index != -1; bool hasWide1 = wide1Index != -1;
@@ -121,10 +153,16 @@ namespace DIGI_Utils {
return ""; return "";
} }
if (digiMode == 3) {
String stationCallsign = (Config.tacticalCallsign == "" ? Config.callsign : Config.tacticalCallsign);
bool containsOwnCall = path.indexOf(stationCallsign) != -1;
if (containsOwnCall) return buildPacket(path, packet, thirdParty, false);
return "";
}
return ""; return "";
} }
if (commaIndex == -1 && (digiMode == 2 || backupDigiMode || digiMode == 3) && crossFreq) return buildPacket("", packet, thirdParty, true); // no "path" but is CrossFreq Digi if (commaIndex == -1 && (digiMode == 1 || backupDigiMode || digiMode == 2) && crossFreq) return buildPacket("", packet, thirdParty, true); // no "path" but is CrossFreq Digi
return ""; return "";
} }
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+11 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -185,6 +185,16 @@ namespace GPS_Utils {
return " _ / _ / _ "; return " _ / _ / _ ";
} }
/*String getDistanceAndCommentFromMicE(const String& packet) {
int indexOfMicE1 = packet.indexOf(":`");
int indexOfMicE2 = packet.indexOf(":\'");
if (indexOfMicE1 > 10 || indexOfMicE2 > 10) {
return decodeEncodedGPS(packet);
}
return " _ / _ / _ ";
}*/
void setup() { void setup() {
#ifdef HAS_GPS #ifdef HAS_GPS
if (Config.beacon.gpsActive && Config.digi.ecoMode != 1) { if (Config.beacon.gpsActive && Config.digi.ecoMode != 1) {
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+11 -2
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -69,6 +69,15 @@ float snr;
namespace LoRa_Utils { namespace LoRa_Utils {
static String sanitizeForWeb(const String& s) { // replaces non-printable ASCII with '.' for WebUI display
String out = s;
for (int i = 0; i < (int)out.length(); i++) {
uint8_t c = (uint8_t)out[i];
if (c < 32 || c == 127) out.setCharAt(i, '.');
}
return out;
}
void setFlag(void) { void setFlag(void) {
operationDone = true; operationDone = true;
} }
@@ -276,7 +285,7 @@ namespace LoRa_Utils {
} }
ReceivedPacket receivedPacket; ReceivedPacket receivedPacket;
receivedPacket.rxTime = NTP_Utils::getFormatedTime(); receivedPacket.rxTime = NTP_Utils::getFormatedTime();
receivedPacket.packet = packet.substring(3); receivedPacket.packet = sanitizeForWeb(packet.substring(3));
receivedPacket.RSSI = rssi; receivedPacket.RSSI = rssi;
receivedPacket.SNR = snr; receivedPacket.SNR = snr;
receivedPackets.push_back(receivedPacket); receivedPackets.push_back(receivedPacket);
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+18
View File
@@ -1,3 +1,21 @@
/* Copyright (C) 2026 Ricardo Guzman - CA2RXU
*
* This file is part of LoRa APRS iGate.
*
* LoRa APRS iGate is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/
#include <Arduino.h> #include <Arduino.h>
#include "network_manager.h" #include "network_manager.h"
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+4 -4
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -82,7 +82,7 @@ namespace QUERY_Utils {
int radioTxActive = Config.loramodule.txActive; int radioTxActive = Config.loramodule.txActive;
bool onlyRadioActive = radioTxActive && Config.loramodule.rxActive && !Config.aprs_is.active; bool onlyRadioActive = radioTxActive && Config.loramodule.rxActive && !Config.aprs_is.active;
if (queryQuestion.startsWith("?EM=OFF")) { if (queryQuestion.startsWith("?EM=OFF")) {
if ((digiMode == 2 || digiMode == 3) && onlyRadioActive) { if ((digiMode == 1 || digiMode == 2 || digiMode == 3) && onlyRadioActive) {
if (digiEcoMode == 1 || digiEcoMode == 2) { // Exit Digipeater EcoMode or Digipeater without WiFiAP if (digiEcoMode == 1 || digiEcoMode == 2) { // Exit Digipeater EcoMode or Digipeater without WiFiAP
answer = (digiEcoMode == 1) ? "DigiEcoMode:OFF" : "Digipeater + WiFiAP enabled"; answer = (digiEcoMode == 1) ? "DigiEcoMode:OFF" : "Digipeater + WiFiAP enabled";
Config.digi.ecoMode = 0; Config.digi.ecoMode = 0;
@@ -97,7 +97,7 @@ namespace QUERY_Utils {
answer = "Digipeater Mode control not possible"; answer = "Digipeater Mode control not possible";
} }
} else if (queryQuestion.startsWith("?EM=ON")) { } else if (queryQuestion.startsWith("?EM=ON")) {
if ((digiMode == 2 || digiMode == 3) && onlyRadioActive) { if ((digiMode == 1 || digiMode == 2 || digiMode == 3) && onlyRadioActive) {
if (digiEcoMode == 0) { // Start Digipeater EcoMode if (digiEcoMode == 0) { // Start Digipeater EcoMode
answer = "DigiEcoMode:ON"; answer = "DigiEcoMode:ON";
Config.digi.ecoMode = 1; Config.digi.ecoMode = 1;
@@ -139,7 +139,7 @@ namespace QUERY_Utils {
if (answer == "") return ""; if (answer == "") return "";
String queryAnswer = Config.callsign; String queryAnswer = (Config.tacticalCallsign == "" ? Config.callsign : Config.tacticalCallsign);
queryAnswer += ">APLRG1"; queryAnswer += ">APLRG1";
if (queryFromAPRSIS) { if (queryFromAPRSIS) {
queryAnswer += ",TCPIP,qAC"; queryAnswer += ",TCPIP,qAC";
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+6 -2
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -79,11 +79,15 @@ namespace SYSLOG_Utils {
syslogPacket.concat(sender); syslogPacket.concat(sender);
syslogPacket.concat(" ---> "); syslogPacket.concat(" ---> ");
syslogPacket.concat(packet.substring(colonIndex + 2)); syslogPacket.concat(packet.substring(colonIndex + 2));
} else if (nextChar == '`') { } else if (nextChar == '`' || nextChar == '\'') { // both Mic-E DTIs are valid
syslogPacket.concat("MIC-E / "); syslogPacket.concat("MIC-E / ");
syslogPacket.concat(sender); syslogPacket.concat(sender);
syslogPacket.concat(" ---> "); syslogPacket.concat(" ---> ");
syslogPacket.concat(String(nextChar)); // restore the actual indicator received
syslogPacket.concat(packet.substring(colonIndex + 2)); syslogPacket.concat(packet.substring(colonIndex + 2));
// append distance for Mic-E, same as the GPS path
//syslogPacket.concat(" / ");
//syslogPacket.concat(GPS_Utils::getDistanceAndComment(packet));
} else if (nextChar == ';') { } else if (nextChar == ';') {
syslogPacket.concat("OBJECT / "); syslogPacket.concat("OBJECT / ");
syslogPacket.concat(sender); syslogPacket.concat(sender);
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+25 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -49,6 +49,14 @@ extern const char web_bootstrap_js[] asm("_binary_data_embed_bootstrap_js_gz_sta
extern const char web_bootstrap_js_end[] asm("_binary_data_embed_bootstrap_js_gz_end"); extern const char web_bootstrap_js_end[] asm("_binary_data_embed_bootstrap_js_gz_end");
extern const size_t web_bootstrap_js_len = web_bootstrap_js_end - web_bootstrap_js; extern const size_t web_bootstrap_js_len = web_bootstrap_js_end - web_bootstrap_js;
extern const char web_leaflet_css[] asm("_binary_data_embed_leaflet_css_gz_start");
extern const char web_leaflet_css_end[] asm("_binary_data_embed_leaflet_css_gz_end");
extern const size_t web_leaflet_css_len = web_leaflet_css_end - web_leaflet_css;
extern const char web_leaflet_js[] asm("_binary_data_embed_leaflet_js_gz_start");
extern const char web_leaflet_js_end[] asm("_binary_data_embed_leaflet_js_gz_end");
extern const size_t web_leaflet_js_len = web_leaflet_js_end - web_leaflet_js;
// Declare external symbols for the embedded image data // Declare external symbols for the embedded image data
extern const unsigned char favicon_data[] asm("_binary_data_embed_favicon_png_gz_start"); extern const unsigned char favicon_data[] asm("_binary_data_embed_favicon_png_gz_start");
extern const unsigned char favicon_data_end[] asm("_binary_data_embed_favicon_png_gz_end"); extern const unsigned char favicon_data_end[] asm("_binary_data_embed_favicon_png_gz_end");
@@ -363,6 +371,20 @@ namespace WEB_Utils {
request->send(response); request->send(response);
} }
void handleLeafletStyle(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response = request->beginResponse(200, "text/css", (const uint8_t*)web_leaflet_css, web_leaflet_css_len);
response->addHeader("Content-Encoding", "gzip");
response->addHeader("Cache-Control", "max-age=3600");
request->send(response);
}
void handleLeafletScript(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response = request->beginResponse(200, "text/javascript", (const uint8_t*)web_leaflet_js, web_leaflet_js_len);
response->addHeader("Content-Encoding", "gzip");
response->addHeader("Cache-Control", "max-age=3600");
request->send(response);
}
void setup() { void setup() {
if (Config.digi.ecoMode == 0) { if (Config.digi.ecoMode == 0) {
server.on("/", HTTP_GET, handleHome); server.on("/", HTTP_GET, handleHome);
@@ -376,6 +398,8 @@ namespace WEB_Utils {
server.on("/script.js", HTTP_GET, handleScript); server.on("/script.js", HTTP_GET, handleScript);
server.on("/bootstrap.css", HTTP_GET, handleBootstrapStyle); server.on("/bootstrap.css", HTTP_GET, handleBootstrapStyle);
server.on("/bootstrap.js", HTTP_GET, handleBootstrapScript); server.on("/bootstrap.js", HTTP_GET, handleBootstrapScript);
server.on("/leaflet.css", HTTP_GET, handleLeafletStyle);
server.on("/leaflet.js", HTTP_GET, handleLeafletScript);
server.on("/favicon.png", HTTP_GET, handleFavicon); server.on("/favicon.png", HTTP_GET, handleFavicon);
OTA_Utils::setup(&server); // Include OTA Updater for WebServer OTA_Utils::setup(&server); // Include OTA Updater for WebServer
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+14 -12
View File
@@ -1,17 +1,17 @@
# Copyright (C) 2025 Ricardo Guzman - CA2RXU # Copyright (C) 2026 Ricardo Guzman - CA2RXU
# #
# This file is part of LoRa APRS iGate. # This file is part of LoRa APRS iGate.
# #
# LoRa APRS iGate is free software: you can redistribute it and/or modify # LoRa APRS iGate is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# LoRa APRS iGate is distributed in the hope that it will be useful, # LoRa APRS iGate is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>. # along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
@@ -26,6 +26,8 @@ files = [
'data_embed/style.css', 'data_embed/style.css',
'data_embed/bootstrap.js', 'data_embed/bootstrap.js',
'data_embed/bootstrap.css', 'data_embed/bootstrap.css',
'data_embed/leaflet.js',
'data_embed/leaflet.css',
'data_embed/favicon.png', 'data_embed/favicon.png',
] ]
@@ -40,20 +42,20 @@ with open('src/LoRa_APRS_iGate.cpp', encoding='utf-8') as cpp_file:
if start > 0 and end > start: if start > 0 and end > start:
versionDate = line[start:end] versionDate = line[start:end]
break break
for src in files: for src in files:
out = src + ".gz" out = src + ".gz"
with open(src, 'rb') as f: with open(src, 'rb') as f:
content = f.read() content = f.read()
if src == 'data_embed/index.html': if src == 'data_embed/index.html':
env_vars = env["BOARD"] + "<br>" + ','.join(env["BUILD_FLAGS"]).replace('-Werror -Wall,', '').replace(',-DELEGANTOTA_USE_ASYNC_WEBSERVER=1', '') + "<br>" + "Version date: " + versionDate env_vars = env["BOARD"] + "<br>" + ','.join(env["BUILD_FLAGS"]).replace('-Werror -Wall,', '').replace(',-DELEGANTOTA_USE_ASYNC_WEBSERVER=1', '') + "<br>" + "Version date: " + versionDate
current_date = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S') + " UTC" current_date = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S') + " UTC"
build_info = f'{env_vars}<br>Build date: {current_date}'.encode() build_info = f'{env_vars}<br>Build date: {current_date}'.encode()
content = content.replace(b'%BUILD_INFO%', build_info) content = content.replace(b'%BUILD_INFO%', build_info)
with open(out, 'wb') as f: with open(out, 'wb') as f:
f.write(gzip.compress(content, compresslevel=9)) f.write(gzip.compress(content, compresslevel=9))
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2026 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *

Some files were not shown because too many files have changed in this diff Show More