Skip to content

Commit b7ea1f7

Browse files
committed
add technical sender info
1 parent 9df1245 commit b7ea1f7

File tree

7 files changed

+11492
-11140
lines changed

7 files changed

+11492
-11140
lines changed

Source/Application/WebDB.cpp

Lines changed: 11234 additions & 11107 deletions
Large diffs are not rendered by default.

Source/HTML/index.html

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<script src="https://cdn.jsdelivr.net/npm/ol@v10.0.0/dist/ol.js"></script>
2121
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v10.0.0/ol.css">
2222

23-
<link rel="stylesheet" href="style.css?hash=b735ed7035d87cfdb8231fb26441a5ea" />
23+
<link rel="stylesheet" href="style.css?hash=941980d4bca290cfc87ab22a9f0cd5d0" />
2424
<link rel="stylesheet" href="custom/config.css" />
2525

2626
</head>
@@ -1110,14 +1110,25 @@ <h3>NMEA Decoder</h3>
11101110
<div><span>Ship type</span><span id="shipcard_shiptype"></span></div>
11111111
</div>
11121112

1113-
<div onclick="shipcardselect(this)" data-context-type="ship"
1114-
class="mapcard-content-row shipcard-content-row shipcard-max-only">
1115-
<div><span>Country</span><span id="shipcard_country"></span></div>
1116-
<div><span>Sender</span><span id="shipcard_type"></span></div>
1117-
<div><span>In Range</span><span id="shipcard_received_stations"></span></div>
1118-
</div>
1119-
1120-
<div onclick="shipcardselect(this)" data-context-type="ship"
1113+
<div onclick="shipcardselect(this)" data-context-type="ship"
1114+
class="mapcard-content-row shipcard-content-row shipcard-max-only">
1115+
<div><span>Country</span><span id="shipcard_country"></span></div>
1116+
<div><span>Sender</span><span id="shipcard_type"></span></div>
1117+
<div><span>In Range</span><span id="shipcard_received_stations"></span></div>
1118+
</div>
1119+
1120+
<!-- Technical details popover -->
1121+
<div id="tech_popover" class="tech-popover" style="display: none;">
1122+
<div><span>RAIM:</span><span id="tech_raim">-</span></div>
1123+
<div><span>DTE:</span><span id="tech_dte">-</span></div>
1124+
<div><span>Mode:</span><span id="tech_assigned">-</span></div>
1125+
<div><span>Display:</span><span id="tech_display">-</span></div>
1126+
<div><span>DSC:</span><span id="tech_dsc">-</span></div>
1127+
<div><span>Band:</span><span id="tech_band">-</span></div>
1128+
<div><span>MSG22:</span><span id="tech_msg22">-</span></div>
1129+
<div><span>Off-Pos:</span><span id="tech_off_position">-</span></div>
1130+
<div><span>Maneuver:</span><span id="tech_maneuver">-</span></div>
1131+
</div> <div onclick="shipcardselect(this)" data-context-type="ship"
11211132
class="mapcard-content-row shipcard-content-row shipcard-max-only">
11221133
<div><span>MMSI</span><span id="shipcard_mmsi">-</span></div>
11231134
<div><span>Callsign</span><span id="shipcard_callsign">-</span></div>
@@ -1365,7 +1376,7 @@ <h3>NMEA Decoder</h3>
13651376
<div class="bottombar"></div>
13661377

13671378
<script src="custom/plugins.js"></script>
1368-
<script src="script.js?hash=88a83b72072a2f18751e67f19682cd5a"></script>
1379+
<script src="script.js?hash=c2b4382276b602aa8eb20819d0e6c928"></script>
13691380

13701381

13711382
<div class="overlay" onclick="toggleInfoPanel()"></div>

Source/HTML/index_local.html

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<script src="cdn/npm/ol@v10.0.0/dist/ol.js"></script>
2121
<link rel="stylesheet" href="cdn/npm/ol@v10.0.0/ol.css">
2222

23-
<link rel="stylesheet" href="style.css?hash=b735ed7035d87cfdb8231fb26441a5ea" />
23+
<link rel="stylesheet" href="style.css?hash=941980d4bca290cfc87ab22a9f0cd5d0" />
2424
<link rel="stylesheet" href="custom/config.css" />
2525

2626
</head>
@@ -1110,14 +1110,25 @@ <h3>NMEA Decoder</h3>
11101110
<div><span>Ship type</span><span id="shipcard_shiptype"></span></div>
11111111
</div>
11121112

1113-
<div onclick="shipcardselect(this)" data-context-type="ship"
1114-
class="mapcard-content-row shipcard-content-row shipcard-max-only">
1115-
<div><span>Country</span><span id="shipcard_country"></span></div>
1116-
<div><span>Sender</span><span id="shipcard_type"></span></div>
1117-
<div><span>In Range</span><span id="shipcard_received_stations"></span></div>
1118-
</div>
1119-
1120-
<div onclick="shipcardselect(this)" data-context-type="ship"
1113+
<div onclick="shipcardselect(this)" data-context-type="ship"
1114+
class="mapcard-content-row shipcard-content-row shipcard-max-only">
1115+
<div><span>Country</span><span id="shipcard_country"></span></div>
1116+
<div><span>Sender</span><span id="shipcard_type"></span></div>
1117+
<div><span>In Range</span><span id="shipcard_received_stations"></span></div>
1118+
</div>
1119+
1120+
<!-- Technical details popover -->
1121+
<div id="tech_popover" class="tech-popover" style="display: none;">
1122+
<div><span>RAIM:</span><span id="tech_raim">-</span></div>
1123+
<div><span>DTE:</span><span id="tech_dte">-</span></div>
1124+
<div><span>Mode:</span><span id="tech_assigned">-</span></div>
1125+
<div><span>Display:</span><span id="tech_display">-</span></div>
1126+
<div><span>DSC:</span><span id="tech_dsc">-</span></div>
1127+
<div><span>Band:</span><span id="tech_band">-</span></div>
1128+
<div><span>MSG22:</span><span id="tech_msg22">-</span></div>
1129+
<div><span>Off-Pos:</span><span id="tech_off_position">-</span></div>
1130+
<div><span>Maneuver:</span><span id="tech_maneuver">-</span></div>
1131+
</div> <div onclick="shipcardselect(this)" data-context-type="ship"
11211132
class="mapcard-content-row shipcard-content-row shipcard-max-only">
11221133
<div><span>MMSI</span><span id="shipcard_mmsi">-</span></div>
11231134
<div><span>Callsign</span><span id="shipcard_callsign">-</span></div>
@@ -1365,7 +1376,7 @@ <h3>NMEA Decoder</h3>
13651376
<div class="bottombar"></div>
13661377

13671378
<script src="custom/plugins.js"></script>
1368-
<script src="script.js?hash=88a83b72072a2f18751e67f19682cd5a"></script>
1379+
<script src="script.js?hash=c2b4382276b602aa8eb20819d0e6c928"></script>
13691380

13701381

13711382
<div class="overlay" onclick="toggleInfoPanel()"></div>

Source/HTML/script.js

Lines changed: 125 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,13 @@ function showContextMenu(event, mmsi, type, context) {
12101210
});
12111211
});
12121212

1213+
// Hide realtime menu items if realtime is disabled
1214+
if (typeof realtime_enabled === "undefined" || realtime_enabled === false) {
1215+
document.querySelectorAll('.ctx-realtime').forEach((element) => {
1216+
element.style.display = "none";
1217+
});
1218+
}
1219+
12131220
// we might have made non-android items visible in the context menu, so hide non-android items if needed
12141221
updateAndroid();
12151222
updateKiosk();
@@ -2019,7 +2026,7 @@ function ToggleFireworks() {
20192026

20202027
function StartFireworks() {
20212028
if (evtSourceMap == null) {
2022-
if (typeof realtime_enabled === "undefined" || realtime_enabled === false) {
2029+
if (!realtime_enabled) {
20232030
showDialog("Error", "Cannot run Firework Mode. Please ensure that AIS-catcher is running with -N REALTIME on.");
20242031
return;
20252032
}
@@ -2958,6 +2965,15 @@ async function fetchShips(noDoubleFetch = true) {
29582965
s.approximate = (flags >> 5) & 1;
29592966
s.channels2 = (flags >> 6) & 0b1111;
29602967
s.cs_unit = (flags >> 10) & 3; // 0=unknown, 1=SOTDMA, 2=Carrier Sense
2968+
s.raim = (flags >> 12) & 3; // 0=unknown, 1=false, 2=true
2969+
s.dte = (flags >> 14) & 3; // 0=unknown, 1=ready, 2=not ready
2970+
s.assigned = (flags >> 16) & 3; // 0=unknown, 1=autonomous, 2=assigned
2971+
s.display = (flags >> 18) & 3; // 0=unknown, 1=false, 2=true
2972+
s.dsc = (flags >> 20) & 3; // 0=unknown, 1=false, 2=true
2973+
s.band = (flags >> 22) & 3; // 0=unknown, 1=false, 2=true
2974+
s.msg22 = (flags >> 24) & 3; // 0=unknown, 1=false, 2=true
2975+
s.off_position = (flags >> 26) & 3; // 0=unknown, 1=on position, 2=off position
2976+
s.maneuver = (flags >> 28) & 3; // 0=not available, 1=no special, 2=special
29612977

29622978
// Check for discrepancies and show error
29632979
if (s.validated !== s.validated2) {
@@ -5491,7 +5507,7 @@ function populateShipcard() {
54915507
document.getElementById("shipcard_sources").innerHTML = getStringfromGroup(ship.group_mask);
54925508

54935509
document.getElementById("shipcard_channels").innerHTML = getStringfromChannels(ship.channels);
5494-
document.getElementById("shipcard_type").innerHTML = getTypeVal(ship);
5510+
document.getElementById("shipcard_type").innerHTML = getTypeVal(ship) + ' <i class="info_icon shipcard-tech-icon" id="shipcard_tech_info" onclick="event.stopPropagation(); toggleTechPopover()" title="Technical details"></i>';
54955511
document.getElementById("shipcard_shiptype").innerHTML = getShipTypeVal(ship.shiptype);
54965512
document.getElementById("shipcard_status").innerHTML = getStatusVal(ship);
54975513
document.getElementById("shipcard_last_signal").innerHTML = getDeltaTimeVal(ship.last_signal);
@@ -5507,7 +5523,79 @@ function populateShipcard() {
55075523

55085524
updateShipcardTrackOption(card_mmsi);
55095525
updateMessageButton();
5526+
updateTechDetails(ship);
5527+
5528+
}
5529+
5530+
function updateTechDetails(ship) {
5531+
// Helper to format flag values
5532+
const formatFlag = (value, trueText = "Yes", falseText = "No", unknownText = "-") => {
5533+
if (value === 0) return unknownText;
5534+
if (value === 1) return falseText;
5535+
if (value === 2) return trueText;
5536+
return unknownText;
5537+
};
55105538

5539+
// Update RAIM
5540+
document.getElementById("tech_raim").textContent = formatFlag(ship.raim);
5541+
5542+
// Update DTE
5543+
document.getElementById("tech_dte").textContent = formatFlag(ship.dte, "Not Ready", "Ready");
5544+
5545+
// Update Assigned Mode
5546+
document.getElementById("tech_assigned").textContent = formatFlag(ship.assigned, "Assigned", "Autonomous");
5547+
5548+
// Update Display
5549+
document.getElementById("tech_display").textContent = formatFlag(ship.display);
5550+
5551+
// Update DSC
5552+
document.getElementById("tech_dsc").textContent = formatFlag(ship.dsc);
5553+
5554+
// Update Band
5555+
document.getElementById("tech_band").textContent = formatFlag(ship.band, "Dual", "Single");
5556+
5557+
// Update MSG22
5558+
document.getElementById("tech_msg22").textContent = formatFlag(ship.msg22);
5559+
5560+
// Update Off Position
5561+
document.getElementById("tech_off_position").textContent = formatFlag(ship.off_position, "Off", "On");
5562+
5563+
// Update Maneuver
5564+
const maneuverText = ship.maneuver === 0 ? "-" : ship.maneuver === 1 ? "None" : "Special";
5565+
document.getElementById("tech_maneuver").textContent = maneuverText;
5566+
}
5567+
5568+
function toggleTechPopover() {
5569+
const popover = document.getElementById("tech_popover");
5570+
const icon = document.getElementById("shipcard_tech_info");
5571+
5572+
if (popover.style.display === "none" || !popover.style.display) {
5573+
// Position popover near the icon
5574+
const iconRect = icon.getBoundingClientRect();
5575+
const shipcardRect = document.getElementById("shipcard").getBoundingClientRect();
5576+
5577+
popover.style.display = "block";
5578+
popover.style.left = (iconRect.left - shipcardRect.left + 20) + "px";
5579+
popover.style.top = (iconRect.bottom - shipcardRect.top + 5) + "px";
5580+
5581+
// Close popover when clicking outside
5582+
setTimeout(() => {
5583+
document.addEventListener("click", closeTechPopover);
5584+
}, 0);
5585+
} else {
5586+
popover.style.display = "none";
5587+
document.removeEventListener("click", closeTechPopover);
5588+
}
5589+
}
5590+
5591+
function closeTechPopover(event) {
5592+
const popover = document.getElementById("tech_popover");
5593+
const icon = document.getElementById("shipcard_tech_info");
5594+
5595+
if (!popover.contains(event.target) && event.target !== icon) {
5596+
popover.style.display = "none";
5597+
document.removeEventListener("click", closeTechPopover);
5598+
}
55115599
}
55125600

55135601
function getCategory(plane) {
@@ -5847,11 +5935,25 @@ function displayShipcardIcons(type) {
58475935
continue;
58485936
}
58495937

5850-
// Show if within offset range or is More button
5851-
const isMoreButton = icon.querySelector('i').classList.contains('more_horiz_icon');
5852-
const isInRange = idx >= shipcardIconOffset[type] && idx < shipcardIconOffset[type] + shipcardIconMax;
5853-
icon.style.display = (isInRange || isMoreButton) ? "flex" : "none";
5854-
idx++;
5938+
// Check if this is the More button - always show it and don't count it
5939+
const isMoreButton = icon.querySelector('i')?.classList.contains('more_horiz_icon');
5940+
if (isMoreButton) {
5941+
icon.style.display = "flex";
5942+
continue;
5943+
}
5944+
5945+
// Check if realtime option should be hidden
5946+
const isRealtimeDisabled = icon.id === 'shipcard_realtime_option' && (typeof realtime_enabled === "undefined" || realtime_enabled === false);
5947+
5948+
if (isRealtimeDisabled) {
5949+
icon.style.display = "none";
5950+
// Don't increment idx, effectively removing it from the visible count
5951+
} else {
5952+
// Show if within offset range
5953+
const isInRange = idx >= shipcardIconOffset[type] && idx < shipcardIconOffset[type] + shipcardIconMax;
5954+
icon.style.display = isInRange ? "flex" : "none";
5955+
idx++;
5956+
}
58555957
}
58565958
}
58575959

@@ -5865,18 +5967,28 @@ function rotateShipcardIcons() {
58655967

58665968
function prepareShipcard() {
58675969
// Initialize offset/count objects if needed
5868-
shipcardIconOffset = shipcardIconOffset || { ship: 0, plane: 0 };
5970+
if (!shipcardIconOffset || typeof shipcardIconOffset !== 'object') {
5971+
shipcardIconOffset = { ship: 0, plane: 0 };
5972+
}
58695973
shipcardIconCount = shipcardIconCount || { ship: 0, plane: 0 };
58705974

58715975
// Count icons for each context
58725976
shipcardIconCount.ship = document.querySelectorAll('#shipcard_footer > div[data-context-type="ship"]').length;
58735977
shipcardIconCount.plane = document.querySelectorAll('#shipcard_footer > div[data-context-type="plane"]').length;
58745978

5979+
// Adjust count if realtime is disabled (exclude realtime option from count)
5980+
if (typeof realtime_enabled === "undefined" || realtime_enabled === false) {
5981+
const realtimeOption = document.getElementById('shipcard_realtime_option');
5982+
if (realtimeOption && realtimeOption.dataset.contextType === 'ship') {
5983+
shipcardIconCount.ship--;
5984+
}
5985+
}
5986+
58755987
// Add More button for each context if needed
5876-
if (shipcardIconCount.ship > shipcardIconMax + 1) {
5988+
if (shipcardIconCount.ship > shipcardIconMax) {
58775989
addShipcardItem('more_horiz', 'More', 'More options', 'rotateShipcardIcons()', 'ship');
58785990
}
5879-
if (shipcardIconCount.plane > shipcardIconMax + 1) {
5991+
if (shipcardIconCount.plane > shipcardIconMax) {
58805992
addShipcardItem('more_horiz', 'More', 'More options', 'rotateShipcardIcons()', 'plane');
58815993
}
58825994

@@ -7105,7 +7217,7 @@ function clearRealtimeFilter() {
71057217

71067218
function openRealtimeForMMSI(mmsi) {
71077219
// Check if realtime is enabled
7108-
if (typeof realtime_enabled === "undefined" || !realtime_enabled) {
7220+
if (!realtime_enabled) {
71097221
return;
71107222
}
71117223

@@ -7189,7 +7301,7 @@ function activateTab(b, a) {
71897301

71907302
if (a == "realtime") {
71917303
// Only initialize realtime viewer if realtime is enabled
7192-
if (typeof realtime_enabled !== "undefined" && realtime_enabled) {
7304+
if (realtime_enabled) {
71937305
// Only create a new viewer if one doesn't exist
71947306
if (!realtimeViewer) {
71957307
// Restore saved state if available
@@ -7278,7 +7390,7 @@ function selectTab() {
72787390
if (settings.tab == "settings") settings.tab = "stat";
72797391

72807392
// Check if requested tab is disabled and redirect to map
7281-
if (settings.tab == "realtime" && (typeof realtime_enabled === "undefined" || realtime_enabled === false)) {
7393+
if (settings.tab == "realtime" && !realtime_enabled) {
72827394
settings.tab = "map";
72837395
}
72847396
if (settings.tab == "log" && (typeof log_enabled === "undefined" || log_enabled === false)) {

Source/HTML/style.css

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,16 @@ td {
10991099
content: "-";
11001100
}
11011101

1102+
.shipcard-tech-icon {
1103+
font-size: 14px !important;
1104+
cursor: help;
1105+
opacity: 0.6;
1106+
display: inline-block !important;
1107+
vertical-align: text-top;
1108+
margin-left: 2px;
1109+
line-height: 1;
1110+
}
1111+
11021112
.shipcard-min-only {
11031113
display: none;
11041114
}
@@ -1117,6 +1127,42 @@ td {
11171127
flex-direction: row;
11181128
}
11191129

1130+
/* Technical details popover */
1131+
.tech-popover {
1132+
position: absolute;
1133+
background: var(--menu-background-color);
1134+
color: var(--menu-font-color);
1135+
border: 1px solid var(--border-color);
1136+
border-radius: 6px;
1137+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
1138+
z-index: 10000;
1139+
min-width: 200px;
1140+
max-width: 300px;
1141+
font-size: 12px;
1142+
padding: 8px 12px;
1143+
}
1144+
1145+
.tech-popover > div {
1146+
display: flex;
1147+
justify-content: space-between;
1148+
padding: 4px 0;
1149+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
1150+
}
1151+
1152+
.tech-popover > div:last-child {
1153+
border-bottom: none;
1154+
}
1155+
1156+
.tech-popover > div > span:first-child {
1157+
font-weight: 500;
1158+
opacity: 0.8;
1159+
}
1160+
1161+
.tech-popover > div > span:last-child {
1162+
font-weight: bold;
1163+
margin-left: 12px;
1164+
}
1165+
11201166
@media only screen and (max-width: 500px) {
11211167
.mapcard {
11221168
left: 0;

0 commit comments

Comments
 (0)