- Added protocol from phytron MCCC-2 motor controller
- Modified lmd200.c to reflect new additional values
This commit is contained in:
116
lmd200.c
116
lmd200.c
@ -13,12 +13,14 @@
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, October 2007
|
||||
*
|
||||
* modifed to use asynnet and to cope with even more data.
|
||||
* Mark Koennecke, June 2009
|
||||
*/
|
||||
#include <sics.h>
|
||||
#include <sicsobj.h>
|
||||
#include <sicshipadaba.h>
|
||||
#include <network.h>
|
||||
#include <nwatch.h>
|
||||
#include <asynnet.h>
|
||||
#include <commandlog.h>
|
||||
#include <stptok.h>
|
||||
/*
|
||||
@ -32,11 +34,9 @@
|
||||
*/
|
||||
#define BUFLEN 1024
|
||||
typedef struct {
|
||||
int state;
|
||||
char host[256];
|
||||
int port;
|
||||
mkChannel *pSock;
|
||||
pNWContext watchContext;
|
||||
int asChannel;
|
||||
char lineBuffer[BUFLEN];
|
||||
} LMD200, *pLMD200;
|
||||
/*----------------------------------------------------------------------------*/
|
||||
@ -46,16 +46,9 @@ static void killLMD200(void *data)
|
||||
if (priv == NULL) {
|
||||
return;
|
||||
}
|
||||
if (priv->watchContext != NULL) {
|
||||
NetWatchRemoveCallback(priv->watchContext);
|
||||
}
|
||||
if (priv->pSock != NULL) {
|
||||
NETClosePort(priv->pSock);
|
||||
free(priv->pSock);
|
||||
}
|
||||
ANETclose(priv->asChannel);
|
||||
free(priv);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void setAlarm(pSICSOBJ self, char *text)
|
||||
{
|
||||
@ -143,72 +136,55 @@ static void interpretLine(pSICSOBJ self, pLMD200 priv)
|
||||
{
|
||||
pHdb node = NULL;
|
||||
|
||||
switch (priv->state) {
|
||||
case IDLE:
|
||||
node = GetHipadabaNode(self->objectNode, "data");
|
||||
assert(node != NULL);
|
||||
|
||||
/*
|
||||
* TODO: check the message headers against what is now coming out
|
||||
* of the device.
|
||||
*/
|
||||
if (strstr(priv->lineBuffer, "Alarm") != NULL) {
|
||||
doAlarm(self, priv->lineBuffer);
|
||||
return;
|
||||
} else if (strstr(priv->lineBuffer, "Pre") != NULL) {
|
||||
setAlarm(self, priv->lineBuffer);
|
||||
} else {
|
||||
priv->state = WAITDATA1;
|
||||
setAlarm(self, "I do not feel very alarmed");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case WAITDATA1:
|
||||
if (strstr(priv->lineBuffer, "...0") == NULL) {
|
||||
/* this data is out of order, recover... */
|
||||
priv->state = IDLE;
|
||||
return;
|
||||
}
|
||||
} else if (strstr(priv->lineBuffer, "...0") == NULL) {
|
||||
storeData(self, 0, priv->lineBuffer);
|
||||
priv->state = WAITDATA2;
|
||||
break;
|
||||
case WAITDATA2:
|
||||
if (strstr(priv->lineBuffer, "...0") == NULL) {
|
||||
/* this data is out of order, recover... */
|
||||
priv->state = IDLE;
|
||||
return;
|
||||
}
|
||||
storeData(self, 8, priv->lineBuffer);
|
||||
priv->state = IDLE;
|
||||
node = GetHipadabaNode(self->objectNode, "data");
|
||||
assert(node != NULL);
|
||||
NotifyHipadabaPar(node, NULL);
|
||||
break;
|
||||
return;
|
||||
} else if(strstr(priv->lineBuffer,"..000") == NULL) {
|
||||
storeData(self, 8, priv->lineBuffer);
|
||||
NotifyHipadabaPar(node, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* This handles the terminator discovery and causes the evaluation of complete
|
||||
* lines.
|
||||
* --------------------------------------------------------------------------*/
|
||||
static int LMD200Callback(void *context, int mode)
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int LMD200Callback(int handle, void *userData)
|
||||
{
|
||||
pSICSOBJ self = (pSICSOBJ) context;
|
||||
pLMD200 priv = NULL;
|
||||
char buffer[512], *pPtr = NULL, line[132];
|
||||
pSICSOBJ self = (pSICSOBJ)userData;
|
||||
pLMD200 priv = (pLMD200)self->pPrivate;
|
||||
char *pPtr = NULL, *pEnd = NULL;
|
||||
int length;
|
||||
|
||||
assert(self != NULL);
|
||||
priv = (pLMD200) self->pPrivate;
|
||||
if (mode == nwatch_read) {
|
||||
memset(buffer, 0, 512);
|
||||
memset(line, 0, 132);
|
||||
NETRead(priv->pSock, buffer, 512, 0);
|
||||
pPtr = stptok(buffer, line, 132, "\r");
|
||||
while (pPtr != NULL) {
|
||||
if (strlen(line) > 3) {
|
||||
strncpy(priv->lineBuffer, line, BUFLEN);
|
||||
pPtr = ANETreadPtr(priv->asChannel,&length);
|
||||
pEnd = strchr(pPtr,(int)'\r');
|
||||
if(pEnd != NULL){
|
||||
length = pEnd - pPtr;
|
||||
*pEnd = '\0';
|
||||
strncpy(priv->lineBuffer,pPtr,BUFLEN);
|
||||
ANETreadConsume(priv->asChannel,length+1);
|
||||
interpretLine(self,priv);
|
||||
priv->lineBuffer[0] = '\0';
|
||||
}
|
||||
pPtr = stptok(pPtr, line, 132, "\r");
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int ClearCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
setAlarm(ccmd,"I do not feel very alarmed...");
|
||||
SCSendOK(con);
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int MakeLMD200(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
@ -228,8 +204,8 @@ int MakeLMD200(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
memset(priv, 0, sizeof(LMD200));
|
||||
strncpy(priv->host, argv[2], 256);
|
||||
priv->port = atoi(argv[3]);
|
||||
priv->pSock = NETConnect(priv->host, priv->port);
|
||||
if (priv->pSock == NULL) {
|
||||
priv->asChannel = ANETconnect(priv->host, priv->port);
|
||||
if (priv->asChannel < 0) {
|
||||
SCWrite(pCon, "ERROR: failed to connect to LMD200", eError);
|
||||
killLMD200(priv);
|
||||
return 0;
|
||||
@ -240,14 +216,16 @@ int MakeLMD200(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
return 0;
|
||||
}
|
||||
textValue = MakeHdbText("I do not feel very alarmed");
|
||||
dataValue = makeHdbValue(HIPFLOATAR, 16);
|
||||
dataValue = makeHdbValue(HIPFLOATAR, 32);
|
||||
AddSICSHdbPar(self->objectNode, "alarm", usInternal, textValue);
|
||||
AddSICSHdbPar(self->objectNode, "data", usInternal, dataValue);
|
||||
self->pPrivate = priv;
|
||||
self->KillPrivate = killLMD200;
|
||||
ReleaseHdbValue(&dataValue);
|
||||
NetWatchRegisterCallback(&priv->watchContext, priv->pSock->sockid,
|
||||
LMD200Callback, self);
|
||||
ANETsetReadCallback(priv->asChannel,LMD200Callback,self, NULL);
|
||||
|
||||
AddSICSHdbPar(self->objectNode,
|
||||
"clearalarm", usUser, MakeSICSFunc(ClearCmd));
|
||||
|
||||
status = AddCommand(pSics,
|
||||
argv[1], InterInvokeSICSOBJ, KillSICSOBJ, self);
|
||||
@ -257,7 +235,5 @@ int MakeLMD200(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
argv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
2
make_gen
2
make_gen
@ -23,7 +23,7 @@ OBJ=psi.o buffer.o ruli.o dmc.o nxsans.o nextrics.o sps.o pimotor.o \
|
||||
dgrambroadcast.o sinq.o tabledrive.o tcpdocho.o julcho.o \
|
||||
ritastorage.o poldizug.o audinelib.o delcam.o el737hpdrivsps.o \
|
||||
rebin.o sanslirebin.o lmd200.o slsvme.o julprot.o sinqhttpprot.o \
|
||||
pmacprot.o pfeifferprot.o termprot.o
|
||||
pmacprot.o pfeifferprot.o termprot.o phytron.o
|
||||
|
||||
.SECONDARY.: sanslirebin.c
|
||||
|
||||
|
100
phytron.c
Normal file
100
phytron.c
Normal file
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* This is an asynchronous protocol driver for the protocol of
|
||||
* the Phytron MCC-2 motor controller.
|
||||
* The send format is:
|
||||
* <STX> DATA <ETX>
|
||||
* the reply format is:
|
||||
* <STX> NACK | ACK |& REPLY <ETX>
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, June 2009
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <ascon.h>
|
||||
#include <ascon.i>
|
||||
#include <dynstring.h>
|
||||
|
||||
#define STX '\2'
|
||||
#define ETX '\3'
|
||||
#define NACK '\5'
|
||||
#define ACK '\6'
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int PhytronHandler(Ascon * a)
|
||||
{
|
||||
char *data = NULL;
|
||||
int ret, l;
|
||||
char chr;
|
||||
|
||||
|
||||
switch (a->state) {
|
||||
case AsconWriteStart:
|
||||
DynStringInsert(a->wrBuffer,"\2",0);
|
||||
DynStringConcatChar(a->wrBuffer,ETX);
|
||||
a->state = AsconWriting;
|
||||
a->wrPos = 0;
|
||||
break;
|
||||
case AsconReading:
|
||||
ret = AsconReadChar(a->fd, &chr);
|
||||
if (ret < 0) {
|
||||
/* EINTR means we must retry */
|
||||
if (errno != EINTR && errno != EAGAIN) {
|
||||
AsconError(a, "AsconReadChar failed:", errno);
|
||||
}
|
||||
return 1;
|
||||
} else if (ret > 0) {
|
||||
if(chr == STX){
|
||||
DynStringClear(a->rdBuffer);
|
||||
} else if (chr == ACK){
|
||||
DynStringConcat(a->rdBuffer,"ACK");
|
||||
} else if(chr == NACK){
|
||||
DynStringConcat(a->rdBuffer,"NACK");
|
||||
} else if(chr == ETX){
|
||||
a->state = AsconReadDone;
|
||||
} else {
|
||||
DynStringConcatChar(a->rdBuffer,chr);
|
||||
}
|
||||
} else if (ret == 0) {
|
||||
if (a->timeout > 0) {
|
||||
if (DoubleTime() - a->start > a->timeout) {
|
||||
AsconError(a, "read timeout", 0);
|
||||
a->state = AsconTimeout;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return AsconStdHandler(a);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int PhytronInit(Ascon * a, SConnection * con, int argc, char *argv[])
|
||||
{
|
||||
a->fd = -1;
|
||||
a->state = AsconConnectStart;
|
||||
a->reconnectInterval = 10;
|
||||
a->hostport = strdup(argv[1]);
|
||||
if (argc > 2) {
|
||||
a->timeout = atof(argv[2]);
|
||||
} else {
|
||||
a->timeout = 2.0; /* sec */
|
||||
}
|
||||
a->killPrivate = free;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
void AddPhytronProtocoll()
|
||||
{
|
||||
AsconProtocol *prot = NULL;
|
||||
|
||||
prot = calloc(sizeof(AsconProtocol), 1);
|
||||
prot->name = strdup("phytron");
|
||||
prot->init = PhytronInit;
|
||||
prot->handler = PhytronHandler;
|
||||
AsconInsertProtocol(prot);
|
||||
}
|
||||
|
3
psi.c
3
psi.c
@ -85,6 +85,8 @@ extern void AddPMACProtocoll();
|
||||
extern void AddPfeifferProtocoll();
|
||||
/* from termprot.c */
|
||||
extern void AddTermProtocoll();
|
||||
/* from phytron.c */
|
||||
extern void AddPhytronProtocoll();
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void SiteInit(void)
|
||||
@ -114,6 +116,7 @@ void SiteInit(void)
|
||||
AddPMACProtocoll();
|
||||
AddPfeifferProtocoll();
|
||||
AddTermProtocoll();
|
||||
AddPhytronProtocoll();
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user