add calset input
This commit is contained in:
parent
32e48b126c
commit
a240cade7e
|
@ -182,6 +182,13 @@ class GwApi{
|
||||||
* The name should be similar to the function name of the user task (although not mandatory)
|
* The name should be similar to the function name of the user task (although not mandatory)
|
||||||
*/
|
*/
|
||||||
virtual bool addUserTask(GwUserTaskFunction task,const String Name, int stackSize=2000)=0;
|
virtual bool addUserTask(GwUserTaskFunction task,const String Name, int stackSize=2000)=0;
|
||||||
|
/**
|
||||||
|
* set a value that is used for calibration in config values
|
||||||
|
* for cfg types calset, calvalue
|
||||||
|
* @param name: the config name this value is used for
|
||||||
|
* @param value: the current value
|
||||||
|
*/
|
||||||
|
virtual void setCalibrationValue(const String &name, double value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* not thread safe methods
|
* not thread safe methods
|
||||||
|
|
|
@ -116,6 +116,10 @@ bool GwWebServer::registerMainHandler(const char *url,RequestCreator creator){
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
bool GwWebServer::registerHandler(const char * url,GwWebServer::HandlerFunction handler){
|
||||||
|
server->on(url,HTTP_GET,handler);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool GwWebServer::registerPostHandler(const char *url, ArRequestHandlerFunction requestHandler,
|
bool GwWebServer::registerPostHandler(const char *url, ArRequestHandlerFunction requestHandler,
|
||||||
ArBodyHandlerFunction bodyHandler){
|
ArBodyHandlerFunction bodyHandler){
|
||||||
|
|
|
@ -11,10 +11,12 @@ class GwWebServer{
|
||||||
GwLog *logger;
|
GwLog *logger;
|
||||||
public:
|
public:
|
||||||
typedef GwRequestMessage *(RequestCreator)(AsyncWebServerRequest *request);
|
typedef GwRequestMessage *(RequestCreator)(AsyncWebServerRequest *request);
|
||||||
|
using HandlerFunction=std::function<void(AsyncWebServerRequest *)>;
|
||||||
GwWebServer(GwLog *logger, GwRequestQueue *queue,int port);
|
GwWebServer(GwLog *logger, GwRequestQueue *queue,int port);
|
||||||
~GwWebServer();
|
~GwWebServer();
|
||||||
void begin();
|
void begin();
|
||||||
bool registerMainHandler(const char *url,RequestCreator creator);
|
bool registerMainHandler(const char *url,RequestCreator creator);
|
||||||
|
bool registerHandler(const char * url,HandlerFunction handler);
|
||||||
bool registerPostHandler(const char *url, ArRequestHandlerFunction requestHandler, ArBodyHandlerFunction bodyHandler);
|
bool registerPostHandler(const char *url, ArRequestHandlerFunction requestHandler, ArBodyHandlerFunction bodyHandler);
|
||||||
void handleAsyncWebRequest(AsyncWebServerRequest *request, GwRequestMessage *msg);
|
void handleAsyncWebRequest(AsyncWebServerRequest *request, GwRequestMessage *msg);
|
||||||
AsyncWebServer * getServer(){return server;}
|
AsyncWebServer * getServer(){return server;}
|
||||||
|
|
|
@ -81,6 +81,7 @@
|
||||||
class GWDMS22B : public SSISensor{
|
class GWDMS22B : public SSISensor{
|
||||||
int zero=2047;
|
int zero=2047;
|
||||||
bool invt=false;
|
bool invt=false;
|
||||||
|
String zeroConfigName;
|
||||||
public:
|
public:
|
||||||
using SSISensor::SSISensor;
|
using SSISensor::SSISensor;
|
||||||
virtual bool preinit(GwApi * api){
|
virtual bool preinit(GwApi * api){
|
||||||
|
@ -102,6 +103,8 @@ class GWDMS22B : public SSISensor{
|
||||||
tN2kMsg msg;
|
tN2kMsg msg;
|
||||||
SetN2kRudder(msg,DegToRad(resolved),iid);
|
SetN2kRudder(msg,DegToRad(resolved),iid);
|
||||||
api->sendN2kMessage(msg);
|
api->sendN2kMessage(msg);
|
||||||
|
api->increment(counterId,prefix);
|
||||||
|
api->setCalibrationValue(zeroConfigName,(double)value);
|
||||||
}
|
}
|
||||||
#define DMS22B(PRFX,...) \
|
#define DMS22B(PRFX,...) \
|
||||||
if (prefix == #PRFX) {\
|
if (prefix == #PRFX) {\
|
||||||
|
@ -109,6 +112,7 @@ class GWDMS22B : public SSISensor{
|
||||||
CFG_GET(iid,PRFX); \
|
CFG_GET(iid,PRFX); \
|
||||||
CFG_GET(fintv,PRFX); \
|
CFG_GET(fintv,PRFX); \
|
||||||
CFG_GET(zero,PRFX); \
|
CFG_GET(zero,PRFX); \
|
||||||
|
zeroConfigName=GwConfigDefinitions::PRFX ## zero;\
|
||||||
CFG_GET(invt,PRFX); \
|
CFG_GET(invt,PRFX); \
|
||||||
bits=12; \
|
bits=12; \
|
||||||
clock=500000; \
|
clock=500000; \
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
{
|
{
|
||||||
"name": "DMS22B$izero",
|
"name": "DMS22B$izero",
|
||||||
"label": "DMS22B$i Zero",
|
"label": "DMS22B$i Zero",
|
||||||
"type": "number",
|
"type": "calset",
|
||||||
"default": 2048,
|
"default": 2048,
|
||||||
"description": "Zero position (0...2^bits-1)",
|
"description": "Zero position (0...2^bits-1)",
|
||||||
"category": "spisensors$b",
|
"category": "spisensors$b",
|
||||||
|
|
|
@ -332,6 +332,9 @@ public:
|
||||||
api->getLogger()->logDebug(GwLog::LOG,"adding user task %s",tname.c_str());
|
api->getLogger()->logDebug(GwLog::LOG,"adding user task %s",tname.c_str());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
virtual void setCalibrationValue(const String &name, double value){
|
||||||
|
api->setCalibrationValue(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
42
src/main.cpp
42
src/main.cpp
|
@ -235,15 +235,38 @@ void SendNMEA0183Message(const tNMEA0183Msg &NMEA0183Msg, int sourceId,bool conv
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CalibrationValues {
|
||||||
|
using Map=std::map<String,double>;
|
||||||
|
Map values;
|
||||||
|
SemaphoreHandle_t lock;
|
||||||
|
public:
|
||||||
|
CalibrationValues(){
|
||||||
|
lock=xSemaphoreCreateMutex();
|
||||||
|
}
|
||||||
|
void set(const String &name,double value){
|
||||||
|
GWSYNCHRONIZED(&lock);
|
||||||
|
values[name]=value;
|
||||||
|
}
|
||||||
|
bool get(const String &name, double &value){
|
||||||
|
GWSYNCHRONIZED(&lock);
|
||||||
|
auto it=values.find(name);
|
||||||
|
if (it==values.end()) return false;
|
||||||
|
value=it->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class ApiImpl : public GwApiInternal
|
class ApiImpl : public GwApiInternal
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int sourceId = -1;
|
int sourceId = -1;
|
||||||
|
std::unique_ptr<CalibrationValues> calibrations;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ApiImpl(int sourceId)
|
ApiImpl(int sourceId)
|
||||||
{
|
{
|
||||||
this->sourceId = sourceId;
|
this->sourceId = sourceId;
|
||||||
|
calibrations.reset(new CalibrationValues());
|
||||||
}
|
}
|
||||||
virtual GwRequestQueue *getQueue()
|
virtual GwRequestQueue *getQueue()
|
||||||
{
|
{
|
||||||
|
@ -332,6 +355,13 @@ public:
|
||||||
virtual bool addUserTask(GwUserTaskFunction task,const String Name, int stackSize=2000){
|
virtual bool addUserTask(GwUserTaskFunction task,const String Name, int stackSize=2000){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
virtual void setCalibrationValue(const String &name, double value){
|
||||||
|
calibrations->set(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getCalibrationValue(const String &name,double &value){
|
||||||
|
return calibrations->get(name,value);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool delayedRestart(){
|
bool delayedRestart(){
|
||||||
|
@ -804,6 +834,18 @@ void setup() {
|
||||||
|
|
||||||
},
|
},
|
||||||
handleConfigRequestData);
|
handleConfigRequestData);
|
||||||
|
webserver.registerHandler("/api/calibrate",[](AsyncWebServerRequest *request){
|
||||||
|
const String name=request->arg("name");
|
||||||
|
double value;
|
||||||
|
if (! apiImpl->getCalibrationValue(name,value)){
|
||||||
|
request->send(400, "text/plain", "name not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char buffer[30];
|
||||||
|
snprintf(buffer,29,"%g",value);
|
||||||
|
buffer[29]=0;
|
||||||
|
request->send(200,"text/plain",buffer);
|
||||||
|
});
|
||||||
|
|
||||||
webserver.begin();
|
webserver.begin();
|
||||||
xdrMappings.begin();
|
xdrMappings.begin();
|
||||||
|
|
|
@ -131,7 +131,6 @@
|
||||||
AHA
|
AHA
|
||||||
</div>
|
</div>
|
||||||
<div class="overlayButtons">
|
<div class="overlayButtons">
|
||||||
<button id="hideOverlay">Close</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -190,6 +189,10 @@
|
||||||
<div class="hidden">
|
<div class="hidden">
|
||||||
<a id="downloadXdr"></a>
|
<a id="downloadXdr"></a>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="hidden" id="calset">
|
||||||
|
<h2 class="heading"></h2>
|
||||||
|
<p class="val"></p>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
59
web/index.js
59
web/index.js
|
@ -371,8 +371,13 @@ function updateMsgDetails(key, details) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function showOverlay(text, isHtml) {
|
function showOverlay(text, isHtml,buttons) {
|
||||||
let el = document.getElementById('overlayContent');
|
let el = document.getElementById('overlayContent');
|
||||||
|
if (text instanceof Object){
|
||||||
|
el.textContent='';
|
||||||
|
el.appendChild(text);
|
||||||
|
}
|
||||||
|
else {
|
||||||
if (isHtml) {
|
if (isHtml) {
|
||||||
el.innerHTML = text;
|
el.innerHTML = text;
|
||||||
el.classList.remove("text");
|
el.classList.remove("text");
|
||||||
|
@ -381,12 +386,22 @@ function showOverlay(text, isHtml) {
|
||||||
el.textContent = text;
|
el.textContent = text;
|
||||||
el.classList.add("text");
|
el.classList.add("text");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
buttons=(buttons?buttons:[]).concat([{label:"Close",click:hideOverlay}]);
|
||||||
let container = document.getElementById('overlayContainer');
|
let container = document.getElementById('overlayContainer');
|
||||||
|
let btframe=container.querySelector('.overlayButtons');
|
||||||
|
btframe.textContent='';
|
||||||
|
buttons.forEach((btconfig)=>{
|
||||||
|
let bt=addEl('button','',btframe,btconfig.label);
|
||||||
|
bt.addEventListener("click",btconfig.click);
|
||||||
|
});
|
||||||
container.classList.remove('hidden');
|
container.classList.remove('hidden');
|
||||||
}
|
}
|
||||||
function hideOverlay() {
|
function hideOverlay() {
|
||||||
let container = document.getElementById('overlayContainer');
|
let container = document.getElementById('overlayContainer');
|
||||||
container.classList.add('hidden');
|
container.classList.add('hidden');
|
||||||
|
let el = document.getElementById('overlayContent');
|
||||||
|
el.textContent='';
|
||||||
}
|
}
|
||||||
function checkChange(el, row,name) {
|
function checkChange(el, row,name) {
|
||||||
let loaded = el.getAttribute('data-loaded');
|
let loaded = el.getAttribute('data-loaded');
|
||||||
|
@ -456,6 +471,45 @@ function checkCondition(element){
|
||||||
if (visible) row.classList.remove('hidden');
|
if (visible) row.classList.remove('hidden');
|
||||||
else row.classList.add('hidden');
|
else row.classList.add('hidden');
|
||||||
}
|
}
|
||||||
|
let caliv=0;
|
||||||
|
function createCalSetInput(configItem,frame,clazz){
|
||||||
|
let el = addEl('input',clazz,frame);
|
||||||
|
let cb = addEl('button','',frame,'C');
|
||||||
|
//el.disabled=true;
|
||||||
|
cb.addEventListener('click',(ev)=>{
|
||||||
|
let cs=document.getElementById("calset").cloneNode(true);
|
||||||
|
cs.classList.remove("hidden");
|
||||||
|
cs.querySelector(".heading").textContent=configItem.name;
|
||||||
|
let vel=cs.querySelector(".val");
|
||||||
|
if (caliv != 0) window.clearInterval(caliv);
|
||||||
|
caliv=window.setInterval(()=>{
|
||||||
|
if (document.body.contains(cs)){
|
||||||
|
fetch("/api/calibrate?name="+encodeURIComponent(configItem.name))
|
||||||
|
.then((r)=>r.text())
|
||||||
|
.then((txt)=>{
|
||||||
|
if (txt != vel.textContent){
|
||||||
|
vel.textContent=txt;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e)=>{
|
||||||
|
alert(e);
|
||||||
|
hideOverlay();
|
||||||
|
window.clearInterval(caliv);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
window.clearInterval(caliv);
|
||||||
|
}
|
||||||
|
},200);
|
||||||
|
showOverlay(cs,false,[{label:'Set',click:()=>{
|
||||||
|
el.value=vel.textContent;
|
||||||
|
let cev=new Event('change');
|
||||||
|
el.dispatchEvent(cev);
|
||||||
|
}}]);
|
||||||
|
})
|
||||||
|
el.setAttribute('name', configItem.name)
|
||||||
|
return el;
|
||||||
|
}
|
||||||
function createInput(configItem, frame,clazz) {
|
function createInput(configItem, frame,clazz) {
|
||||||
let el;
|
let el;
|
||||||
if (configItem.type === 'boolean' || configItem.type === 'list' || configItem.type == 'boatData') {
|
if (configItem.type === 'boolean' || configItem.type === 'list' || configItem.type == 'boatData') {
|
||||||
|
@ -492,6 +546,9 @@ function createInput(configItem, frame,clazz) {
|
||||||
if (configItem.type === 'xdr'){
|
if (configItem.type === 'xdr'){
|
||||||
return createXdrInput(configItem,frame,clazz);
|
return createXdrInput(configItem,frame,clazz);
|
||||||
}
|
}
|
||||||
|
if (configItem.type === "calset"){
|
||||||
|
return createCalSetInput(configItem,frame,clazz);
|
||||||
|
}
|
||||||
el = addEl('input',clazz,frame);
|
el = addEl('input',clazz,frame);
|
||||||
if (configItem.readOnly) el.setAttribute('disabled',true);
|
if (configItem.readOnly) el.setAttribute('disabled',true);
|
||||||
el.setAttribute('name', configItem.name)
|
el.setAttribute('name', configItem.name)
|
||||||
|
|
Loading…
Reference in New Issue