diff --git a/lib/boatData/GwBoatData.cpp b/lib/boatData/GwBoatData.cpp
index 533f931..467d71b 100644
--- a/lib/boatData/GwBoatData.cpp
+++ b/lib/boatData/GwBoatData.cpp
@@ -6,20 +6,46 @@ GwBoatData::GwBoatData(GwLog *logger){
 GwBoatData::~GwBoatData(){
     GwBoatItemBase::GwBoatItemMap::iterator it;
     for (it=values.begin() ; it != values.end();it++){
-        delete *it;
+        delete it->second;
     }
 }
 
-template<class T> GwBoatItem<T> *GwBoatData::getOrCreate(T dummy, String name, String format,
-                                                  unsigned long invalidTime)
+template<class T> GwBoatItem<T> *GwBoatData::getOrCreate(T initial, GwBoatItemNameProvider *provider)
 {
-    for (auto it=values.begin();it != values.end();it++){
-        if ((*it)->getName() == name){
-            return *it;
+    String name=provider->getBoatItemName();
+    auto it=values.find(name);
+    if (it != values.end()) {
+        int expectedType=GwBoatItemTypes::getType(initial);
+        if (expectedType != it->second->getCurrentType()){
+            LOG_DEBUG(GwLog::DEBUG,"invalid type for boat item %s, expected %d, got %d",
+                name.c_str(),expectedType,it->second->getCurrentType());
+            return NULL;
         }
+        return (GwBoatItem<T>*)(it->second);
     }
-    return new GwBoatItem<T>(name,format,invalidTime,&values);
+    GwBoatItem<T> *rt=new GwBoatItem<T>(GwBoatItemTypes::getType(initial), name,
+        provider->getBoatItemFormat(),
+        provider->getInvalidTime(),
+        &values);
+    rt->update(initial);
+    LOG_DEBUG(GwLog::LOG,"creating boatItem %s, type %d",
+        name.c_str(),rt->getCurrentType());
+    return rt;
 }
+template<class T> bool GwBoatData::update(T value,int source,GwBoatItemNameProvider *provider){
+    GwBoatItem<T> *item=getOrCreate(value,provider);
+    if (! item) return false;
+    return item->update(value,source);
+}
+template bool GwBoatData::update<double>(double value,int source,GwBoatItemNameProvider *provider);
+template<class T> T GwBoatData::getDataWithDefault(T defaultv, GwBoatItemNameProvider *provider){
+    auto it=values.find(provider->getBoatItemName());
+    if (it == values.end()) return defaultv;
+    int expectedType=GwBoatItemTypes::getType(defaultv);
+    if (expectedType != it->second->getCurrentType()) return defaultv;
+    return ((GwBoatItem<T> *)(it->second))->getDataWithDefault(defaultv);
+}
+template double GwBoatData::getDataWithDefault<double>(double defaultv, GwBoatItemNameProvider *provider);
 String GwBoatData::toJson() const {
     unsigned long minTime=millis();
     GwBoatItemBase::GwBoatItemMap::const_iterator it;
@@ -27,11 +53,13 @@ String GwBoatData::toJson() const {
     size_t elementSizes=0;
     for (it=values.begin() ; it != values.end();it++){
         count++;
-        elementSizes+=(*it)->getJsonSize();
+        elementSizes+=it->second->getJsonSize();
     }
-    DynamicJsonDocument json(JSON_OBJECT_SIZE(count)+elementSizes+10);
+    int sz=JSON_OBJECT_SIZE(count)+elementSizes+10;
+    LOG_DEBUG(GwLog::DEBUG,"size for boatData: %d",sz);
+    DynamicJsonDocument json(sz);
     for (it=values.begin() ; it != values.end();it++){
-        (*it)->toJsonDoc(&json,minTime);
+        it->second->toJsonDoc(&json,minTime);
     }
     String buf;
     serializeJson(json,buf);
diff --git a/lib/boatData/GwBoatData.h b/lib/boatData/GwBoatData.h
index d2e0db3..866d086 100644
--- a/lib/boatData/GwBoatData.h
+++ b/lib/boatData/GwBoatData.h
@@ -4,9 +4,21 @@
 #include "GwLog.h"
 #include <ArduinoJson.h>
 #include <Arduino.h>
-#include <vector>
+#include <map>
 #define GW_BOAT_VALUE_LEN 32
 #define GWSC(name) static constexpr const __FlashStringHelper* name=F(#name)
+#define GWTYPE_DOUBLE 1
+#define GWTYPE_UINT32 2
+#define GWTYPE_UINT16 3
+#define GWTYPE_INT16 4
+#define GWTYPE_USER 100
+class GwBoatItemTypes{
+    public:
+        static int getType(const uint32_t &x){return GWTYPE_UINT32;}
+        static int getType(const uint16_t &x){return GWTYPE_UINT16;}
+        static int getType(const int16_t &x){return GWTYPE_INT16;}
+        static int getType(const double &x){return GWTYPE_DOUBLE;}
+};
 class GwBoatItemBase{
     public:
         static const unsigned long INVALID_TIME=60000;
@@ -23,8 +35,9 @@ class GwBoatItemBase{
         GWSC(mtr2nm);
         GWSC(formatDop);
         GWSC(formatRot);
-        typedef std::vector<GwBoatItemBase*> GwBoatItemMap;
+        typedef std::map<String,GwBoatItemBase*> GwBoatItemMap;
     protected:
+        int type;
         unsigned long lastSet=0;
         unsigned long invalidTime=INVALID_TIME;
         String name;
@@ -34,6 +47,7 @@ class GwBoatItemBase{
             else lastSet=millis();
         }
     public:
+        int getCurrentType(){return type;}
         unsigned long getLastSet() const {return lastSet;}
         bool isValid(unsigned long now=0) const {
             if (lastSet == 0) return false;
@@ -46,13 +60,14 @@ class GwBoatItemBase{
             this->invalidTime=invalidTime;
             this->name=name;
             this->format=format;
+            this->type=0;
         }
         virtual ~GwBoatItemBase(){}
         void invalidate(){
             lastSet=0;
         }
         virtual void toJsonDoc(JsonDocument *doc, unsigned long minTime)=0;
-        virtual size_t getJsonSize(){return JSON_OBJECT_SIZE(15);}
+        virtual size_t getJsonSize(){return JSON_OBJECT_SIZE(10);}
         virtual int getLastSource()=0;
         virtual void refresh(unsigned long ts=0){uls(ts);}
         String getName(){return name;}
@@ -63,10 +78,11 @@ template<class T> class GwBoatItem : public GwBoatItemBase{
         T data;
         int lastUpdateSource;
     public:
-        GwBoatItem(String name,String formatInfo,unsigned long invalidTime=INVALID_TIME,GwBoatItemMap *map=NULL):
+        GwBoatItem(int type,String name,String formatInfo,unsigned long invalidTime=INVALID_TIME,GwBoatItemMap *map=NULL):
             GwBoatItemBase(name,formatInfo,invalidTime){
+            this->type=type;
             if (map){
-                map->push_back(this);
+                (*map)[name]=this;
             }
             lastUpdateSource=-1;
         }
@@ -77,7 +93,7 @@ template<class T> class GwBoatItem : public GwBoatItemBase{
                 //priority handling
                 //sources with lower ids will win
                 //and we will not overwrite their value
-                if (lastUpdateSource < source){
+                if (lastUpdateSource < source && lastUpdateSource >= 0){
                     return false;
                 }
             }
@@ -171,7 +187,8 @@ bool convertToJson(const GwSatInfoList &si,JsonVariant &variant);
 class GwBoatDataSatList : public GwBoatItem<GwSatInfoList>
 {
 public:
-    GwBoatDataSatList(String name, String formatInfo, unsigned long invalidTime = INVALID_TIME, GwBoatItemMap *map = NULL) : GwBoatItem<GwSatInfoList>(name, formatInfo, invalidTime, map) {}
+    GwBoatDataSatList(String name, String formatInfo, unsigned long invalidTime = INVALID_TIME, GwBoatItemMap *map = NULL) : 
+        GwBoatItem<GwSatInfoList>(GWTYPE_USER+1, name, formatInfo, invalidTime, map) {}
     bool update(GwSatInfo info, int source)
     {
         unsigned long now = millis();
@@ -205,8 +222,16 @@ public:
 
 };
 
+class GwBoatItemNameProvider
+{
+public:
+    virtual String getBoatItemName() = 0;
+    virtual String getBoatItemFormat() = 0;
+    virtual unsigned long getInvalidTime(){ return GwBoatItemBase::INVALID_TIME;}
+    virtual ~GwBoatItemNameProvider() {}
+};
 #define GWBOATDATA(type,name,time,fmt)  \
-    GwBoatItem<type> *name=new GwBoatItem<type>(F(#name),GwBoatItemBase::fmt,time,&values) ;
+    GwBoatItem<type> *name=new GwBoatItem<type>(GwBoatItemTypes::getType((type)0),F(#name),GwBoatItemBase::fmt,time,&values) ;
 #define GWSPECBOATDATA(clazz,name,time,fmt)  \
     clazz *name=new clazz(F(#name),GwBoatItemBase::fmt,time,&values) ;
 class GwBoatData{
@@ -254,43 +279,11 @@ class GwBoatData{
     public:
         GwBoatData(GwLog *logger);
         ~GwBoatData();
-        template<class T> GwBoatItem<T> *getOrCreate(T dummy,String name,String format,
-            unsigned long invalidTime=GwBoatItemBase::INVALID_TIME);
+        template<class T> GwBoatItem<T> *getOrCreate(T initial,GwBoatItemNameProvider *provider);
+        template<class T> bool update(T value,int source,GwBoatItemNameProvider *provider);
+        template<class T> T getDataWithDefault(T defaultv, GwBoatItemNameProvider *provider);
         String toJson() const;
 };
-/**
- * class for lazy creation of a boat item
- * once we have someone that knows the name for it
- * and providing fast access without searching all the time trough the map
- * xdr mappings implement such a provider
- */
-class GwBoatItemNameProvider
-{
-public:
-    virtual String getBoatItemName() = 0;
-    virtual String getBoatItemFormat() = 0;
-    virtual ~GwBoatItemNameProvider() {}
-};
-template<class T> class GwBoatItemHolder{
-    private:
-        GwBoatItem<T> *item=NULL;
-        GwBoatData *data;
-        unsigned long invalidTime=GwBoatItemBase::INVALID_TIME;
-    public:
-        GwBoatItemHolder(GwBoatData *data,unsigned long invalidTime=GwBoatItemBase::INVALID_TIME){
-            this->data=data;
-            this->invalidTime=invalidTime;
-        }
-        GwBoatItem<T> *getItem(GwBoatItemNameProvider *provider){
-                if (item) return item;
-                T dummy;
-                item=data->getOrCreate(dummy,
-                    provider->getBoatItemName() ,
-                    provider->getBoatItemFormat(),
-                    invalidTime);
-                return item;
-            }
-        GwBoatItem<T> *getItem(){return item;}       
-};
+
 
 #endif
\ No newline at end of file
diff --git a/lib/nmea2kto0183/N2kDataToNMEA0183.cpp b/lib/nmea2kto0183/N2kDataToNMEA0183.cpp
index e47459e..126bf2f 100644
--- a/lib/nmea2kto0183/N2kDataToNMEA0183.cpp
+++ b/lib/nmea2kto0183/N2kDataToNMEA0183.cpp
@@ -105,6 +105,10 @@ private:
             return false;
         return item->update(value,sourceId);
     }
+    bool updateDouble(GwXDRFoundMapping * mapping, double &value){
+        if (mapping->empty) return false;
+        return boatData->update(value,sourceId,mapping);
+    }
     
     unsigned long LastPosSend;
     unsigned long NextRMCSend;
@@ -1234,7 +1238,7 @@ private:
            return;
         }
         GwXDRFoundMapping mapping=xdrMappings->getMapping(XDRTEMP,(int)TemperatureSource,0,TemperatureInstance);
-        if (mapping.empty) return;
+        if (! updateDouble(&mapping,Temperature)) return;
         LOG_DEBUG(GwLog::DEBUG+1,"found temperature mapping %s",mapping.definition->toString().c_str());
         addToXdr(mapping.buildXdrEntry(Temperature));
         finalizeXdr();
@@ -1251,7 +1255,7 @@ private:
            return;
         }
         GwXDRFoundMapping mapping=xdrMappings->getMapping(XDRHUMIDITY,(int)HumiditySource,0,HumidityInstance);
-        if (mapping.empty) return;
+        if (! updateDouble(&mapping,ActualHumidity)) return;
         LOG_DEBUG(GwLog::DEBUG+1,"found humidity mapping %s",mapping.definition->toString().c_str());
         addToXdr(mapping.buildXdrEntry(ActualHumidity));
         finalizeXdr();
@@ -1268,7 +1272,7 @@ private:
             return; 
         }
         GwXDRFoundMapping mapping=xdrMappings->getMapping(XDRPRESSURE,(int)PressureSource,0,PressureInstance);
-        if (mapping.empty) return;
+        if (! updateDouble(&mapping,ActualPressure)) return;
         LOG_DEBUG(GwLog::DEBUG+1,"found pressure mapping %s",mapping.definition->toString().c_str());
         addToXdr(mapping.buildXdrEntry(ActualPressure));
         finalizeXdr();
diff --git a/lib/xdrmappings/GwXDRMappings.cpp b/lib/xdrmappings/GwXDRMappings.cpp
index 6ae224c..8b460c4 100644
--- a/lib/xdrmappings/GwXDRMappings.cpp
+++ b/lib/xdrmappings/GwXDRMappings.cpp
@@ -188,6 +188,10 @@ GwXDRMappingDef *GwXDRMappingDef::fromString(String s)
             return NULL;
         }
     }
+    if (rt->direction == GwXDRMappingDef::M_DISABLED || rt->xdrName == ""){
+        delete rt;
+        return NULL;
+    }
     return rt;
 }
 String GwXDRMappingDef::getTransducerName(int instance)
diff --git a/lib/xdrmappings/GwXDRMappings.h b/lib/xdrmappings/GwXDRMappings.h
index 8dffacc..9b79181 100644
--- a/lib/xdrmappings/GwXDRMappings.h
+++ b/lib/xdrmappings/GwXDRMappings.h
@@ -166,7 +166,7 @@ class GwXDRFoundMapping : public GwBoatItemNameProvider{
         String buildXdrEntry(double value);
         //boat Data info
         virtual String getBoatItemName(){
-            return getTransducerName();
+            return String("xdr")+getTransducerName();
         };
         virtual String getBoatItemFormat(){
             return "formatXdr"+type->xdrunit; //TODO: use the type def for the correct format
diff --git a/web/index.css b/web/index.css
index 67fd23a..0b8ce2f 100644
--- a/web/index.css
+++ b/web/index.css
@@ -242,7 +242,7 @@ body{
   }
   
   .dash {
-      width: 6em;
+      width: 6.5em;
       height: 4em;
       display: flex;
       flex-direction: column;
diff --git a/web/index.js b/web/index.js
index 0f67327..2b76e50 100644
--- a/web/index.js
+++ b/web/index.js
@@ -1025,6 +1025,15 @@ let valueFormatters = {
         u:'m'
     }
 }
+function resizeFont(el,reset,maxIt){
+    if (maxIt === undefined) maxIt=10;
+    if (! el) return;
+    if (reset) el.style.fontSize='';
+    while (el.scrollWidth > el.clientWidth && maxIt){
+        let next=parseFloat(window.getComputedStyle(el).fontSize)*0.9;
+        el.style.fontSize=next+"px";
+    }
+}
 function createDashboardItem(name, def, parent) {
     let frame = addEl('div', 'dash', parent);
     let title = addEl('span', 'dashTitle', frame, name);
@@ -1035,7 +1044,11 @@ function createDashboardItem(name, def, parent) {
     let footer = addEl('div','footer',frame);
     let src= addEl('span','source',footer);
     src.setAttribute('id','source_'+name);
-    addEl('span','unit',footer,fmt?fmt.u:'');
+    let u=fmt?fmt.u:'';
+    if (! fmt && def.format.match(/formatXdr/)){
+        u=def.format.replace(/formatXdr/,'');
+    }
+    addEl('span','unit',footer,u);
     return value;
 }
 function createDashboard() {
@@ -1057,9 +1070,14 @@ function sourceName(v){
     return "---";
 }
 function updateDashboard(data) {
+    let frame = document.getElementById('dashboardPage');
     for (let n in data) {
         let de = document.getElementById('data_' + n);
+        if (! de && frame){
+            de=createDashboardItem(n,data[n],frame);   
+        }
         if (de) {
+            let newContent='----';
             if (data[n].valid) {
                 let formatter;
                 if (data[n].format && data[n].format != "NULL") {
@@ -1067,26 +1085,38 @@ function updateDashboard(data) {
                     formatter = valueFormatters[key];
                 }
                 if (formatter) {
-                    de.textContent = formatter.f(data[n].value);
+                    newContent = formatter.f(data[n].value);
                 }
                 else {
                     let v = parseFloat(data[n].value);
                     if (!isNaN(v)) {
                         v = v.toFixed(3)
-                        de.textContent = v;
+                        newContent = v;
                     }
                     else {
-                        de.textContent = data[n].value;
+                        newContent = data[n].value;
                     }
                 }
             }
-            else de.textContent = "---";
+            else newContent = "---";
+            if (newContent !== de.textContent){
+                de.textContent=newContent;
+                resizeFont(de,true);
+            }
         }
         let src=document.getElementById('source_'+n);
         if (src){
             src.textContent=sourceName(data[n].source);
         }
     }
+    forEl('.dashValue',function(el){
+        let id=el.getAttribute('id');
+        if (id){
+            if (! data[id.replace(/^data_/,'')]){
+                el.parentElement.remove();
+            }
+        }
+    });
 }
 
 window.setInterval(update, 1000);