Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
fd55a08
tuned widget layout
quantenschaum Oct 13, 2025
1311764
revised wind graphics and wind display
quantenschaum Oct 13, 2025
a82ff92
tuned widget configuration
quantenschaum Oct 13, 2025
2f2c7d3
added options to position formatter
quantenschaum Oct 13, 2025
8100d16
added float formatter, revised decimal formatter
quantenschaum Oct 13, 2025
bf770ca
removed OLC
quantenschaum Oct 13, 2025
4f4bd62
added distance and speed units
quantenschaum Oct 13, 2025
5c66f0b
revised formatters, added fahrenheit
quantenschaum Oct 13, 2025
09ddfe1
wind graphics as angle when ending in A
quantenschaum Oct 13, 2025
dc55da2
let formatters handle default value
quantenschaum Oct 13, 2025
2deacb3
added GNSS status widget
quantenschaum Oct 13, 2025
a505e7b
fixed position formatter
quantenschaum Oct 13, 2025
3685b03
Merge branch 'master-wv' into widgets+
quantenschaum Oct 25, 2025
bd355b4
make kind of depth selectable
quantenschaum Oct 25, 2025
ddee41b
replace : by raised colon for nicer time format
quantenschaum Oct 25, 2025
9f3b614
fixed decimal formatter and added parameter descriptions
quantenschaum Oct 25, 2025
e8d300c
reworked float formatter
quantenschaum Oct 25, 2025
04ac96a
reworked distance formatter
quantenschaum Oct 25, 2025
eb4ec47
adjusted flex depth widget
quantenschaum Oct 25, 2025
8b99351
Merge branch 'master-wv' into widgets+
quantenschaum Oct 25, 2025
5095e47
added tabular-nums for widgets
quantenschaum Oct 25, 2025
845a4fd
moved replacements into value fragment
quantenschaum Oct 26, 2025
4e08d48
added flex-basis auto
quantenschaum Oct 26, 2025
58458a1
prevent widgets from collapsing during editing
quantenschaum Oct 29, 2025
d602b9c
adjusted borders on nav page to 2px
quantenschaum Oct 29, 2025
8629162
added/adjusted formatter docs
quantenschaum Oct 29, 2025
48ea489
Merge branch 'master-wv' into widgets+
quantenschaum Feb 23, 2026
d063e00
switched widget styles to use CSS variables for improved consistency
quantenschaum Feb 23, 2026
146720d
AIS widget styling to use flexbox for improved layout
quantenschaum Feb 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions docs/hints/en_layouts.html
Original file line number Diff line number Diff line change
Expand Up @@ -117,21 +117,33 @@ <h2><a name="formatter" id="formatter"></a>Formatter</h2>
fractional digits are only shown if the value has a fractional part</td>
<td>same as formatDecimal</td>
</tr>
<tr>
<td>formatFloat</td>
<td>format as floating-point number</td>
<td>digits: number of digits in total, negative values indicate signed numbers inserting a placeholder for the sign if necessary<br/>
maxFrac: max. number of fractional digits<br/>
leadingZeroes: show leading zeroes<br/>
</td>
</tr>
<tr>
<td>formatDistance</td>
<td>distance in nm/m/km</td>
<td>unit:<br>
nm - distance in nm<br>
m- distance in m instead of nm<br>
km - distance&nbsp; in km instead of nm</td>
<td>distance in selected unit</td>
<td>unit: distance unit<br>
nm - nautical miles<br>
m - meters<br>
km - Kilometers<br>
ft - feet<br>
yd - Yards<br>
digits: number of digits in total (see formatFloat)<br/>
maxFrac: max. number of fractional digits (see formatFloat)</td>
</tr>
<tr>
<td>formatSpeed</td>
<td>speed in kn|m/s|km/h</td>
<td>unit:<br>
ms - m/s instead of kn<br>
kmh - km/h instead of kn<br>
kn - kn</td>
<td>speed in selected unit</td>
<>unit: speed unit<br>
kn - Knots<br>
ms or m/s - meters per second<br>
kmh or km/h - kilometers per hour</td>
</tr>
<tr>
<td>formatDirection</td>
Expand Down
50 changes: 31 additions & 19 deletions docs/hints/layouts.html
Original file line number Diff line number Diff line change
Expand Up @@ -121,71 +121,83 @@ <h2><a name="formatter" id="formatter"></a>Formatierer (formatter)</h2>
nicht ganzzahlige Werte dargestellt.</td>
<td>wie bei formatDecimal</td>
</tr>
<tr>
<td>formatFloat</td>
<td>Formatierung als Gleitkommazahl</td>
<td>digits: Anzahl der Stellen insgesamt, negative Werte zeigen Zahlen mit potenziell negativem Vorzeichen an (signed, fügt Vorzeichenplatzhalter ein)<br/>
maxFrac: maximale Anzahl Nachkommastellen<br/>
leadingZeroes: führende Nullen anzeigen<br/>
</td>
</tr>
<tr>
<td>formatDistance</td>
<td>Entfernung in nm|m|km</td>
<td>unit:<br>
nm - Enterfnung in nm<br>
m - Entfernung in m statt nm<br>
km - Entfernung in km statt nm</td>
<td>Entfernung in der gewählten Einheit</td>
<td>unit: Entfernungseinheit<br>
nm - Seemeilen (nautical miles)<br>
m - Meter<br>
km - Kilometer<br>
ft - Fuß (foot)<br>
yd - Yards<br>
digits: Anzahl der Stellen (siehe formatFloat)<br/>
maxFrac: maximale Anzahl Nachkommastellen (siehe formatFloat)</td>
</tr>
<tr>
<td>formatSpeed</td>
<td>Geschwindigkeit in kn|m/s|km/h</td>
<td>Geschwindigkeit in der gewählten Einheit</td>
<td>unit:<br>
kn - knoten<br>
ms - m/s statt kn<br>
kmh - km/h statt kn</td>
kn - Knoten<br>
ms oder m/s - Meter pro Sekunde<br>
kmh oder km/h - Kilometer pro Stunde</td>
</tr>
<tr>
<td>formatDirection</td>
<td>Formatiere einen Gradwert</td>
<td>inputRadian: - Input in rad statt Grad<br>
<td>Richtung als Gradwert</td>
<td>inputRadian: Input in rad statt Grad<br>
range180: zeige +/- 180° statt 0...360°<br>
leadingZero: zeige immer 3 Stellen</td>
</tr>
<tr>
<td>formatDirection360</td>
<td>Formatiere einen Gradwert</td>
<td>Richtung als Gradwert immer im Bereich 0...360°</td>
<td>leadingZero: zeige immer 3 Stellen</td>
</tr>
<tr>
<td>formatTime</td>
<td>Formatiere einen Zeitwert (Wert muss intern ein Date Wert sein)
<td>Formatiere einen Zeitwert (nur auf Zeit/Datumswerte anwendbar)
(hh:mm:ss)</td>
<td><br>
<td>seconds: Sekunden anzeigen<br>
</td>
</tr>
<tr>
<td>formatClock</td>
<td>Formatiere einen Zeitwert (Wert muss intern ein Date Wert sein)
<td>Formatiere einen Zeitwert (nur auf Zeit/Datumswerte anwendbar)
(hh:mm)</td>
<td><br>
</td>
</tr>
<tr>
<td>formatDateTime</td>
<td>Formatiere Datum und Uhrzeit (Wert muss intern ein Date Wert sein)</td>
<td>Formatiere Datum und Uhrzeit (nur auf Zeit/Datumswerte anwendbar)</td>
<td><br>
</td>
</tr>
<tr>
<td>formatDate</td>
<td>Formatiere Datum (Wert muss intern ein Date Wert sein)</td>
<td>Formatiere Datum (nur auf Zeit/Datumswerte anwendbar)</td>
<td><br>
</td>
</tr>
<tr>
<td>formatString</td>
<td>gibt den Input unverändert weiter</td>
<td>direkte Umwandlung in einen String durch JavaScript</td>
<td><br>
</td>
</tr>
<tr>
<td>formatTemperature</td>
<td>Formatiere eine Temperatur (seit 20210106), Input in Kelvin</td>
<td>unit:<br>
celsius, kelvin</td>
celsius, kelvin, fahrenheit</td>
</tr>
<tr>
<td>formatPressure</td>
Expand Down
24 changes: 23 additions & 1 deletion server/avnav_nmea.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ class NMEAParser(object):
K_TIME=Key('time','the received GPS time',signalK='navigation.datetime')
K_SATUSED=Key('satUsed', 'number of Sats in use',signalK='navigation.gnss.satellites')
K_SATVIEW=Key('satInview', 'number of Sats in view',signalK='navigation.gnss.satellitesInView.count')
K_FIX_TYPE=Key('fixType', 'GNSS fix type (1=none, 2=2D, 3=3D)')
K_FIX_QUALITY=Key('fixQuality', 'GNSS fix quality (0=invalid, 1=nonRTK, 2=SBAS/diff, 4=RTK fixed, 5=RTK float, 6=dead reckoning)')
K_PDOP=Key('PDOP', 'Position Dilution of Precision')
K_HDOP=Key('HDOP', 'Horizontal Dilution of Precision')
K_VDOP=Key('VDOP', 'Vertical Dilution of Precision')
#we will add the GPS base to all entries
GPS_DATA=[
K_LAT,
Expand All @@ -162,6 +167,11 @@ class NMEAParser(object):
K_TIME,
K_SATVIEW,
K_SATUSED,
K_FIX_TYPE,
K_FIX_QUALITY,
K_PDOP,
K_HDOP,
K_VDOP,
Key('transducers.*','transducer data from xdr'),
K_HDGC,
K_HDGM,
Expand Down Expand Up @@ -382,9 +392,14 @@ def parseData(self,data,source='internal',sourcePriority=DEFAULT_SOURCE_PRIORITY
try:
if tag=='GGA':
mode=int(darray[6] or 0) #quality
rt[self.K_FIX_QUALITY.key]=mode
if mode >= 1 and all(darray[i] for i in (2,3,4,5)):
rt[self.K_LAT.key]=self.nmeaPosToFloat(darray[2],darray[3])
rt[self.K_LON.key]=self.nmeaPosToFloat(darray[4],darray[5])
if darray[7]:
rt[self.K_SATUSED.key]=int(darray[7])
if darray[8]:
rt[self.K_HDOP.key]=float(darray[8])
self.addToNavData(rt,source=source,record=tag,timestamp=timestamp,priority=basePriority)
return True
if tag == 'GSA':
Expand All @@ -393,6 +408,13 @@ def parseData(self,data,source='internal',sourcePriority=DEFAULT_SOURCE_PRIORITY
used=store.getUsed()
AVNLog.debug("GSA: added %d used %d",an,used)
rt[self.K_SATUSED.key]=used
if darray[2]:
fix=int(darray[2])
if fix>1: rt[self.K_FIX_TYPE.key]=fix
for i,k in enumerate((self.K_PDOP,self.K_HDOP,self.K_VDOP)):
if not k: continue
dop=float(darray[15+i])
rt[k.key]=dop
self.addToNavData(rt,source=source,record=tag,timestamp=timestamp,priority=basePriority)
return True
if tag=='GSV':
Expand Down Expand Up @@ -930,4 +952,4 @@ def setValue(self,key, data, source='test', priority=1, record=None, timestamp=N
continue
print(line)
parser.parseData(line,source='test')
navdata.print_stats()
navdata.print_stats()
4 changes: 2 additions & 2 deletions viewer/components/CenterDisplayWidget.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const CenterDisplayWidget = (props) => {
}
return (
<WidgetFrame {...props} addClass="centerDisplayWidget" caption="Center" unit={undefined}>
{!small && <div className="widgetData">{Formatter.formatLonLats(props.centerPosition)}</div>}
{!small && <div className="widgetData Position">{Formatter.formatLonLats(props.centerPosition,props.positionFmt)}</div>}
{(measurePosition !== undefined) &&
<div className="widgetData">
<div className="label measure"></div>
Expand Down Expand Up @@ -99,4 +99,4 @@ CenterDisplayWidget.propTypes={
style: PropTypes.object,
mode: PropTypes.string
};
export default CenterDisplayWidget;
export default CenterDisplayWidget;
19 changes: 10 additions & 9 deletions viewer/components/DepthWidgetFlex.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const DepthDisplayFlex=(props)=>{
const iprops={...props};
iprops.unit=props.dunit;
iprops.formatter=(v)=>{
return formatter.formatDistance(v,props.dunit,props.digits,props.fillRight);
return formatter.formatDistance(v,props.dunit,props.digits,props.maxFrac);
}
if (iprops.offset && iprops.value != null){
iprops.value+=parseFloat(iprops.offset );
Expand Down Expand Up @@ -85,18 +85,19 @@ DepthDisplayFlex.predefined={
displayName:"unit",
list:DEPTH_UNITS,
default:'m',
description:'Select the unit for the depth display'},
description:'Select the unit for the depth display'
},
digits:{
type:'NUMBER',
default:0,
description:'minimal number of digits for the depth display, set to 0 to let the system choose',
description:'minimal number of digits for the depth display, 0=global default',
list:[0,10]
},
fillRight:{
type:'BOOLEAN',
default: false,
description: 'let the fractional part extend to have the requested number of digits',
condition: {digits:(all,dv)=>dv>0}
maxFrac:{
type:'NUMBER',
default:1,
description: 'max. number of decimal places',
list:[0,10]
},
offset: new EditableFloatParameterUI({
name:'offset',
Expand Down Expand Up @@ -155,4 +156,4 @@ DepthBelowWater.predefined={
value: keys.nav.gps.depthBelowWaterline
},
caption:'DBW'
}
}
34 changes: 22 additions & 12 deletions viewer/components/DirectWidget.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/**
* Created by andreas on 23.02.16.
*/

Expand All @@ -7,6 +7,7 @@ import PropTypes from 'prop-types';
import Value from './Value.jsx';
import {WidgetFrame, WidgetProps} from "./WidgetBase";
import {useStringsChanged} from "../hoc/Resizable";
import {concatsp} from "../util/helper";

const DirectWidget=(wprops)=>{
let props;
Expand All @@ -16,22 +17,31 @@ const DirectWidget=(wprops)=>{
props={...wprops,value:'Error: '+e}
}
let val;
let vdef=props.default||'0';
if (props.value !== undefined) {
if (props.minValue != null && parseFloat(props.value) < props.minValue)val=vdef;
else if(props.maxValue != null && parseFloat(props.value) > props.maxValue)val=vdef;
else val=props.formatter?props.formatter(props.value):vdef+"";
}
else{
if (! isNaN(vdef) && props.formatter) val=props.formatter(vdef);
else val=vdef+"";
let vdef=props.default||'---';
try {
if (props.value != null) {
let outOfRange=0;
if(parseFloat(props.value) < props.minValue) outOfRange=-1;
if(parseFloat(props.value) > props.maxValue) outOfRange=+1;
if(outOfRange) {
vdef=props.formatter?props.formatter(null):vdef; // placeholder with correct with
if (outOfRange<0) vdef=vdef.replace(/./g,'<'); // underflow
if (outOfRange>0) vdef=vdef.replace(/./g,'>'); // overflow
throw new Error();
}
}
val=props.formatter?props.formatter(props.value):props.value;
val=(val==null?'':''+val)||vdef;
}catch(error){
val=vdef;
}
const display={
value:val
};
const resizeSequence=useStringsChanged(display,wprops.mode==='gps')
if(props.addClass) props.addClass=concatsp(props.addClass,'DirectWidget');
return (
<WidgetFrame {...props} addClass="DirectWidget" resizeSequence={resizeSequence} >
<WidgetFrame {...props} resizeSequence={resizeSequence} >
<div className='widgetData'>
<Value value={val}/>
</div>
Expand Down Expand Up @@ -59,4 +69,4 @@ DirectWidget.editableParameters={
value: true
};

export default DirectWidget;
export default DirectWidget;
9 changes: 6 additions & 3 deletions viewer/components/Value.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import PropTypes from 'prop-types';
*/
const Value=function(props){
if (! props.value) return null;
let prefix=(props.value+"").replace(/[^ ].*/,'');
let remain=(props.value+"").replace(/^ */,'');
let val=''+props.value;
val=val.replaceAll('-','\u2012'); // replace - by digit wide hyphen (figure dash)
val=val.replaceAll(':','\uA789'); // replace : with raised colon, looks better in time format 00:00
let prefix=val.replace(/[^ ].*/,'');
let remain=val.replace(/^ */,'');
return(
<React.Fragment>
<span className='valuePrefix'>{prefix.replace(/ /g,'0')}</span>
Expand All @@ -21,4 +24,4 @@ const Value=function(props){
Value.propTypes={
value: PropTypes.string
}
export default Value;
export default Value;
Loading
Loading