
- Added a multicountsersec to teplace hmcontrol and multicounter - Fixed a case sensitivity bug in haddcheck - Made oscillate work with second generation motors for POLDI - Added a time stamper to trace. Now there will be time stamps in trace files which allow to correlate things from the master log with the trace. - Updated polterwrite. - Updated testprot to work with the behave test
182 lines
4.6 KiB
C
182 lines
4.6 KiB
C
/**
|
|
* This is a protocol handler for the Munich sputter system. The protocol
|
|
* is described in a separate manual. Messages to send look like this:
|
|
*
|
|
* 2 character length of message + command=value or ? + checksum
|
|
*
|
|
* Responses come like this:
|
|
*
|
|
* 2 characters length + status = transmission code + checksum
|
|
* 2 character length + 2 characters command status + command=value + checksum
|
|
*
|
|
* An additional feauture is that the Labview server closes the connection after
|
|
* each communication.........
|
|
*
|
|
* I am lazy: rather then creating a private data structure I use the line count
|
|
* to keep track of the 2 messages expected as reply. The linecount also signals
|
|
* reconnect with a value of -10
|
|
*
|
|
* Mark Koennecke, October 2013
|
|
*/
|
|
#include <errno.h>
|
|
#include <ascon.h>
|
|
#include <ascon.i>
|
|
|
|
static int mustReadMore(Ascon *a)
|
|
{
|
|
int len;
|
|
char lenString[3], *cmd;
|
|
|
|
if(GetDynStringLength(a->rdBuffer) < 2){
|
|
return 1;
|
|
}
|
|
cmd = GetCharArray(a->rdBuffer);
|
|
memset(lenString,0,sizeof(lenString));
|
|
lenString[0] = cmd[0];
|
|
lenString[1] = cmd[1];
|
|
len = atoi(lenString);
|
|
if(GetDynStringLength(a->rdBuffer) < len + 2){ /* length + checksum */
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
/*-------------------------------------------------------------------------------*/
|
|
static void processStatusLine(Ascon *a)
|
|
{
|
|
char *cmd, *pPtr;
|
|
int status;
|
|
|
|
cmd = GetCharArray(a->rdBuffer);
|
|
if(strstr(cmd,"status") == NULL){
|
|
AsconError(a,"wrong reply",0);
|
|
return;
|
|
}
|
|
pPtr = strchr(cmd,'=');
|
|
pPtr++;
|
|
pPtr[3] = '\0';
|
|
status = atoi(pPtr);
|
|
if(status != 10) {
|
|
AsconError(a,"bad transmission status",status);
|
|
}
|
|
DynStringClear(a->rdBuffer);
|
|
a->lineCount++;
|
|
}
|
|
/*-------------------------------------------------------------------------------*/
|
|
static void processPayLoad(Ascon *a)
|
|
{
|
|
char *cmd, code[3];
|
|
int status, len;
|
|
|
|
cmd = strdup(GetCharArray(a->rdBuffer));
|
|
memset(code,0,sizeof(code));
|
|
code[0] = cmd[2];
|
|
code[1] = cmd[3];
|
|
status = atoi(code);
|
|
switch(status){
|
|
case 30:
|
|
len = strlen(cmd);
|
|
cmd[len-2] = '\0';
|
|
DynStringClear(a->rdBuffer);
|
|
DynStringConcat(a->rdBuffer,cmd+4);
|
|
break;
|
|
case 35:
|
|
DynStringClear(a->rdBuffer);
|
|
DynStringConcat(a->rdBuffer,"ERROR: Command unknown");
|
|
break;
|
|
case 36:
|
|
DynStringClear(a->rdBuffer);
|
|
DynStringConcat(a->rdBuffer,"ERROR: Syntax error");
|
|
break;
|
|
case 37:
|
|
DynStringClear(a->rdBuffer);
|
|
DynStringConcat(a->rdBuffer,"ERROR: out of range");
|
|
break;
|
|
}
|
|
free(cmd);
|
|
a->state = AsconReadDone;
|
|
a->lineCount = -10;
|
|
}
|
|
/*-------------------------------------------------------------------------------*/
|
|
static int SputterHandler(Ascon *a)
|
|
{
|
|
char *cmd, lenString[3], chr;
|
|
int len, checksum, i, ret;
|
|
|
|
switch(a->state){
|
|
case AsconWriteStart:
|
|
/*
|
|
reconnect when something had been done
|
|
*/
|
|
if(a->lineCount == -10){
|
|
AsconReconnect(a,NULL);
|
|
a->lineCount = 0;
|
|
return 1;
|
|
}
|
|
/*
|
|
Prepend length and append checksum
|
|
*/
|
|
cmd = strdup(GetCharArray(a->wrBuffer));
|
|
len = strlen(cmd) + 2;
|
|
DynStringClear(a->wrBuffer);
|
|
sprintf(lenString,"%02d",len);
|
|
DynStringConcat(a->wrBuffer,lenString);
|
|
DynStringConcat(a->wrBuffer,cmd);
|
|
free(cmd);
|
|
cmd = GetCharArray(a->wrBuffer);
|
|
for(i = 0, checksum = 0; i < strlen(cmd); i++){
|
|
checksum += (int)cmd[i];
|
|
}
|
|
checksum = checksum % 256;
|
|
sprintf(lenString,"%2X",checksum);
|
|
if(lenString[0] == ' ') {
|
|
lenString[0] = '0';
|
|
}
|
|
DynStringConcat(a->wrBuffer,lenString);
|
|
a->state = AsconWriting;
|
|
a->lineCount = 0;
|
|
a->wrPos = 0;
|
|
DynStringClear(a->rdBuffer);
|
|
break;
|
|
case AsconReading:
|
|
if(mustReadMore(a)){
|
|
ret = AsconReadChar(a->fd, &chr);
|
|
if (ret < 0) {
|
|
/* EINTR means we must retry */
|
|
if (errno != EINTR && errno != EAGAIN) {
|
|
AsconError(a, "AsconReadChar failed:", errno);
|
|
}
|
|
} else if (ret > 0) {
|
|
DynStringConcatChar(a->rdBuffer,chr);
|
|
}
|
|
} else {
|
|
if(a->lineCount == 0) {
|
|
processStatusLine(a);
|
|
} else {
|
|
processPayLoad(a);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
return AsconStdHandler(a);
|
|
}
|
|
return 1;
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
static int SputterInit(Ascon *a, SConnection *con, int argc, char *argv[])
|
|
{
|
|
a->hostport = strdup(argv[1]);
|
|
a->timeout = 3*60;
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------------*/
|
|
void AddSputterProtocoll()
|
|
{
|
|
AsconProtocol *prot = NULL;
|
|
|
|
prot = calloc(sizeof(AsconProtocol), 1);
|
|
prot->name = strdup("sputter");
|
|
prot->init = SputterInit;
|
|
prot->handler = SputterHandler;
|
|
AsconInsertProtocol(prot);
|
|
}
|