From 58054805889beaf05a1789f14985de592ef00e63 Mon Sep 17 00:00:00 2001 From: George Nicolas Kontogiorgos <george.kontogiorgos@ess.eu> Date: Sat, 2 Sep 2023 01:33:11 +0200 Subject: [PATCH 1/5] Add LICENSE file --- LICENSE | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0730be6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2023, European Spallation Source ERIC +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- GitLab From 3bbdbb21cfd56818f87d1f6506fc4233d1e3c87a Mon Sep 17 00:00:00 2001 From: George Kontogiorgos <george.kontogiorgos@ess.eu> Date: Tue, 26 Sep 2023 16:48:41 +0200 Subject: [PATCH 2/5] Fix debug messages behavior related to the server queries --- .gitignore | 2 +- cmds/st-asyn-dev.cmd | 2 +- etalonMultiLine2App/src/etalonMultiLine2.cpp | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 6000f6d..6105fc8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,4 @@ Makefile.E3 .cvsignore O.* core.* -etalon +etalon* diff --git a/cmds/st-asyn-dev.cmd b/cmds/st-asyn-dev.cmd index 7b80576..6017eb9 100644 --- a/cmds/st-asyn-dev.cmd +++ b/cmds/st-asyn-dev.cmd @@ -21,7 +21,7 @@ drvAsynIPPortConfigure("$(PORTNAME)", "$(IPADDR):$(IPPORT)") #asynSetTraceMask("$(PORTNAME)",-1,0x9) #asynSetTraceIOMask("$(PORTNAME)",-1,0x2) -etalonMultiLine2Config("ETALON", "$(PORTNAME)", 0) +etalonMultiLine2Config("ETALON", "$(PORTNAME)", 1) dbLoadRecords(control.db, "P=$(PREFIX),R=:, PORT="ETALON", ADDR=0, SLOW_SCAN=$(SLOW_SCAN), FAST_SCAN=$(FAST_SCAN)") dbLoadRecords(data.db, "P=$(PREFIX),R=:, PORT="ETALON", ADDR=0, SLOW_SCAN=$(SLOW_SCAN), FAST_SCAN=$(FAST_SCAN)") diff --git a/etalonMultiLine2App/src/etalonMultiLine2.cpp b/etalonMultiLine2App/src/etalonMultiLine2.cpp index 4e2fbae..b199fe1 100644 --- a/etalonMultiLine2App/src/etalonMultiLine2.cpp +++ b/etalonMultiLine2App/src/etalonMultiLine2.cpp @@ -210,7 +210,8 @@ asynStatus EtalonMultiline2::serverQuery(const char * query, reply, MAX_REPLY_SIZE, TIMEOUT, &nWrite, &nRead, &eomReason); - + spdlog::debug("query: {}", query); + spdlog::debug("reply: {}", reply); if (status) { @@ -497,7 +498,6 @@ asynStatus EtalonMultiline2::performMeasurement(asynStatus status) char tempBuffer[10]; for(int i = 0; i < numSelectedChannels; i++) { - spdlog::debug("{}", measChEna_[i]); if(measChEna_[i]) { strcat(query,","); @@ -516,8 +516,6 @@ asynStatus EtalonMultiline2::performMeasurement(asynStatus status) status = callParamCallbacks(); status = serverQuery(query, reply, status); - spdlog::debug("query: {}", query); - spdlog::debug("reply: {}", reply); if(strcmp(reply, "ERROR") == 0) { -- GitLab From 01968228d7e36833fb61c34ea134316d66e6ac9b Mon Sep 17 00:00:00 2001 From: George Kontogiorgos <george.kontogiorgos@ess.eu> Date: Tue, 26 Sep 2023 16:51:35 +0200 Subject: [PATCH 3/5] Do not send a query to server if none of channels are enabled --- etalonMultiLine2App/src/etalonMultiLine2.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/etalonMultiLine2App/src/etalonMultiLine2.cpp b/etalonMultiLine2App/src/etalonMultiLine2.cpp index b199fe1..1b7792b 100644 --- a/etalonMultiLine2App/src/etalonMultiLine2.cpp +++ b/etalonMultiLine2App/src/etalonMultiLine2.cpp @@ -490,7 +490,7 @@ asynStatus EtalonMultiline2::performMeasurement(asynStatus status) { char query[MAX_QUERY_SIZE]; char reply[MAX_REPLY_SIZE]; - + short int enabledChannelsCounter = 0; if(!status) { strcpy(query, "measurelength"); @@ -506,10 +506,12 @@ asynStatus EtalonMultiline2::performMeasurement(asynStatus status) strcat(query,","); sprintf(tempBuffer, "%lf", measPreshot_[i]); strcat(query, tempBuffer); + enabledChannelsCounter++; } } } - + if(enabledChannelsCounter) + { if(!status) status = setIntegerParam(MeasState_, StateMeasuring); if(!status) @@ -659,6 +661,13 @@ asynStatus EtalonMultiline2::performMeasurement(asynStatus status) if(!status) status = setIntegerParam(MeasState_, StateIdle); } + } + } + else + { + spdlog::warn("There are no enabled channels, I am not going to send a measure request to the server. Setting status to ERROR."); + if(!status) + status = setIntegerParam(MeasState_, StateError); } return status; } -- GitLab From 2c2020f9e10a57e1b8457a28cf936a76e083468e Mon Sep 17 00:00:00 2001 From: George Kontogiorgos <george.kontogiorgos@ess.eu> Date: Wed, 27 Sep 2023 16:27:03 +0200 Subject: [PATCH 4/5] Fix counter behaviour to allow a unique ID for each measurement --- etalonMultiLine2App/Db/control.template | 23 +- etalonMultiLine2App/Db/data.template | 60 +++- etalonMultiLine2App/Db/status.template | 35 +- etalonMultiLine2App/src/etalonMultiLine2.cpp | 334 +++++++++++-------- etalonMultiLine2App/src/etalonMultiLine2.h | 46 ++- 5 files changed, 337 insertions(+), 161 deletions(-) diff --git a/etalonMultiLine2App/Db/control.template b/etalonMultiLine2App/Db/control.template index 002e428..04b7f90 100644 --- a/etalonMultiLine2App/Db/control.template +++ b/etalonMultiLine2App/Db/control.template @@ -31,7 +31,7 @@ record(waveform, "$(P)$(R)MeasEnableChannel-S") { field(DTYP, "asynInt32ArrayIn") field(PINI, "YES") field(FTVL, "LONG") - field(NELM, 40) + field(NELM, "40") field(INP, "@asyn($(PORT),$(ADDR))MEAS_ENABLE_CHANNEL") info(autosaveFields, "VAL") } @@ -41,7 +41,7 @@ record(waveform, "$(P)$(R)MeasPreshot-S") { field(DTYP, "asynFloat64ArrayIn") field(PINI, "YES") field(FTVL, "DOUBLE") - field(NELM, 40) + field(NELM, "40") field(INP, "@asyn($(PORT),$(ADDR))MEAS_CHANNEL_PRESHOT") info(autosaveFields, "VAL") } @@ -81,3 +81,22 @@ record(bo, "$(P)$(R)AlignmentStart-S") { field(ONAM, "True") field(OUT, "@asyn($(PORT),$(ADDR))ALIGNMENT_START") } + +record(waveform, "$(P)$(R)ErrorMask-S") { + field(DESC, "Mask to enable checking errors") + field(DTYP, "asynInt32ArrayIn") + field(PINI, "YES") + field(FTVL, "LONG") + field(INP, "@asyn($(PORT),$(ADDR))ERROR_MASK") + field(NELM, "40") + info(autosaveFields, "VAL") +} + +record(ao, "$(P)$(R)GlobalMeasCounter-S") { + field(DESC, "Set measurement counter") + field(DOL, "$(P)$(R)GlobalMeasCounter-R") + field(OMSL, "closed_loop") + field(DTYP, "asynInt32") + field(PINI, "YES") + field(OUT, "@asyn($(PORT),$(ADDR))GLOBAL_MEAS_COUNTER") +} diff --git a/etalonMultiLine2App/Db/data.template b/etalonMultiLine2App/Db/data.template index 5cef77b..2b21c26 100644 --- a/etalonMultiLine2App/Db/data.template +++ b/etalonMultiLine2App/Db/data.template @@ -18,6 +18,16 @@ record(waveform, "$(P)$(R)DataLenLength-R") { field(NELM, "40") } +record(waveform, "$(P)$(R)LstValDataLenLength-R") { + field(DESC, "Last valid Li: measured length") + field(DTYP, "asynFloat64ArrayIn") + field(EGU, "mm") + field(SCAN, "I/O Intr") + field(INP, "@asyn($(PORT),$(ADDR))LAST_VALID_MEASURED_LENGTH") + field(FTVL, "DOUBLE") + field(NELM, "40") +} + record(waveform, "$(P)$(R)DataLenIMin-R") { field(DESC, "IMini: minimum intensity") field(DTYP, "asynInt32ArrayIn") @@ -27,6 +37,15 @@ record(waveform, "$(P)$(R)DataLenIMin-R") { field(NELM, "40") } +record(waveform, "$(P)$(R)LstVldDataLenIMin-R") { + field(DESC, "Last vallid IMini: minimum intensity") + field(DTYP, "asynInt32ArrayIn") + field(SCAN, "I/O Intr") + field(INP, "@asyn($(PORT),$(ADDR))LAST_VALID_MEASURED_IMIN") + field(FTVL, "LONG") + field(NELM, "40") +} + record(waveform, "$(P)$(R)DataLenIMax-R") { field(DESC, "IMaxi: maximum intensity") field(DTYP, "asynInt32ArrayIn") @@ -36,6 +55,15 @@ record(waveform, "$(P)$(R)DataLenIMax-R") { field(NELM, "40") } +record(waveform, "$(P)$(R)LstVldDataLenIMax-R") { + field(DESC, "Last valid IMaxi: maximum intensity") + field(DTYP, "asynInt32ArrayIn") + field(SCAN, "I/O Intr") + field(INP, "@asyn($(PORT),$(ADDR))LAST_VALID_MEASURED_IMAX") + field(FTVL, "LONG") + field(NELM, "40") +} + record(waveform, "$(P)$(R)DataLenTemp-R") { field(DESC, "Ti: temperature") field(DTYP, "asynFloat64ArrayIn") @@ -46,6 +74,16 @@ record(waveform, "$(P)$(R)DataLenTemp-R") { field(NELM, "40") } +record(waveform, "$(P)$(R)LstVldDataLenTemp-R") { + field(DESC, "Last valid Ti: temperature") + field(DTYP, "asynFloat64ArrayIn") + field(EGU, "o.C") + field(SCAN, "I/O Intr") + field(INP, "@asyn($(PORT),$(ADDR))LAST_VALID_MEASURED_TEMP") + field(FTVL, "DOUBLE") + field(NELM, "40") +} + record(waveform, "$(P)$(R)DataLenPress-R") { field(DESC, "Pi: air pressure") field(DTYP, "asynFloat64ArrayIn") @@ -56,6 +94,16 @@ record(waveform, "$(P)$(R)DataLenPress-R") { field(NELM, "40") } +record(waveform, "$(P)$(R)LstVldDataLenPress-R") { + field(DESC, "Last valid Pi: air pressure") + field(DTYP, "asynFloat64ArrayIn") + field(EGU, "hPa") + field(SCAN, "I/O Intr") + field(INP, "@asyn($(PORT),$(ADDR))LAST_VALID_MEASURED_PRESS") + field(FTVL, "DOUBLE") + field(NELM, "40") +} + record(waveform, "$(P)$(R)DataLenHum-R") { field(DESC, "Hi: humidity") field(DTYP, "asynFloat64ArrayIn") @@ -64,4 +112,14 @@ record(waveform, "$(P)$(R)DataLenHum-R") { field(INP, "@asyn($(PORT),$(ADDR))MEASURED_HUM") field(FTVL, "DOUBLE") field(NELM, "40") -} \ No newline at end of file +} + +record(waveform, "$(P)$(R)LstVldDataLenHum-R") { + field(DESC, "Last valid Hi: humidity") + field(DTYP, "asynFloat64ArrayIn") + field(EGU, "%") + field(SCAN, "I/O Intr") + field(INP, "@asyn($(PORT),$(ADDR))LAST_VALID_MEASURED_HUM") + field(FTVL, "DOUBLE") + field(NELM, "40") +} diff --git a/etalonMultiLine2App/Db/status.template b/etalonMultiLine2App/Db/status.template index f9f31eb..e4182b9 100644 --- a/etalonMultiLine2App/Db/status.template +++ b/etalonMultiLine2App/Db/status.template @@ -54,7 +54,7 @@ record(waveform, "$(P)$(R)SelectedChannels-R") { field(DTYP, "asynInt32ArrayIn") field(INP, "@asyn($(PORT),$(ADDR))SELECTED_CHANNELS") field(FTVL, "LONG") - field(NELM, 40) + field(NELM, "40") field(SCAN, "I/O Intr") } @@ -119,7 +119,7 @@ record(waveform, "$(P)$(R)Gains-R") { field(DTYP, "asynInt32ArrayIn") field(FTVL, "LONG") field(INP, "@asyn($(PORT),$(ADDR))GAINS") - field(NELM, 40) + field(NELM, "40") field(SCAN, "I/O Intr") } @@ -128,7 +128,7 @@ record(waveform, "$(P)$(R)AlignDataMax-R") { field(DTYP, "asynFloat64ArrayIn") field(INP, "@asyn($(PORT),$(ADDR))ALIGN_DATA_MAX") field(FTVL, "DOUBLE") - field(NELM, 40) + field(NELM, "40") field(SCAN, "I/O Intr") } @@ -137,7 +137,7 @@ record(waveform, "$(P)$(R)AlignDataMin-R") { field(DTYP, "asynFloat64ArrayIn") field(INP, "@asyn($(PORT),$(ADDR))ALIGN_DATA_MIN") field(FTVL, "DOUBLE") - field(NELM, 40) + field(NELM, "40") field(SCAN, "I/O Intr") } @@ -180,10 +180,31 @@ record(mbbi, "$(P)$(R)CurrentTask-R") { } record(waveform, "$(P)$(R)MeasCounter-R") { - field(DESC, "Measure counter for each channel") + field(DESC, "Measure counter per channel") field(DTYP, "asynInt32ArrayIn") field(FTVL, "LONG") field(INP, "@asyn($(PORT),$(ADDR))MEAS_COUNTER") - field(NELM, 40) + field(NELM, "40") field(SCAN, "I/O Intr") -} \ No newline at end of file + info(autosaveFields, "VAL") +} + +record(waveform, "$(P)$(R)LstVldMeasCounter-R") { + field(DESC, "Last valid measure counter per ch") + field(DTYP, "asynInt32ArrayIn") + field(FTVL, "LONG") + field(INP, "@asyn($(PORT),$(ADDR))LAST_VALID_MEAS_COUNTER") + field(NELM, "40") + field(SCAN, "I/O Intr") + info(autosaveFields, "VAL") +} + +record(ai, "$(P)$(R)GlobalMeasCounter-R") { + field(DESC, "Get measurement counter") + field(PINI, "YES") + field(DTYP, "asynInt32") + field(INP, "@asyn($(PORT),$(ADDR))GLOBAL_MEAS_COUNTER") + field(SCAN, "I/O Intr") + field(FLNK, "$(P)$(R)GlobalMeasCounter-S") + info(autosaveFields, "VAL") +} diff --git a/etalonMultiLine2App/src/etalonMultiLine2.cpp b/etalonMultiLine2App/src/etalonMultiLine2.cpp index 1b7792b..c7951c5 100644 --- a/etalonMultiLine2App/src/etalonMultiLine2.cpp +++ b/etalonMultiLine2App/src/etalonMultiLine2.cpp @@ -1,17 +1,3 @@ -#define EPICS_THREAD_CAN_JOIN - -#include <iocsh.h> -#include <epicsThread.h> -#include <epicsEvent.h> -#include <epicsExport.h> -#include <asynPortDriver.h> -#include <string.h> -#include <epicsExit.h> - -#include <signal.h> - -#include "spdlog/spdlog.h" -#include "asynOctetSyncIO.h" #include "etalonMultiLine2.h" static const char *driverName = "etalonMultiLine2"; @@ -83,13 +69,25 @@ EtalonMultiline2::EtalonMultiline2(const char *portName, createParam("ALIGN_DATA_MAX", asynParamFloat64Array, &AlignDataMax_); createParam("ALIGN_DATA_MIN", asynParamFloat64Array, &AlignDataMin_); - createParam("MEASURED_LENGTH", asynParamFloat64Array, &MeasuredLength_); - createParam("MEASURED_IMIN", asynParamInt32Array, &MeasuredImin_); - createParam("MEASURED_IMAX", asynParamInt32Array, &MeasuredImax_); - createParam("MEASURED_TEMP", asynParamFloat64Array, &MeasuredTemp_); - createParam("MEASURED_PRESS", asynParamFloat64Array, &MeasuredPress_); - createParam("MEASURED_HUM", asynParamFloat64Array, &MeasuredHum_); + createParam("GLOBAL_MEAS_COUNTER", asynParamInt32, &GlobalMeasCounter_); + + createParam("MEAS_COUNTER", asynParamInt32Array, &MeasCounter_); + createParam("MEASURED_LENGTH", asynParamFloat64Array, &MeasuredLength_); + createParam("MEASURED_IMIN", asynParamInt32Array, &MeasuredImin_); + createParam("MEASURED_IMAX", asynParamInt32Array, &MeasuredImax_); + createParam("MEASURED_TEMP", asynParamFloat64Array, &MeasuredTemp_); + createParam("MEASURED_PRESS", asynParamFloat64Array, &MeasuredPress_); + createParam("MEASURED_HUM", asynParamFloat64Array, &MeasuredHum_); + + createParam("LAST_VALID_MEAS_COUNTER", asynParamInt32Array, &LastValidMeasCounter_); + createParam("LAST_VALID_MEASURED_LENGTH", asynParamFloat64Array, &LastValidMeasuredLength_); + createParam("LAST_VALID_MEASURED_IMIN", asynParamInt32Array, &LastValidMeasuredImin_); + createParam("LAST_VALID_MEASURED_IMAX", asynParamInt32Array, &LastValidMeasuredImax_); + createParam("LAST_VALID_MEASURED_TEMP", asynParamFloat64Array, &LastValidMeasuredTemp_); + createParam("LAST_VALID_MEASURED_PRESS", asynParamFloat64Array, &LastValidMeasuredPress_); + createParam("LAST_VALID_MEASURED_HUM", asynParamFloat64Array, &LastValidMeasuredHum_); + createParam("ERROR_MASK", asynParamInt32Array, &ErrorMask_); createParam("MEASURED_ANALYSIS_ERROR", asynParamInt32Array, &MeasuredAnalysisError_); createParam("MEASURED_BEAM_INTERRUPTION", asynParamInt32Array, &MeasuredBeamInterruption_); createParam("MEASURED_TEMPERATURE_ERROR", asynParamInt32Array, &MeasuredTemperatureError_); @@ -100,7 +98,6 @@ EtalonMultiline2::EtalonMultiline2(const char *portName, createParam("MEASURED_LASER_SPEED_ERROR", asynParamInt32Array, &MeasuredLaserSpeedError_); createParam("MEASURED_LASER_TEMPERATURE_ERROR", asynParamInt32Array, &MeasuredLaserTemperatureError_); createParam("MEASURED_DAQ_ERROR", asynParamInt32Array, &MeasuredDaqError_); - createParam("MEAS_COUNTER", asynParamInt32Array, &MeasCounter_); /* Enable debug level */ if(enableDebug) @@ -511,156 +508,187 @@ asynStatus EtalonMultiline2::performMeasurement(asynStatus status) } } if(enabledChannelsCounter) - { - if(!status) - status = setIntegerParam(MeasState_, StateMeasuring); - if(!status) - status = callParamCallbacks(); - - status = serverQuery(query, reply, status); - - if(strcmp(reply, "ERROR") == 0) - { - spdlog::error("Server replied error for the following request: {}", query); - - if(!status) - status = setIntegerParam(MeasState_, StateError); - - if(!status) - status = callParamCallbacks(); - } - else if(strcmp(reply, "measurementfinished") == 0) { if(!status) - status = setIntegerParam(MeasState_, StateProcessing); - + status = setIntegerParam(MeasState_, StateMeasuring); if(!status) status = callParamCallbacks(); - - if(!status) - { - size_t nbytesTransfered; - int eomReason; - status = pasynOctetSyncIO->read(pasynUserOctet_, - reply, 1000*sizeof(char), - TIMEOUT, - &nbytesTransfered, &eomReason); - spdlog::debug("reply: {}", reply); - } + + status = serverQuery(query, reply, status); if(strcmp(reply, "ERROR") == 0) { - spdlog::error("Error after processing. Query: {} Reply: {}. Did you set the preshot != 0?", query, reply); - + spdlog::error("Server replied error for the following request: {}", query); + if(!status) status = setIntegerParam(MeasState_, StateError); - + if(!status) status = callParamCallbacks(); } - else + else if(strcmp(reply, "measurementfinished") == 0) { - double measuredLength[MAX_NUM_OF_CHANNELS]; - int minimumIntensityRaw[MAX_NUM_OF_CHANNELS]; - int maximumIntensityRaw[MAX_NUM_OF_CHANNELS]; - double temperature[MAX_NUM_OF_CHANNELS]; - double airPressure[MAX_NUM_OF_CHANNELS]; - double humidity[MAX_NUM_OF_CHANNELS]; - int analysisError[MAX_NUM_OF_CHANNELS]; - int beamBreak[MAX_NUM_OF_CHANNELS]; - int temperatureError[MAX_NUM_OF_CHANNELS]; - int motionTolerance[MAX_NUM_OF_CHANNELS]; - int intensityError[MAX_NUM_OF_CHANNELS]; - int connectionErrorUSB[MAX_NUM_OF_CHANNELS]; - int tcpServerError[MAX_NUM_OF_CHANNELS]; - int errorSettingLaserSpeed[MAX_NUM_OF_CHANNELS]; - int laserTemperatureError[MAX_NUM_OF_CHANNELS]; - int daqErrorDuringDataAcq[MAX_NUM_OF_CHANNELS]; - int tcpServerErrorFinal; + if(!status) + status = setIntegerParam(MeasState_, StateProcessing); + + if(!status) + status = callParamCallbacks(); + if(!status) { - char * token; - - token = strtok(reply, "_"); - token = strtok(NULL, "_"); - - int channelNumber; - - for(int i = 0; i < numSelectedChannels; i++) - { - if(measChEna_[i]) - { - sscanf(token, "%d,%lf,%d,%d,%lf,%lf,%lf,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &channelNumber, - measuredLength + i, - minimumIntensityRaw + i, - maximumIntensityRaw + i, - temperature + i, - airPressure + i, - humidity + i, - analysisError + i, - beamBreak + i, - temperatureError + i, - motionTolerance + i, - intensityError + i, - connectionErrorUSB + i, - tcpServerError + i, - errorSettingLaserSpeed + i, - laserTemperatureError + i, - daqErrorDuringDataAcq + i); + size_t nbytesTransfered; + int eomReason; + status = pasynOctetSyncIO->read(pasynUserOctet_, + reply, 1000*sizeof(char), + TIMEOUT, + &nbytesTransfered, &eomReason); + spdlog::debug("reply: {}", reply); + } - token = strtok(NULL, "_"); - } - } - sscanf(token, "%d", &tcpServerErrorFinal); + if(strcmp(reply, "ERROR") == 0) + { + spdlog::error("Error after processing. Query: {} Reply: {}. Did you set the preshot != 0?", query, reply); + + if(!status) + status = setIntegerParam(MeasState_, StateError); + + if(!status) + status = callParamCallbacks(); } - if(!status) - status = doCallbacksFloat64Array(measuredLength, MAX_NUM_OF_CHANNELS, MeasuredLength_, 0); - if(!status) - status = doCallbacksInt32Array(minimumIntensityRaw, MAX_NUM_OF_CHANNELS, MeasuredImin_, 0); - if(!status) - status = doCallbacksInt32Array(maximumIntensityRaw, MAX_NUM_OF_CHANNELS, MeasuredImax_, 0); - if(!status) - status = doCallbacksFloat64Array(temperature, MAX_NUM_OF_CHANNELS, MeasuredTemp_, 0); - if(!status) - status = doCallbacksFloat64Array(airPressure, MAX_NUM_OF_CHANNELS, MeasuredPress_, 0); - if(!status) - status = doCallbacksFloat64Array(humidity, MAX_NUM_OF_CHANNELS, MeasuredHum_, 0); - if(!status) - status = doCallbacksInt32Array(analysisError, MAX_NUM_OF_CHANNELS, MeasuredAnalysisError_, 0); - if(!status) - status = doCallbacksInt32Array(beamBreak, MAX_NUM_OF_CHANNELS, MeasuredBeamInterruption_, 0); - if(!status) - status = doCallbacksInt32Array(temperatureError, MAX_NUM_OF_CHANNELS, MeasuredTemperatureError_, 0); - if(!status) - status = doCallbacksInt32Array(motionTolerance, MAX_NUM_OF_CHANNELS, MeasuredMovementToleranceError_, 0); - if(!status) - status = doCallbacksInt32Array(intensityError, MAX_NUM_OF_CHANNELS, MeasuredIntensityError_, 0); - if(!status) - status = doCallbacksInt32Array(connectionErrorUSB, MAX_NUM_OF_CHANNELS, MeasuredUsbConnectionError_, 0); - if(!status) - status = doCallbacksInt32Array(tcpServerError, MAX_NUM_OF_CHANNELS, MeasuredTcpServerError_, 0); - if(!status) - status = doCallbacksInt32Array(errorSettingLaserSpeed, MAX_NUM_OF_CHANNELS, MeasuredLaserSpeedError_, 0); - if(!status) - status = doCallbacksInt32Array(laserTemperatureError, MAX_NUM_OF_CHANNELS, MeasuredLaserTemperatureError_, 0); - if(!status) - status = doCallbacksInt32Array(daqErrorDuringDataAcq, MAX_NUM_OF_CHANNELS, MeasuredDaqError_, 0); - - for(int i = 0; i < numSelectedChannels; i++) + else { - if(measChEna_[i]) + double measuredLength[MAX_NUM_OF_CHANNELS]; + int minimumIntensityRaw[MAX_NUM_OF_CHANNELS]; + int maximumIntensityRaw[MAX_NUM_OF_CHANNELS]; + double temperature[MAX_NUM_OF_CHANNELS]; + double airPressure[MAX_NUM_OF_CHANNELS]; + double humidity[MAX_NUM_OF_CHANNELS]; + int analysisError[MAX_NUM_OF_CHANNELS]; + int beamBreak[MAX_NUM_OF_CHANNELS]; + int temperatureError[MAX_NUM_OF_CHANNELS]; + int motionToleranceError[MAX_NUM_OF_CHANNELS]; + int intensityError[MAX_NUM_OF_CHANNELS]; + int connectionErrorUSB[MAX_NUM_OF_CHANNELS]; + int tcpServerError[MAX_NUM_OF_CHANNELS]; + int errorSettingLaserSpeed[MAX_NUM_OF_CHANNELS]; + int laserTemperatureError[MAX_NUM_OF_CHANNELS]; + int daqErrorDuringDataAcq[MAX_NUM_OF_CHANNELS]; + int tcpServerErrorFinal; + int errorResult[MAX_NUM_OF_CHANNELS]; + if(!status) { + char * token; + + token = strtok(reply, "_"); + token = strtok(NULL, "_"); + + int channelNumber; + + // Update valid measure ID + int globalMeasCounter; + if(!status) + status = getIntegerParam(GlobalMeasCounter_, &globalMeasCounter); + spdlog::debug("Global measure counter: {}", globalMeasCounter); + globalMeasCounter++; if(!status) + status = setIntegerParam(GlobalMeasCounter_, globalMeasCounter); + + for(int i = 0; i < numSelectedChannels; i++) { - measCounter_[i]++; - status = doCallbacksInt32Array(measCounter_, MAX_NUM_OF_CHANNELS, MeasCounter_, 0); + if(measChEna_[i]) + { + sscanf(token, "%d,%lf,%d,%d,%lf,%lf,%lf,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &channelNumber, + measuredLength + i, + minimumIntensityRaw + i, + maximumIntensityRaw + i, + temperature + i, + airPressure + i, + humidity + i, + analysisError + i, + beamBreak + i, + temperatureError + i, + motionToleranceError + i, + intensityError + i, + connectionErrorUSB + i, + tcpServerError + i, + errorSettingLaserSpeed + i, + laserTemperatureError + i, + daqErrorDuringDataAcq + i); + token = strtok(NULL, "_"); + errorResult[i] = ((analysisError[i] << ANALYSIS_ERROR_BIT_POSITION) + + (beamBreak[i] << BEAM_BREAK_BIT_POSITION) + + (temperatureError[i] << TEMPERATURE_ERROR_BIT_POSITION) + + (motionToleranceError[i] << MOTION_TOLERANCE_ERROR_BIT_POSITION) + + (intensityError[i] << INTENSITY_ERROR_BIT_POSITION) + + (connectionErrorUSB[i] << CONNECTION_ERROR_USB_BIT_POSITION) + + (tcpServerError[i] << TCP_SERVER_ERROR_BIT_POSITION) + + (errorSettingLaserSpeed[i] << ERROR_SETTING_LASER_SPEED_BIT_POSITION) + + (laserTemperatureError[i] << LASER_TEMPERATURE_ERROR_BIT_POSITION) + + (daqErrorDuringDataAcq[i] << DAQ_ERROR_DURING_DATA_ACQ_BIT_POSITION) + + (tcpServerErrorFinal << TCP_SERVER_ERROR_FINAL_BIT_POSITION)) & errorMask_[i]; + spdlog::debug("Channel: {} Error mask: 0x{:X} Error result: 0x{:X}", channelList_[i], errorMask_[i], errorResult[i]); + // Update last valid measurement if no errors + if(errorResult[i] == 0) + { + if(!status) + status = doCallbacksFloat64Array(measuredLength, MAX_NUM_OF_CHANNELS, LastValidMeasuredLength_, 0); + if(!status) + status = doCallbacksInt32Array(minimumIntensityRaw, MAX_NUM_OF_CHANNELS, LastValidMeasuredImin_, 0); + if(!status) + status = doCallbacksInt32Array(maximumIntensityRaw, MAX_NUM_OF_CHANNELS, LastValidMeasuredImax_, 0); + if(!status) + status = doCallbacksFloat64Array(temperature, MAX_NUM_OF_CHANNELS, LastValidMeasuredTemp_, 0); + if(!status) + status = doCallbacksFloat64Array(airPressure, MAX_NUM_OF_CHANNELS, LastValidMeasuredPress_, 0); + if(!status) + status = doCallbacksFloat64Array(humidity, MAX_NUM_OF_CHANNELS, LastValidMeasuredHum_, 0); + // Update valid measurement counter per channel + lastValidMeasCounter_[i] = globalMeasCounter; + } + measCounter_[i] = globalMeasCounter; + } } + status = doCallbacksInt32Array(lastValidMeasCounter_, MAX_NUM_OF_CHANNELS, LastValidMeasCounter_, 0); + status = doCallbacksInt32Array(measCounter_, MAX_NUM_OF_CHANNELS, MeasCounter_, 0); + sscanf(token, "%d", &tcpServerErrorFinal); } - } + // Update current measurement + if(!status) + status = doCallbacksFloat64Array(measuredLength, MAX_NUM_OF_CHANNELS, MeasuredLength_, 0); + if(!status) + status = doCallbacksInt32Array(minimumIntensityRaw, MAX_NUM_OF_CHANNELS, MeasuredImin_, 0); + if(!status) + status = doCallbacksInt32Array(maximumIntensityRaw, MAX_NUM_OF_CHANNELS, MeasuredImax_, 0); + if(!status) + status = doCallbacksFloat64Array(temperature, MAX_NUM_OF_CHANNELS, MeasuredTemp_, 0); + if(!status) + status = doCallbacksFloat64Array(airPressure, MAX_NUM_OF_CHANNELS, MeasuredPress_, 0); + if(!status) + status = doCallbacksFloat64Array(humidity, MAX_NUM_OF_CHANNELS, MeasuredHum_, 0); + if(!status) + status = doCallbacksInt32Array(analysisError, MAX_NUM_OF_CHANNELS, MeasuredAnalysisError_, 0); + if(!status) + status = doCallbacksInt32Array(beamBreak, MAX_NUM_OF_CHANNELS, MeasuredBeamInterruption_, 0); + if(!status) + status = doCallbacksInt32Array(temperatureError, MAX_NUM_OF_CHANNELS, MeasuredTemperatureError_, 0); + if(!status) + status = doCallbacksInt32Array(motionToleranceError, MAX_NUM_OF_CHANNELS, MeasuredMovementToleranceError_, 0); + if(!status) + status = doCallbacksInt32Array(intensityError, MAX_NUM_OF_CHANNELS, MeasuredIntensityError_, 0); + if(!status) + status = doCallbacksInt32Array(connectionErrorUSB, MAX_NUM_OF_CHANNELS, MeasuredUsbConnectionError_, 0); + if(!status) + status = doCallbacksInt32Array(tcpServerError, MAX_NUM_OF_CHANNELS, MeasuredTcpServerError_, 0); + if(!status) + status = doCallbacksInt32Array(errorSettingLaserSpeed, MAX_NUM_OF_CHANNELS, MeasuredLaserSpeedError_, 0); + if(!status) + status = doCallbacksInt32Array(laserTemperatureError, MAX_NUM_OF_CHANNELS, MeasuredLaserTemperatureError_, 0); + if(!status) + status = doCallbacksInt32Array(daqErrorDuringDataAcq, MAX_NUM_OF_CHANNELS, MeasuredDaqError_, 0); - if(!status) - status = setIntegerParam(MeasState_, StateIdle); - } + if(!status) + status = setIntegerParam(MeasState_, StateIdle); + } } } else @@ -788,7 +816,7 @@ asynStatus EtalonMultiline2::writeInt32(asynUser *pasynUser, else pollingEnable_ = 0; } - if(function == AlignmentStart_) + else if(function == AlignmentStart_) { if(value) { @@ -801,8 +829,12 @@ asynStatus EtalonMultiline2::writeInt32(asynUser *pasynUser, if(!status) status = setIntegerParam(AlignmentStart_, 0); } + else + status = asynPortDriver::writeInt32(pasynUser, value); + if(!status) status = callParamCallbacks(); + return status; } @@ -817,6 +849,12 @@ asynStatus EtalonMultiline2::readInt32Array(asynUser *pasynUser, { memcpy(measChEna_, value, MAX_NUM_OF_CHANNELS*sizeof(int)); } + else if(function == ErrorMask_) + { + memcpy(errorMask_, value, MAX_NUM_OF_CHANNELS*sizeof(int)); + } + else + status = asynPortDriver::readInt32Array(pasynUser, value, nElements, nIn); *nIn = nElements; return status; } diff --git a/etalonMultiLine2App/src/etalonMultiLine2.h b/etalonMultiLine2App/src/etalonMultiLine2.h index 6e31063..bcb91d8 100644 --- a/etalonMultiLine2App/src/etalonMultiLine2.h +++ b/etalonMultiLine2App/src/etalonMultiLine2.h @@ -1,3 +1,18 @@ +#include <iocsh.h> +#include <epicsThread.h> +#include <epicsEvent.h> +#include <epicsExport.h> +#include <string.h> +#include <epicsExit.h> + +#include <signal.h> +#include "spdlog/spdlog.h" + +#include <asynPortDriver.h> +#include <asynOctetSyncIO.h> + +#define EPICS_THREAD_CAN_JOIN + #define MAX_NUM_OF_CHANNELS 40 #define MAX_QUERY_SIZE 1000 #define MAX_REPLY_SIZE 1000 @@ -6,6 +21,18 @@ #define CHANNEL_SEPARATOR "_" #define VALUE_WITHIN_CHANNEL_SEPARATOR "," +#define ANALYSIS_ERROR_BIT_POSITION 0 +#define BEAM_BREAK_BIT_POSITION 1 +#define TEMPERATURE_ERROR_BIT_POSITION 2 +#define MOTION_TOLERANCE_ERROR_BIT_POSITION 3 +#define INTENSITY_ERROR_BIT_POSITION 4 +#define CONNECTION_ERROR_USB_BIT_POSITION 5 +#define TCP_SERVER_ERROR_BIT_POSITION 6 +#define ERROR_SETTING_LASER_SPEED_BIT_POSITION 7 +#define LASER_TEMPERATURE_ERROR_BIT_POSITION 8 +#define DAQ_ERROR_DURING_DATA_ACQ_BIT_POSITION 9 +#define TCP_SERVER_ERROR_FINAL_BIT_POSITION 10 + class EtalonMultiline2 : public asynPortDriver { @@ -56,6 +83,9 @@ protected: int AlignDataMax_; int AlignDataMin_; + int GlobalMeasCounter_; + + int MeasCounter_; int MeasuredLength_; int MeasuredImin_; int MeasuredImax_; @@ -63,6 +93,15 @@ protected: int MeasuredPress_; int MeasuredHum_; + int LastValidMeasCounter_; + int LastValidMeasuredLength_; + int LastValidMeasuredImin_; + int LastValidMeasuredImax_; + int LastValidMeasuredTemp_; + int LastValidMeasuredPress_; + int LastValidMeasuredHum_; + + int ErrorMask_; int MeasuredAnalysisError_; int MeasuredBeamInterruption_; int MeasuredTemperatureError_; @@ -73,7 +112,6 @@ protected: int MeasuredLaserSpeedError_; int MeasuredLaserTemperatureError_; int MeasuredDaqError_; - int MeasCounter_; private: asynUser *pasynUserOctet_; @@ -92,11 +130,13 @@ private: epicsInt32 gains_[MAX_NUM_OF_CHANNELS]; epicsInt32 measChEna_[MAX_NUM_OF_CHANNELS]; epicsFloat64 measPreshot_[MAX_NUM_OF_CHANNELS]; + epicsInt32 errorMask_[MAX_NUM_OF_CHANNELS]; + epicsInt32 measCounter_[MAX_NUM_OF_CHANNELS]; + epicsInt32 lastValidMeasCounter_[MAX_NUM_OF_CHANNELS]; epicsInt32 pollingEnable_; epicsInt32 initialPolling_; - - epicsInt32 measCounter_[MAX_NUM_OF_CHANNELS]; + epicsInt64 measureCurrentID_; enum MeasurementState { -- GitLab From f318a4ab5e16f9d05e5b7b8e5d7475b02c3470c0 Mon Sep 17 00:00:00 2001 From: George Kontogiorgos <george.kontogiorgos@ess.eu> Date: Wed, 27 Sep 2023 16:52:03 +0200 Subject: [PATCH 5/5] Add missing PV for general server error --- etalonMultiLine2App/Db/data.template | 2 +- etalonMultiLine2App/Db/error.template | 9 +++++++++ etalonMultiLine2App/src/etalonMultiLine2.cpp | 5 +++++ etalonMultiLine2App/src/etalonMultiLine2.h | 1 + 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/etalonMultiLine2App/Db/data.template b/etalonMultiLine2App/Db/data.template index 2b21c26..104cceb 100644 --- a/etalonMultiLine2App/Db/data.template +++ b/etalonMultiLine2App/Db/data.template @@ -18,7 +18,7 @@ record(waveform, "$(P)$(R)DataLenLength-R") { field(NELM, "40") } -record(waveform, "$(P)$(R)LstValDataLenLength-R") { +record(waveform, "$(P)$(R)LstVldDataLenLength-R") { field(DESC, "Last valid Li: measured length") field(DTYP, "asynFloat64ArrayIn") field(EGU, "mm") diff --git a/etalonMultiLine2App/Db/error.template b/etalonMultiLine2App/Db/error.template index 85eb9f6..793e06b 100644 --- a/etalonMultiLine2App/Db/error.template +++ b/etalonMultiLine2App/Db/error.template @@ -101,3 +101,12 @@ record(waveform, "$(P)$(R)DataLenDAQErr-R") { field(FTVL, "LONG") field(NELM, "40") } + +record(bi, "$(P)$(R)TcpFinalServerErr-R") { + field(DESC, "SE: TCP server error") + field(DTYP, "asynInt32") + field(ZNAM, "False") + field(ONAM, "True") + field(INP, "@asyn($(PORT),$(ADDR))TCP_FINAL_SERVER_ERROR") + field(SCAN, "I/O Intr") +} diff --git a/etalonMultiLine2App/src/etalonMultiLine2.cpp b/etalonMultiLine2App/src/etalonMultiLine2.cpp index c7951c5..21ecad8 100644 --- a/etalonMultiLine2App/src/etalonMultiLine2.cpp +++ b/etalonMultiLine2App/src/etalonMultiLine2.cpp @@ -98,6 +98,7 @@ EtalonMultiline2::EtalonMultiline2(const char *portName, createParam("MEASURED_LASER_SPEED_ERROR", asynParamInt32Array, &MeasuredLaserSpeedError_); createParam("MEASURED_LASER_TEMPERATURE_ERROR", asynParamInt32Array, &MeasuredLaserTemperatureError_); createParam("MEASURED_DAQ_ERROR", asynParamInt32Array, &MeasuredDaqError_); + createParam("TCP_FINAL_SERVER_ERROR", asynParamInt32, &TcpFinalServerError_); /* Enable debug level */ if(enableDebug) @@ -651,6 +652,10 @@ asynStatus EtalonMultiline2::performMeasurement(asynStatus status) status = doCallbacksInt32Array(lastValidMeasCounter_, MAX_NUM_OF_CHANNELS, LastValidMeasCounter_, 0); status = doCallbacksInt32Array(measCounter_, MAX_NUM_OF_CHANNELS, MeasCounter_, 0); sscanf(token, "%d", &tcpServerErrorFinal); + if(!status) + status = setIntegerParam(TcpFinalServerError_, tcpServerErrorFinal); + if(!status) + status = callParamCallbacks(); } // Update current measurement if(!status) diff --git a/etalonMultiLine2App/src/etalonMultiLine2.h b/etalonMultiLine2App/src/etalonMultiLine2.h index bcb91d8..c12468e 100644 --- a/etalonMultiLine2App/src/etalonMultiLine2.h +++ b/etalonMultiLine2App/src/etalonMultiLine2.h @@ -112,6 +112,7 @@ protected: int MeasuredLaserSpeedError_; int MeasuredLaserTemperatureError_; int MeasuredDaqError_; + int TcpFinalServerError_; private: asynUser *pasynUserOctet_; -- GitLab