Improved the error message when the error is printed.
This commit is contained in:
@ -864,12 +864,8 @@ asynStatus pmacv3Axis::readEncoderType() {
|
|||||||
|
|
||||||
int reponse_length = strlen(response);
|
int reponse_length = strlen(response);
|
||||||
if (reponse_length < 3) {
|
if (reponse_length < 3) {
|
||||||
asynPrint(
|
return pC_->errMsgCouldNotParseResponse(command, response, axisNo_,
|
||||||
pC_->pasynUserSelf, ASYN_TRACE_ERROR,
|
__PRETTY_FUNCTION__, __LINE__);
|
||||||
"%s => line %d:\nUnexpected reponse '%s' from axis %d on "
|
|
||||||
"controller %s while reading the encoder type. Aborting....\n",
|
|
||||||
__PRETTY_FUNCTION__, __LINE__, response, axisNo_, pC_->portName);
|
|
||||||
return asynError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are only interested in the last two digits and the last value in
|
// We are only interested in the last two digits and the last value in
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "asynMotorController.h"
|
#include "asynMotorController.h"
|
||||||
#include "asynOctetSyncIO.h"
|
#include "asynOctetSyncIO.h"
|
||||||
#include "pmacv3Axis.h"
|
#include "pmacv3Axis.h"
|
||||||
|
#include <cstring>
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
#include <errlog.h>
|
#include <errlog.h>
|
||||||
#include <iocsh.h>
|
#include <iocsh.h>
|
||||||
@ -11,6 +12,21 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copy src into dst and replace all carriage returns with spaces
|
||||||
|
*
|
||||||
|
* @param dst Buffer for the modified string
|
||||||
|
* @param src Original string
|
||||||
|
*/
|
||||||
|
void adjustResponseForPrint(char *dst, const char *src) {
|
||||||
|
strcpy(dst, src);
|
||||||
|
for (size_t i = 0; i < strlen(dst); i++) {
|
||||||
|
if (dst[i] == '\r') {
|
||||||
|
dst[i] = '_';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Construct a new pmacv3Controller::pmacv3Controller object
|
* @brief Construct a new pmacv3Controller::pmacv3Controller object
|
||||||
*
|
*
|
||||||
@ -192,8 +208,9 @@ asynStatus pmacv3Controller::writeRead(int axisNo, const char *command,
|
|||||||
// Definition of local variables.
|
// Definition of local variables.
|
||||||
asynStatus status = asynSuccess;
|
asynStatus status = asynSuccess;
|
||||||
asynStatus pl_status = asynSuccess;
|
asynStatus pl_status = asynSuccess;
|
||||||
char full_command[MAXBUF_] = {0};
|
char fullCommand[MAXBUF_] = {0};
|
||||||
char user_message[MAXBUF_] = {0};
|
char drvMessageText[MAXBUF_] = {0};
|
||||||
|
char modResponse[MAXBUF_] = {0};
|
||||||
int motorStatusProblem = 0;
|
int motorStatusProblem = 0;
|
||||||
int numReceivedResponses = 0;
|
int numReceivedResponses = 0;
|
||||||
|
|
||||||
@ -232,7 +249,7 @@ asynStatus pmacv3Controller::writeRead(int axisNo, const char *command,
|
|||||||
this protocol encodes the message length at the beginning. See Turbo PMAC
|
this protocol encodes the message length at the beginning. See Turbo PMAC
|
||||||
User Manual, page 418 in VR_PMAC_GETRESPONSE
|
User Manual, page 418 in VR_PMAC_GETRESPONSE
|
||||||
|
|
||||||
The message has to be build manually into the buffer full_command, since it
|
The message has to be build manually into the buffer fullCommand, since it
|
||||||
contains NULL terminators in its middle, therefore the string manipulation
|
contains NULL terminators in its middle, therefore the string manipulation
|
||||||
methods of C don't work.
|
methods of C don't work.
|
||||||
*/
|
*/
|
||||||
@ -242,20 +259,20 @@ asynStatus pmacv3Controller::writeRead(int axisNo, const char *command,
|
|||||||
strlen(command) + 1; // +1 because of the appended /r
|
strlen(command) + 1; // +1 because of the appended /r
|
||||||
const int offset = 8;
|
const int offset = 8;
|
||||||
|
|
||||||
// Positions 2 to 6 must have the value 0. Since full_command is initialized
|
// Positions 2 to 6 must have the value 0. Since fullCommand is initialized
|
||||||
// as an array of zeros, we don't need to set these bits manually.
|
// as an array of zeros, we don't need to set these bits manually.
|
||||||
full_command[0] = '\x40';
|
fullCommand[0] = '\x40';
|
||||||
full_command[1] = '\xBF';
|
fullCommand[1] = '\xBF';
|
||||||
full_command[7] = commandLength;
|
fullCommand[7] = commandLength;
|
||||||
|
|
||||||
snprintf((char *)full_command + offset, MAXBUF_ - offset, "%s\r", command);
|
snprintf((char *)fullCommand + offset, MAXBUF_ - offset, "%s\r", command);
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,
|
asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,
|
||||||
"%s => line %d:\nSending command %s", __PRETTY_FUNCTION__,
|
"%s => line %d:\nSending command %s", __PRETTY_FUNCTION__,
|
||||||
__LINE__, full_command);
|
__LINE__, fullCommand);
|
||||||
|
|
||||||
// Perform the actual writeRead
|
// Perform the actual writeRead
|
||||||
status = pasynOctetSyncIO->writeRead(
|
status = pasynOctetSyncIO->writeRead(
|
||||||
lowLevelPortUser_, full_command, commandLength + offset, response,
|
lowLevelPortUser_, fullCommand, commandLength + offset, response,
|
||||||
MAXBUF_, comTimeout_, &nbytesOut, &nbytesIn, &eomReason);
|
MAXBUF_, comTimeout_, &nbytesOut, &nbytesIn, &eomReason);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -291,7 +308,7 @@ asynStatus pmacv3Controller::writeRead(int axisNo, const char *command,
|
|||||||
if (status == asynSuccess) {
|
if (status == asynSuccess) {
|
||||||
// If flushing the MCU succeded, try to send the command again
|
// If flushing the MCU succeded, try to send the command again
|
||||||
status = pasynOctetSyncIO->writeRead(
|
status = pasynOctetSyncIO->writeRead(
|
||||||
lowLevelPortUser_, full_command, commandLength + offset,
|
lowLevelPortUser_, fullCommand, commandLength + offset,
|
||||||
response, MAXBUF_, comTimeout_, &nbytesOut, &nbytesIn,
|
response, MAXBUF_, comTimeout_, &nbytesOut, &nbytesIn,
|
||||||
&eomReason);
|
&eomReason);
|
||||||
|
|
||||||
@ -306,15 +323,19 @@ asynStatus pmacv3Controller::writeRead(int axisNo, const char *command,
|
|||||||
|
|
||||||
// Second check: If this fails, give up and propagate the error.
|
// Second check: If this fails, give up and propagate the error.
|
||||||
if (numExpectedResponses != numReceivedResponses) {
|
if (numExpectedResponses != numReceivedResponses) {
|
||||||
asynPrint(
|
|
||||||
this->pasynUserSelf, ASYN_TRACE_ERROR,
|
adjustResponseForPrint(modResponse, response);
|
||||||
"%s => line %d:\nUnexpected response %s for command %s\n",
|
|
||||||
__PRETTY_FUNCTION__, __LINE__, response, command);
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
snprintf(user_message, sizeof(user_message),
|
"%s => line %d:\nUnexpected response %s (_ are "
|
||||||
"Received unexpected response %s for command %s. "
|
"carriage returns) for command %s\n",
|
||||||
|
__PRETTY_FUNCTION__, __LINE__, modResponse, command);
|
||||||
|
snprintf(drvMessageText, sizeof(drvMessageText),
|
||||||
|
"Received unexpected response %s (_ are "
|
||||||
|
"carriage returns) for command %s. "
|
||||||
"Please call the support",
|
"Please call the support",
|
||||||
response, command);
|
modResponse, command);
|
||||||
pl_status = setStringParam(motorMessageText_, user_message);
|
pl_status = setStringParam(motorMessageText_, drvMessageText);
|
||||||
if (pl_status != asynSuccess) {
|
if (pl_status != asynSuccess) {
|
||||||
return paramLibAccessFailed(pl_status, "motorMessageText_",
|
return paramLibAccessFailed(pl_status, "motorMessageText_",
|
||||||
__PRETTY_FUNCTION__, __LINE__);
|
__PRETTY_FUNCTION__, __LINE__);
|
||||||
@ -330,23 +351,24 @@ asynStatus pmacv3Controller::writeRead(int axisNo, const char *command,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create custom error messages for different failure modes
|
// Create custom error messages for different failure modes
|
||||||
if (strlen(user_message) == 0) {
|
if (strlen(drvMessageText) == 0) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case asynSuccess:
|
case asynSuccess:
|
||||||
break; // Communicate nothing
|
break; // Communicate nothing
|
||||||
case asynTimeout:
|
case asynTimeout:
|
||||||
snprintf(user_message, sizeof(user_message),
|
snprintf(drvMessageText, sizeof(drvMessageText),
|
||||||
"connection timeout for axis %d", axisNo);
|
"connection timeout for axis %d", axisNo);
|
||||||
break;
|
break;
|
||||||
case asynDisconnected:
|
case asynDisconnected:
|
||||||
snprintf(user_message, sizeof(user_message),
|
snprintf(drvMessageText, sizeof(drvMessageText),
|
||||||
"axis is not connected");
|
"axis is not connected");
|
||||||
break;
|
break;
|
||||||
case asynDisabled:
|
case asynDisabled:
|
||||||
snprintf(user_message, sizeof(user_message), "axis is disabled");
|
snprintf(drvMessageText, sizeof(drvMessageText),
|
||||||
|
"axis is disabled");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
snprintf(user_message, sizeof(user_message),
|
snprintf(drvMessageText, sizeof(drvMessageText),
|
||||||
"Communication failed (%s)", stringifyAsynStatus(status));
|
"Communication failed (%s)", stringifyAsynStatus(status));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -367,7 +389,7 @@ asynStatus pmacv3Controller::writeRead(int axisNo, const char *command,
|
|||||||
|
|
||||||
if (motorStatusProblem == 0) {
|
if (motorStatusProblem == 0) {
|
||||||
pl_status =
|
pl_status =
|
||||||
axis->setStringParam(this->motorMessageText_, user_message);
|
axis->setStringParam(this->motorMessageText_, drvMessageText);
|
||||||
if (pl_status != asynSuccess) {
|
if (pl_status != asynSuccess) {
|
||||||
return paramLibAccessFailed(pl_status, "motorMessageText_",
|
return paramLibAccessFailed(pl_status, "motorMessageText_",
|
||||||
__PRETTY_FUNCTION__, __LINE__);
|
__PRETTY_FUNCTION__, __LINE__);
|
||||||
@ -377,16 +399,18 @@ asynStatus pmacv3Controller::writeRead(int axisNo, const char *command,
|
|||||||
|
|
||||||
// Log the overall status (communication successfull or not)
|
// Log the overall status (communication successfull or not)
|
||||||
if (status == asynSuccess) {
|
if (status == asynSuccess) {
|
||||||
|
|
||||||
asynPrint(lowLevelPortUser_, ASYN_TRACEIO_DRIVER,
|
asynPrint(lowLevelPortUser_, ASYN_TRACEIO_DRIVER,
|
||||||
"%s => line %d:\nDevice response: %s\n", __PRETTY_FUNCTION__,
|
"%s => line %d:\nDevice response: %s (_ are "
|
||||||
__LINE__, response);
|
"carriage returns)\n",
|
||||||
|
__PRETTY_FUNCTION__, __LINE__, modResponse);
|
||||||
pl_status = axis->setIntegerParam(this->motorStatusCommsError_, 0);
|
pl_status = axis->setIntegerParam(this->motorStatusCommsError_, 0);
|
||||||
} else {
|
} else {
|
||||||
if (status == asynSuccess) {
|
if (status == asynSuccess) {
|
||||||
asynPrint(
|
asynPrint(
|
||||||
lowLevelPortUser_, ASYN_TRACE_ERROR,
|
lowLevelPortUser_, ASYN_TRACE_ERROR,
|
||||||
"%s => line %d:\nCommunication failed for command %s (%s)\n",
|
"%s => line %d:\nCommunication failed for command %s (%s)\n",
|
||||||
__PRETTY_FUNCTION__, __LINE__, full_command,
|
__PRETTY_FUNCTION__, __LINE__, fullCommand,
|
||||||
stringifyAsynStatus(status));
|
stringifyAsynStatus(status));
|
||||||
pl_status = axis->setIntegerParam(this->motorStatusCommsError_, 1);
|
pl_status = axis->setIntegerParam(this->motorStatusCommsError_, 1);
|
||||||
}
|
}
|
||||||
@ -420,6 +444,15 @@ asynStatus pmacv3Controller::writeInt32(asynUser *pasynUser, epicsInt32 value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asynStatus pmacv3Controller::errMsgCouldNotParseResponse(
|
||||||
|
const char *command, const char *response, int axisNo,
|
||||||
|
const char *functionName, int lineNumber) {
|
||||||
|
char modifiedResponse[MAXBUF_] = {0};
|
||||||
|
adjustResponseForPrint(modifiedResponse, response);
|
||||||
|
return sinqController::errMsgCouldNotParseResponse(
|
||||||
|
command, modifiedResponse, axisNo, functionName, lineNumber);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************************/
|
/*************************************************************************************/
|
||||||
/** The following functions are C-wrappers, and can be called directly from
|
/** The following functions are C-wrappers, and can be called directly from
|
||||||
* iocsh */
|
* iocsh */
|
||||||
|
@ -93,6 +93,29 @@ class pmacv3Controller : public sinqController {
|
|||||||
*/
|
*/
|
||||||
pmacv3Axis *castToAxis(asynMotorAxis *asynAxis);
|
pmacv3Axis *castToAxis(asynMotorAxis *asynAxis);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Specialized version of sinqController::errMsgCouldNotParseResponse
|
||||||
|
* for pmacv3
|
||||||
|
*
|
||||||
|
* This is an overloaded version of
|
||||||
|
* sinqController::errMsgCouldNotParseResponse which calls
|
||||||
|
* adjustResponseForLogging on response before handing it over to
|
||||||
|
* sinqController::errMsgCouldNotParseResponse.
|
||||||
|
*
|
||||||
|
* @param command Command which led to the unparseable message
|
||||||
|
* @param response Response which wasn't parseable
|
||||||
|
* @param axisNo_ Axis where the problem occurred
|
||||||
|
* @param functionName Name of the caller function. It is recommended
|
||||||
|
to use a macro, e.g. __func__ or __PRETTY_FUNCTION__.
|
||||||
|
* @param lineNumber Source code line where this function is
|
||||||
|
called. It is recommended to use a macro, e.g. __LINE__.
|
||||||
|
* @return asynStatus Returns asynError.
|
||||||
|
*/
|
||||||
|
asynStatus errMsgCouldNotParseResponse(const char *command,
|
||||||
|
const char *response, int axisNo_,
|
||||||
|
const char *functionName,
|
||||||
|
int lineNumber);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Set the maximum buffer size. This is an empirical value which must be
|
// Set the maximum buffer size. This is an empirical value which must be
|
||||||
// large enough to avoid overflows for all commands to the device /
|
// large enough to avoid overflows for all commands to the device /
|
||||||
|
Reference in New Issue
Block a user