Merge branch 'wellenvogel:master' into feature/env2
This commit is contained in:
commit
df126c9f34
|
@ -6,20 +6,46 @@ GwBoatData::GwBoatData(GwLog *logger){
|
||||||
GwBoatData::~GwBoatData(){
|
GwBoatData::~GwBoatData(){
|
||||||
GwBoatItemBase::GwBoatItemMap::iterator it;
|
GwBoatItemBase::GwBoatItemMap::iterator it;
|
||||||
for (it=values.begin() ; it != values.end();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,
|
template<class T> GwBoatItem<T> *GwBoatData::getOrCreate(T initial, GwBoatItemNameProvider *provider)
|
||||||
unsigned long invalidTime)
|
|
||||||
{
|
{
|
||||||
for (auto it=values.begin();it != values.end();it++){
|
String name=provider->getBoatItemName();
|
||||||
if ((*it)->getName() == name){
|
auto it=values.find(name);
|
||||||
return *it;
|
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 {
|
String GwBoatData::toJson() const {
|
||||||
unsigned long minTime=millis();
|
unsigned long minTime=millis();
|
||||||
GwBoatItemBase::GwBoatItemMap::const_iterator it;
|
GwBoatItemBase::GwBoatItemMap::const_iterator it;
|
||||||
|
@ -27,11 +53,13 @@ String GwBoatData::toJson() const {
|
||||||
size_t elementSizes=0;
|
size_t elementSizes=0;
|
||||||
for (it=values.begin() ; it != values.end();it++){
|
for (it=values.begin() ; it != values.end();it++){
|
||||||
count++;
|
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++){
|
for (it=values.begin() ; it != values.end();it++){
|
||||||
(*it)->toJsonDoc(&json,minTime);
|
it->second->toJsonDoc(&json,minTime);
|
||||||
}
|
}
|
||||||
String buf;
|
String buf;
|
||||||
serializeJson(json,buf);
|
serializeJson(json,buf);
|
||||||
|
|
|
@ -4,9 +4,21 @@
|
||||||
#include "GwLog.h"
|
#include "GwLog.h"
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <vector>
|
#include <map>
|
||||||
#define GW_BOAT_VALUE_LEN 32
|
#define GW_BOAT_VALUE_LEN 32
|
||||||
#define GWSC(name) static constexpr const __FlashStringHelper* name=F(#name)
|
#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{
|
class GwBoatItemBase{
|
||||||
public:
|
public:
|
||||||
static const unsigned long INVALID_TIME=60000;
|
static const unsigned long INVALID_TIME=60000;
|
||||||
|
@ -23,8 +35,9 @@ class GwBoatItemBase{
|
||||||
GWSC(mtr2nm);
|
GWSC(mtr2nm);
|
||||||
GWSC(formatDop);
|
GWSC(formatDop);
|
||||||
GWSC(formatRot);
|
GWSC(formatRot);
|
||||||
typedef std::vector<GwBoatItemBase*> GwBoatItemMap;
|
typedef std::map<String,GwBoatItemBase*> GwBoatItemMap;
|
||||||
protected:
|
protected:
|
||||||
|
int type;
|
||||||
unsigned long lastSet=0;
|
unsigned long lastSet=0;
|
||||||
unsigned long invalidTime=INVALID_TIME;
|
unsigned long invalidTime=INVALID_TIME;
|
||||||
String name;
|
String name;
|
||||||
|
@ -34,6 +47,7 @@ class GwBoatItemBase{
|
||||||
else lastSet=millis();
|
else lastSet=millis();
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
int getCurrentType(){return type;}
|
||||||
unsigned long getLastSet() const {return lastSet;}
|
unsigned long getLastSet() const {return lastSet;}
|
||||||
bool isValid(unsigned long now=0) const {
|
bool isValid(unsigned long now=0) const {
|
||||||
if (lastSet == 0) return false;
|
if (lastSet == 0) return false;
|
||||||
|
@ -46,13 +60,14 @@ class GwBoatItemBase{
|
||||||
this->invalidTime=invalidTime;
|
this->invalidTime=invalidTime;
|
||||||
this->name=name;
|
this->name=name;
|
||||||
this->format=format;
|
this->format=format;
|
||||||
|
this->type=0;
|
||||||
}
|
}
|
||||||
virtual ~GwBoatItemBase(){}
|
virtual ~GwBoatItemBase(){}
|
||||||
void invalidate(){
|
void invalidate(){
|
||||||
lastSet=0;
|
lastSet=0;
|
||||||
}
|
}
|
||||||
virtual void toJsonDoc(JsonDocument *doc, unsigned long minTime)=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 int getLastSource()=0;
|
||||||
virtual void refresh(unsigned long ts=0){uls(ts);}
|
virtual void refresh(unsigned long ts=0){uls(ts);}
|
||||||
String getName(){return name;}
|
String getName(){return name;}
|
||||||
|
@ -63,10 +78,11 @@ template<class T> class GwBoatItem : public GwBoatItemBase{
|
||||||
T data;
|
T data;
|
||||||
int lastUpdateSource;
|
int lastUpdateSource;
|
||||||
public:
|
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){
|
GwBoatItemBase(name,formatInfo,invalidTime){
|
||||||
|
this->type=type;
|
||||||
if (map){
|
if (map){
|
||||||
map->push_back(this);
|
(*map)[name]=this;
|
||||||
}
|
}
|
||||||
lastUpdateSource=-1;
|
lastUpdateSource=-1;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +93,7 @@ template<class T> class GwBoatItem : public GwBoatItemBase{
|
||||||
//priority handling
|
//priority handling
|
||||||
//sources with lower ids will win
|
//sources with lower ids will win
|
||||||
//and we will not overwrite their value
|
//and we will not overwrite their value
|
||||||
if (lastUpdateSource < source){
|
if (lastUpdateSource < source && lastUpdateSource >= 0){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,7 +187,8 @@ bool convertToJson(const GwSatInfoList &si,JsonVariant &variant);
|
||||||
class GwBoatDataSatList : public GwBoatItem<GwSatInfoList>
|
class GwBoatDataSatList : public GwBoatItem<GwSatInfoList>
|
||||||
{
|
{
|
||||||
public:
|
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)
|
bool update(GwSatInfo info, int source)
|
||||||
{
|
{
|
||||||
unsigned long now = millis();
|
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) \
|
#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) \
|
#define GWSPECBOATDATA(clazz,name,time,fmt) \
|
||||||
clazz *name=new clazz(F(#name),GwBoatItemBase::fmt,time,&values) ;
|
clazz *name=new clazz(F(#name),GwBoatItemBase::fmt,time,&values) ;
|
||||||
class GwBoatData{
|
class GwBoatData{
|
||||||
|
@ -254,43 +279,11 @@ class GwBoatData{
|
||||||
public:
|
public:
|
||||||
GwBoatData(GwLog *logger);
|
GwBoatData(GwLog *logger);
|
||||||
~GwBoatData();
|
~GwBoatData();
|
||||||
template<class T> GwBoatItem<T> *getOrCreate(T dummy,String name,String format,
|
template<class T> GwBoatItem<T> *getOrCreate(T initial,GwBoatItemNameProvider *provider);
|
||||||
unsigned long invalidTime=GwBoatItemBase::INVALID_TIME);
|
template<class T> bool update(T value,int source,GwBoatItemNameProvider *provider);
|
||||||
|
template<class T> T getDataWithDefault(T defaultv, GwBoatItemNameProvider *provider);
|
||||||
String toJson() const;
|
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
|
#endif
|
|
@ -105,6 +105,10 @@ private:
|
||||||
return false;
|
return false;
|
||||||
return item->update(value,sourceId);
|
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 LastPosSend;
|
||||||
unsigned long NextRMCSend;
|
unsigned long NextRMCSend;
|
||||||
|
@ -1234,7 +1238,7 @@ private:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GwXDRFoundMapping mapping=xdrMappings->getMapping(XDRTEMP,(int)TemperatureSource,0,TemperatureInstance);
|
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());
|
LOG_DEBUG(GwLog::DEBUG+1,"found temperature mapping %s",mapping.definition->toString().c_str());
|
||||||
addToXdr(mapping.buildXdrEntry(Temperature));
|
addToXdr(mapping.buildXdrEntry(Temperature));
|
||||||
finalizeXdr();
|
finalizeXdr();
|
||||||
|
@ -1251,7 +1255,7 @@ private:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GwXDRFoundMapping mapping=xdrMappings->getMapping(XDRHUMIDITY,(int)HumiditySource,0,HumidityInstance);
|
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());
|
LOG_DEBUG(GwLog::DEBUG+1,"found humidity mapping %s",mapping.definition->toString().c_str());
|
||||||
addToXdr(mapping.buildXdrEntry(ActualHumidity));
|
addToXdr(mapping.buildXdrEntry(ActualHumidity));
|
||||||
finalizeXdr();
|
finalizeXdr();
|
||||||
|
@ -1268,7 +1272,7 @@ private:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GwXDRFoundMapping mapping=xdrMappings->getMapping(XDRPRESSURE,(int)PressureSource,0,PressureInstance);
|
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());
|
LOG_DEBUG(GwLog::DEBUG+1,"found pressure mapping %s",mapping.definition->toString().c_str());
|
||||||
addToXdr(mapping.buildXdrEntry(ActualPressure));
|
addToXdr(mapping.buildXdrEntry(ActualPressure));
|
||||||
finalizeXdr();
|
finalizeXdr();
|
||||||
|
|
|
@ -188,6 +188,10 @@ GwXDRMappingDef *GwXDRMappingDef::fromString(String s)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rt->direction == GwXDRMappingDef::M_DISABLED || rt->xdrName == ""){
|
||||||
|
delete rt;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
String GwXDRMappingDef::getTransducerName(int instance)
|
String GwXDRMappingDef::getTransducerName(int instance)
|
||||||
|
|
|
@ -166,7 +166,7 @@ class GwXDRFoundMapping : public GwBoatItemNameProvider{
|
||||||
String buildXdrEntry(double value);
|
String buildXdrEntry(double value);
|
||||||
//boat Data info
|
//boat Data info
|
||||||
virtual String getBoatItemName(){
|
virtual String getBoatItemName(){
|
||||||
return getTransducerName();
|
return String("xdr")+getTransducerName();
|
||||||
};
|
};
|
||||||
virtual String getBoatItemFormat(){
|
virtual String getBoatItemFormat(){
|
||||||
return "formatXdr"+type->xdrunit; //TODO: use the type def for the correct format
|
return "formatXdr"+type->xdrunit; //TODO: use the type def for the correct format
|
||||||
|
|
|
@ -242,7 +242,7 @@ body{
|
||||||
}
|
}
|
||||||
|
|
||||||
.dash {
|
.dash {
|
||||||
width: 6em;
|
width: 6.5em;
|
||||||
height: 4em;
|
height: 4em;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
40
web/index.js
40
web/index.js
|
@ -1025,6 +1025,15 @@ let valueFormatters = {
|
||||||
u:'m'
|
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) {
|
function createDashboardItem(name, def, parent) {
|
||||||
let frame = addEl('div', 'dash', parent);
|
let frame = addEl('div', 'dash', parent);
|
||||||
let title = addEl('span', 'dashTitle', frame, name);
|
let title = addEl('span', 'dashTitle', frame, name);
|
||||||
|
@ -1035,7 +1044,11 @@ function createDashboardItem(name, def, parent) {
|
||||||
let footer = addEl('div','footer',frame);
|
let footer = addEl('div','footer',frame);
|
||||||
let src= addEl('span','source',footer);
|
let src= addEl('span','source',footer);
|
||||||
src.setAttribute('id','source_'+name);
|
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;
|
return value;
|
||||||
}
|
}
|
||||||
function createDashboard() {
|
function createDashboard() {
|
||||||
|
@ -1057,9 +1070,14 @@ function sourceName(v){
|
||||||
return "---";
|
return "---";
|
||||||
}
|
}
|
||||||
function updateDashboard(data) {
|
function updateDashboard(data) {
|
||||||
|
let frame = document.getElementById('dashboardPage');
|
||||||
for (let n in data) {
|
for (let n in data) {
|
||||||
let de = document.getElementById('data_' + n);
|
let de = document.getElementById('data_' + n);
|
||||||
|
if (! de && frame){
|
||||||
|
de=createDashboardItem(n,data[n],frame);
|
||||||
|
}
|
||||||
if (de) {
|
if (de) {
|
||||||
|
let newContent='----';
|
||||||
if (data[n].valid) {
|
if (data[n].valid) {
|
||||||
let formatter;
|
let formatter;
|
||||||
if (data[n].format && data[n].format != "NULL") {
|
if (data[n].format && data[n].format != "NULL") {
|
||||||
|
@ -1067,26 +1085,38 @@ function updateDashboard(data) {
|
||||||
formatter = valueFormatters[key];
|
formatter = valueFormatters[key];
|
||||||
}
|
}
|
||||||
if (formatter) {
|
if (formatter) {
|
||||||
de.textContent = formatter.f(data[n].value);
|
newContent = formatter.f(data[n].value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let v = parseFloat(data[n].value);
|
let v = parseFloat(data[n].value);
|
||||||
if (!isNaN(v)) {
|
if (!isNaN(v)) {
|
||||||
v = v.toFixed(3)
|
v = v.toFixed(3)
|
||||||
de.textContent = v;
|
newContent = v;
|
||||||
}
|
}
|
||||||
else {
|
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);
|
let src=document.getElementById('source_'+n);
|
||||||
if (src){
|
if (src){
|
||||||
src.textContent=sourceName(data[n].source);
|
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);
|
window.setInterval(update, 1000);
|
||||||
|
|
Loading…
Reference in New Issue