diff --git a/lib/boatData/GwBoatData.cpp b/lib/boatData/GwBoatData.cpp
index 80ea23d..91d1bc2 100644
--- a/lib/boatData/GwBoatData.cpp
+++ b/lib/boatData/GwBoatData.cpp
@@ -7,14 +7,14 @@
 #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;}
-        static int getType(const GwSatInfoList &x){ return GWTYPE_USER+1;}
+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; }
+    static int getType(const GwSatInfoList &x) { return GWTYPE_USER + 1; }
 };
 
 bool GwBoatItemBase::isValid(unsigned long now) const
@@ -34,63 +34,84 @@ GwBoatItemBase::GwBoatItemBase(String name, String format, unsigned long invalid
     this->name = name;
     this->format = format;
     this->type = 0;
-    this->lastUpdateSource=-1;
+    this->lastUpdateSource = -1;
 }
-size_t GwBoatItemBase::getJsonSize(){return JSON_OBJECT_SIZE(10);}
+size_t GwBoatItemBase::getJsonSize() { return JSON_OBJECT_SIZE(10); }
 #define STRING_SIZE 40
-GwBoatItemBase::StringWriter::StringWriter(){
-    buffer=new uint8_t[STRING_SIZE];
-    wp=buffer;
-    bufferSize=STRING_SIZE;
-    buffer [0]=0;
+GwBoatItemBase::StringWriter::StringWriter()
+{
+    buffer = new uint8_t[STRING_SIZE];
+    wp = buffer;
+    bufferSize = STRING_SIZE;
+    buffer[0] = 0;
 };
-const char *GwBoatItemBase::StringWriter::c_str() const{
+const char *GwBoatItemBase::StringWriter::c_str() const
+{
     return (const char *)buffer;
 }
-int GwBoatItemBase::StringWriter::getSize() const{
-    return wp-buffer;
+int GwBoatItemBase::StringWriter::getSize() const
+{
+    int rt=wp - buffer;
+    if (rt >= baseOffset) rt-=baseOffset;
+    return rt;
 }
-void GwBoatItemBase::StringWriter::reset(){
-    wp=buffer;
-    *wp=0;
+void GwBoatItemBase::StringWriter::setBase()
+{
+    baseOffset = wp - buffer;
 }
-void GwBoatItemBase::StringWriter::ensure(size_t size){
-    size_t fill=wp-buffer;
-    size_t newSize=bufferSize;
-    while ((fill+size) >= (newSize-1) ){
-        newSize+=STRING_SIZE;       
+bool GwBoatItemBase::StringWriter::baseFilled()
+{
+    return baseOffset != 0;
+}
+void GwBoatItemBase::StringWriter::reset()
+{
+    wp = buffer + baseOffset;
+    *wp = 0;
+}
+void GwBoatItemBase::StringWriter::ensure(size_t size)
+{
+    size_t fill = wp - buffer;
+    size_t newSize = bufferSize;
+    while ((fill + size) >= (newSize - 1))
+    {
+        newSize += STRING_SIZE;
     }
-    if (newSize != bufferSize){
-        uint8_t *newBuffer=new uint8_t[newSize];
-        memcpy(newBuffer,buffer,fill);
-        newBuffer[fill]=0;
+    if (newSize != bufferSize)
+    {
+        uint8_t *newBuffer = new uint8_t[newSize];
+        memcpy(newBuffer, buffer, fill);
+        newBuffer[fill] = 0;
         delete buffer;
-        buffer=newBuffer;
-        wp=newBuffer+fill;
-        bufferSize=newSize;
+        buffer = newBuffer;
+        wp = newBuffer + fill;
+        bufferSize = newSize;
     }
 }
-size_t GwBoatItemBase::StringWriter::write(uint8_t c){
+size_t GwBoatItemBase::StringWriter::write(uint8_t c)
+{
     ensure(1);
-    *wp=c;
+    *wp = c;
     wp++;
-    *wp=0;
+    *wp = 0;
     return 1;
 }
-size_t GwBoatItemBase::StringWriter::write(const uint8_t* s, size_t n){
+size_t GwBoatItemBase::StringWriter::write(const uint8_t *s, size_t n)
+{
     ensure(n);
-    memcpy(wp,s,n);
-    wp+=n;
-    *wp=0;
+    memcpy(wp, s, n);
+    wp += n;
+    *wp = 0;
     return n;
 }
-template<class T> GwBoatItem<T>::GwBoatItem(String name,String formatInfo,unsigned long invalidTime,GwBoatItemMap *map):
-    GwBoatItemBase(name,formatInfo,invalidTime){
-            T dummy;
-            this->type=GwBoatItemTypes::getType(dummy);
-            if (map){
-                (*map)[name]=this;
-            }
+template <class T>
+GwBoatItem<T>::GwBoatItem(String name, String formatInfo, unsigned long invalidTime, GwBoatItemMap *map) : GwBoatItemBase(name, formatInfo, invalidTime)
+{
+    T dummy;
+    this->type = GwBoatItemTypes::getType(dummy);
+    if (map)
+    {
+        (*map)[name] = this;
+    }
 }
 
 template <class T>
@@ -140,59 +161,76 @@ void GwBoatItem<T>::toJsonDoc(GwJsonDocument *doc, unsigned long minTime)
     o[F("format")] = format;
 }
 
+class WriterWrapper
+{
+    GwBoatItemBase::StringWriter *writer = NULL;
 
-class WriterWrapper{
-    GwBoatItemBase::StringWriter *writer=NULL;
-    public:
-        WriterWrapper(GwBoatItemBase::StringWriter *w){
-            writer=w;
-        }
-        size_t write(uint8_t c){
-            if (! writer) return 0;
-            return writer->write(c);
-        }
-        size_t write(const uint8_t* s, size_t n){
-            if (! writer) return 0;
-            return writer->write(s,n);
-        }
+public:
+    WriterWrapper(GwBoatItemBase::StringWriter *w)
+    {
+        writer = w;
+    }
+    size_t write(uint8_t c)
+    {
+        if (!writer)
+            return 0;
+        return writer->write(c);
+    }
+    size_t write(const uint8_t *s, size_t n)
+    {
+        if (!writer)
+            return 0;
+        return writer->write(s, n);
+    }
 };
 typedef ARDUINOJSON_NAMESPACE::TextFormatter<WriterWrapper> GwTextWriter;
 
-static void writeToString(GwTextWriter *writer,const double &value){
+static void writeToString(GwTextWriter *writer, const double &value)
+{
     writer->writeFloat(value);
 }
-static void writeToString(GwTextWriter *writer,const uint16_t &value){
+static void writeToString(GwTextWriter *writer, const uint16_t &value)
+{
     writer->writeInteger(value);
 }
-static void writeToString(GwTextWriter *writer,const uint32_t &value){
+static void writeToString(GwTextWriter *writer, const uint32_t &value)
+{
     writer->writeInteger(value);
 }
-static void writeToString(GwTextWriter *writer,const int16_t &value){
+static void writeToString(GwTextWriter *writer, const int16_t &value)
+{
     writer->writeInteger(value);
 }
-static void writeToString(GwTextWriter *writer,GwSatInfoList &value){
+static void writeToString(GwTextWriter *writer, GwSatInfoList &value)
+{
     writer->writeInteger(value.getNumSats());
 }
 
 template <class T>
-void GwBoatItem<T>::fillString(){
-    bool valid=isValid();
-    if (writer.getSize() && (valid == lastStringValid)) return;
-    lastStringValid=valid;
+void GwBoatItem<T>::fillString()
+{
+    bool valid = isValid();
+    if (writer.getSize() && (valid == lastStringValid))
+        return;
+    lastStringValid = valid;
     writer.reset();
     WriterWrapper wrapper(&writer);
     GwTextWriter stringWriter(wrapper);
-    stringWriter.writeRaw(name.c_str());
-    stringWriter.writeChar(',');
-    stringWriter.writeInteger(valid?1:0);
+    if (!writer.baseFilled())
+    {
+        stringWriter.writeRaw(name.c_str());
+        stringWriter.writeChar(',');
+        stringWriter.writeRaw(format.c_str());
+        stringWriter.writeChar(',');
+        writer.setBase();
+    }
+    stringWriter.writeInteger(valid ? 1 : 0);
     stringWriter.writeChar(',');
     stringWriter.writeInteger(lastSet);
     stringWriter.writeChar(',');
     stringWriter.writeInteger(lastUpdateSource);
     stringWriter.writeChar(',');
-    stringWriter.writeRaw(format.c_str());
-    stringWriter.writeChar(',');
-    writeToString(&stringWriter,data);
+    writeToString(&stringWriter, data);
 }
 
 template class GwBoatItem<double>;
@@ -229,8 +267,7 @@ void GwSatInfoList::update(GwSatInfo entry)
     sats.push_back(entry);
 }
 
-GwBoatDataSatList::GwBoatDataSatList(String name, String formatInfo, unsigned long invalidTime , GwBoatItemMap *map) : 
-        GwBoatItem<GwSatInfoList>(name, formatInfo, invalidTime, map) {}
+GwBoatDataSatList::GwBoatDataSatList(String name, String formatInfo, unsigned long invalidTime, GwBoatItemMap *map) : GwBoatItem<GwSatInfoList>(name, formatInfo, invalidTime, map) {}
 
 bool GwBoatDataSatList::update(GwSatInfo info, int source)
 {
@@ -256,93 +293,119 @@ void GwBoatDataSatList::toJsonDoc(GwJsonDocument *doc, unsigned long minTime)
     GwBoatItem<GwSatInfoList>::toJsonDoc(doc, minTime);
 }
 
-GwBoatData::GwBoatData(GwLog *logger){
-    this->logger=logger;
+GwBoatData::GwBoatData(GwLog *logger)
+{
+    this->logger = logger;
 }
-GwBoatData::~GwBoatData(){
+GwBoatData::~GwBoatData()
+{
     GwBoatItemBase::GwBoatItemMap::iterator it;
-    for (it=values.begin() ; it != values.end();it++){
+    for (it = values.begin(); it != values.end(); it++)
+    {
         delete it->second;
     }
 }
 
-template<class T> GwBoatItem<T> *GwBoatData::getOrCreate(T initial, GwBoatItemNameProvider *provider)
+template <class T>
+GwBoatItem<T> *GwBoatData::getOrCreate(T initial, GwBoatItemNameProvider *provider)
 {
-    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());
+    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 (GwBoatItem<T> *)(it->second);
     }
-    GwBoatItem<T> *rt=new GwBoatItem<T>(name,
-        provider->getBoatItemFormat(),
-        provider->getInvalidTime(),
-        &values);
+    GwBoatItem<T> *rt = new GwBoatItem<T>(name,
+                                          provider->getBoatItemFormat(),
+                                          provider->getInvalidTime(),
+                                          &values);
     rt->update(initial);
-    LOG_DEBUG(GwLog::LOG,"creating boatItem %s, type %d",
-        name.c_str(),rt->getCurrentType());
+    LOG_DEBUG(GwLog::LOG, "creating boatItem %s, type %d",
+              name.c_str(), rt->getCurrentType());
     return rt;
 }
-template<class T> bool GwBoatData::update(const T value,int source,GwBoatItemNameProvider *provider){
-    GwBoatItem<T> *item=getOrCreate(value,provider);
-    if (! item) return false;
-    return item->update(value,source);
+template <class T>
+bool GwBoatData::update(const 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;
+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();
+String GwBoatData::toJson() const
+{
+    unsigned long minTime = millis();
     GwBoatItemBase::GwBoatItemMap::const_iterator it;
-    size_t count=0;
-    size_t elementSizes=0;
-    for (it=values.begin() ; it != values.end();it++){
+    size_t count = 0;
+    size_t elementSizes = 0;
+    for (it = values.begin(); it != values.end(); it++)
+    {
         count++;
-        elementSizes+=it->second->getJsonSize();
+        elementSizes += it->second->getJsonSize();
     }
-    int sz=JSON_OBJECT_SIZE(count)+elementSizes+10;
-    LOG_DEBUG(GwLog::DEBUG,"size for boatData: %d",sz);
+    int sz = JSON_OBJECT_SIZE(count) + elementSizes + 10;
+    LOG_DEBUG(GwLog::DEBUG, "size for boatData: %d", sz);
     GwJsonDocument json(sz);
-    for (it=values.begin() ; it != values.end();it++){
-        it->second->toJsonDoc(&json,minTime);
+    for (it = values.begin(); it != values.end(); it++)
+    {
+        it->second->toJsonDoc(&json, minTime);
     }
     String buf;
-    serializeJson(json,buf);
+    serializeJson(json, buf);
     return buf;
 }
-String GwBoatData::toString(){
+String GwBoatData::toString()
+{
     String rt;
-    for (auto it=values.begin() ; it != values.end();it++){
-        rt+=it->second->getDataString();
-        rt+="\n";
+    rt.reserve(values.size() * 80);
+    for (auto it = values.begin(); it != values.end(); it++)
+    {
+        rt += it->second->getDataString();
+        rt += "\n";
     }
     return rt;
 }
-bool GwBoatData::isValid(String name){
-    auto it=values.find(name);
-    if (it == values.end()) return false;
+bool GwBoatData::isValid(String name)
+{
+    auto it = values.find(name);
+    if (it == values.end())
+        return false;
     return it->second->isValid();
 }
-GwBoatItemBase* GwBoatData::getBase(String name){
-    auto it=values.find(name);
-    if (it == values.end()) return NULL;
+GwBoatItemBase *GwBoatData::getBase(String name)
+{
+    auto it = values.find(name);
+    if (it == values.end())
+        return NULL;
     return it->second;
 }
-double GwBoatData::getDoubleValue(String name,double defaultv){
-    auto it=values.find(name);
-    if (it == values.end()) return defaultv;
-    if (! it->second->isValid()) return defaultv;
+double GwBoatData::getDoubleValue(String name, double defaultv)
+{
+    auto it = values.find(name);
+    if (it == values.end())
+        return defaultv;
+    if (!it->second->isValid())
+        return defaultv;
     return it->second->getDoubleValue();
 }
 double formatCourse(double cv)
@@ -354,8 +417,9 @@ double formatCourse(double cv)
         rt += 360;
     return rt;
 }
-double formatDegToRad(double deg){
-    return deg/180.0 * M_PI;
+double formatDegToRad(double deg)
+{
+    return deg / 180.0 * M_PI;
 }
 double formatWind(double cv)
 {
@@ -378,20 +442,24 @@ double mtr2nm(double m)
     return m / 1852.0;
 }
 
-bool convertToJson(const GwSatInfoList &si,JsonVariant &variant){
+bool convertToJson(const GwSatInfoList &si, JsonVariant &variant)
+{
     return variant.set(si.getNumSats());
 }
 
 #ifdef _UNDEF
 #include <ArduinoJson/Json/TextFormatter.hpp>
 
-class XWriter{
-    public:
-     void write(uint8_t c) {
+class XWriter
+{
+public:
+    void write(uint8_t c)
+    {
     }
 
-  void write(const uint8_t* s, size_t n) {
-  }   
+    void write(const uint8_t *s, size_t n)
+    {
+    }
 };
 static XWriter xwriter;
 ARDUINOJSON_NAMESPACE::TextFormatter<XWriter> testWriter(xwriter);
diff --git a/lib/boatData/GwBoatData.h b/lib/boatData/GwBoatData.h
index 855491d..8f6adb6 100644
--- a/lib/boatData/GwBoatData.h
+++ b/lib/boatData/GwBoatData.h
@@ -14,6 +14,7 @@ class GwBoatItemBase{
             uint8_t *buffer =NULL;
             uint8_t *wp=NULL;
             size_t bufferSize=0;
+            size_t baseOffset=0;
             void ensure(size_t size);
             public:
                 StringWriter();
@@ -21,6 +22,8 @@ class GwBoatItemBase{
                 size_t write(const uint8_t* s, size_t n);
                 const char * c_str() const;
                 int getSize() const;
+                void setBase();
+                bool baseFilled();
                 void reset();
         };
         static const unsigned long INVALID_TIME=60000;
diff --git a/lib/statistics/GwStatistics.h b/lib/statistics/GwStatistics.h
index 2feb232..b2efec8 100644
--- a/lib/statistics/GwStatistics.h
+++ b/lib/statistics/GwStatistics.h
@@ -119,6 +119,6 @@ class TimeMonitor{
       current[index]=now;
       int64_t currentv=now-sv;
       if ((now-start) > max) max=now-start;
-      times[index-1]->add(currentv);
+      times[index]->add(currentv);
     }
 };
diff --git a/web/index.js b/web/index.js
index bc627ca..afd1ecb 100644
--- a/web/index.js
+++ b/web/index.js
@@ -1205,10 +1205,10 @@ function parseBoatDataLine(line){
     let rt={};
     let parts=line.split(',');
     rt.name=parts[0];
-    rt.valid=parts[1] === '1';
-    rt.update=parseInt(parts[2]);
-    rt.source=parseInt(parts[3]);
-    rt.format=parts[4];
+    rt.valid=parts[2] === '1';
+    rt.update=parseInt(parts[3]);
+    rt.source=parseInt(parts[4]);
+    rt.format=parts[1];
     rt.value=parts[5];
     return rt;
 }