Merge branch 'master' into moreremo
This commit is contained in:
589
binprot.c
Normal file
589
binprot.c
Normal file
@ -0,0 +1,589 @@
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include "ascon.h"
|
||||
#include "ascon.i"
|
||||
#include "dynstring.h"
|
||||
#include "cnvrt.h"
|
||||
|
||||
/*
|
||||
* this is a (scriptcontext) general binary protocol driver
|
||||
*
|
||||
* Markus Zolliker Aug 2010
|
||||
*
|
||||
* conversion to and from binary
|
||||
*
|
||||
* Syntax:
|
||||
* space separated items, the command first, a slash and then the read format
|
||||
*
|
||||
* commandItem ... / formatItem ...
|
||||
*
|
||||
* where a commandItem one of the following
|
||||
*
|
||||
* a number converted according to the choosen format, i1 is default
|
||||
* int<n> changing the format to <n> byte integers
|
||||
* hex changing the format to hexadecimal (1 byte at a time)
|
||||
* float changing the format to 4 byte ieee float
|
||||
* crc send crc
|
||||
*
|
||||
* and formatItem is one of the follwing
|
||||
*
|
||||
* skip skip one byte
|
||||
* skip<n> skip <n> bytes
|
||||
* code returned function code, when bit7 is set, the response is
|
||||
* recogized as an error message and the response is dumped
|
||||
* the result
|
||||
* int<n> convert <n> bytes to integer (most significant byte first)
|
||||
* and append the (decimal coded) number to the result
|
||||
* if <n> is omitted, <n> = 1 is assumed
|
||||
* hex convert 1 byte to hexadecimal coded integer
|
||||
* and append it to the response
|
||||
* float convert 4 bytes from ieee float
|
||||
* and append the number to the response
|
||||
* crc check crc (if wrong, "badCRC" is added to the response)
|
||||
*
|
||||
* multiple items in the response are space separated
|
||||
*
|
||||
* Usage example: Modbus read (float)
|
||||
* command: address 250, function 3, start-address 8, size 2, crc
|
||||
* response: address, function, byte-count, float, crc
|
||||
*
|
||||
* sct send 250 3 int2 10 2 crc / skip code skip float crc
|
||||
*
|
||||
* different crc's might be used (argv[2] opf BinInit):
|
||||
* modbus-crc: CRC-16-IBM, order: lo,hi
|
||||
* keller-crc: CRC-16-IBM, order: hi,lo
|
||||
* sycon-crc: sort of mod 256 checksum, byte stuffing included (no float allowed)
|
||||
*/
|
||||
|
||||
typedef enum {intType, hexType, floatType,
|
||||
skipType, codeType, crcType, dumpType, errorType} BinDataType;
|
||||
// dumpType, errorType must be the last items
|
||||
|
||||
typedef enum {modbusCrc, kellerCrc, rsportCrc, syconCrc} CrcAlgorithm;
|
||||
|
||||
typedef struct {
|
||||
CrcAlgorithm crcAlgorithm;
|
||||
pDynString inp;
|
||||
char *nextFmt;
|
||||
pDynString result;
|
||||
int expectedChars;
|
||||
BinDataType type;
|
||||
long iValue;
|
||||
int dumpFrom;
|
||||
int syconState;
|
||||
unsigned char chksum;
|
||||
} BinPrivate;
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int calc_crc(char *inp, int inpLen)
|
||||
{
|
||||
/** CRC-16-IBM Algorithm
|
||||
* crc calculation:
|
||||
* returns the 16bit CRC value of a message
|
||||
* crc check:
|
||||
* returns 0 when the crc appended to the message (lo byte first)
|
||||
* is correct
|
||||
*/
|
||||
|
||||
unsigned int crc = 0xffff;
|
||||
unsigned int next;
|
||||
int carry;
|
||||
int n;
|
||||
|
||||
while (inpLen--) {
|
||||
next = *(unsigned char *) inp;
|
||||
crc ^= next;
|
||||
for (n = 0; n < 8; n++) {
|
||||
carry = crc & 1;
|
||||
crc >>= 1;
|
||||
if (carry) {
|
||||
crc ^= 0xA001;
|
||||
}
|
||||
}
|
||||
inp++;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int calc_crc8(char *inp, int inpLen)
|
||||
{
|
||||
/** CRC-8 (x8+x5+x4+1) Algorithm
|
||||
* crc calculation:
|
||||
* returns the 8bit CRC value of a message
|
||||
* crc check:
|
||||
* returns 0 when the crc appended to the message is correct
|
||||
*/
|
||||
|
||||
unsigned char crc = 0;
|
||||
unsigned char data;
|
||||
int n;
|
||||
|
||||
while (inpLen--) {
|
||||
data = *(unsigned char *) inp;
|
||||
for (n = 0; n < 8; n++) {
|
||||
if ((crc ^ data) & 1) {
|
||||
crc ^= 0x18;
|
||||
crc >>= 1;
|
||||
crc |= 0x80;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
crc &= 0x7f;
|
||||
}
|
||||
data >>= 1;
|
||||
}
|
||||
inp++;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int BinReadItem(Ascon *a) {
|
||||
BinPrivate *p = a->private;
|
||||
char item[32];
|
||||
int valen;
|
||||
int size;
|
||||
|
||||
if (sscanf(p->nextFmt, "%30s%n", item, &valen) <= 0) {
|
||||
if (p->type < dumpType) {
|
||||
p->dumpFrom = GetDynStringLength(a->rdBuffer);
|
||||
p->type= dumpType;
|
||||
}
|
||||
p->expectedChars = 999;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcasecmp(item, "crc") == 0) {
|
||||
p->type = crcType;
|
||||
p->expectedChars = 2;
|
||||
p->nextFmt += valen;
|
||||
return 1;
|
||||
} else if (strncasecmp(item, "int", 3) == 0) {
|
||||
size = 1;
|
||||
sscanf(item + 3, "%d", &size);
|
||||
p->expectedChars = size;
|
||||
p->type = intType;
|
||||
p->iValue = 0;
|
||||
} else if (strcasecmp(item, "float") == 0) {
|
||||
p->expectedChars = 4;
|
||||
p->type = floatType;
|
||||
} else if (strcasecmp(item, "hex") == 0) {
|
||||
p->expectedChars = 1;
|
||||
p->type = hexType;
|
||||
} else if (strcasecmp(item, "code") == 0) {
|
||||
p->type = codeType;
|
||||
} else if (strncasecmp(item, "skip", 4) == 0) {
|
||||
size = 1;
|
||||
sscanf(item + 4, "%d", &size);
|
||||
p->expectedChars = size;
|
||||
p->type = skipType;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
p->nextFmt += valen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void BinError(Ascon *a, char *text) {
|
||||
BinPrivate *p = a->private;
|
||||
|
||||
p->type= errorType;
|
||||
p->dumpFrom = 0;
|
||||
p->expectedChars = 1;
|
||||
DynStringCopy(a->errmsg, "BINERR: ");
|
||||
DynStringConcat(a->errmsg, text);
|
||||
a->state = AsconFailed;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void BinToSycon(pDynString dyn) {
|
||||
char *str = strdup(GetCharArray(dyn));
|
||||
int l = GetDynStringLength(dyn);
|
||||
unsigned char sum, byte;
|
||||
int i;
|
||||
|
||||
DynStringClear(dyn);
|
||||
DynStringConcat(dyn, "\x02\x10\x80"); /* STX ADDR CMD */
|
||||
sum = 0x10 + 0x80;
|
||||
for (i=0; i<l; i++) {
|
||||
byte = str[i];
|
||||
sum += byte;
|
||||
switch (byte) {
|
||||
case 0x02:
|
||||
DynStringConcatChar(dyn, 0x07);
|
||||
DynStringConcatChar(dyn, '0');
|
||||
break;
|
||||
case 0x0d:
|
||||
DynStringConcatChar(dyn, 0x07);
|
||||
DynStringConcatChar(dyn, '1');
|
||||
break;
|
||||
case 0x07:
|
||||
DynStringConcatChar(dyn, 0x07);
|
||||
DynStringConcatChar(dyn, '2');
|
||||
break;
|
||||
default:
|
||||
DynStringConcatChar(dyn, byte);
|
||||
}
|
||||
}
|
||||
DynStringConcatChar(dyn, 0x30 + (sum / 16));
|
||||
DynStringConcatChar(dyn, 0x30 + (sum % 16));
|
||||
DynStringConcatChar(dyn, 0x0d);
|
||||
free(str);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int BinHandler(Ascon *a) {
|
||||
int res;
|
||||
char *str;
|
||||
int len;
|
||||
int i, l, pos;
|
||||
unsigned int crc;
|
||||
pDynString dyn;
|
||||
char item[32];
|
||||
char data[8];
|
||||
int size;
|
||||
int valen;
|
||||
BinDataType type;
|
||||
long iValue;
|
||||
double fValue;
|
||||
BinPrivate *p = a->private;
|
||||
|
||||
switch (a->state) {
|
||||
case AsconWriteStart:
|
||||
/* exchange buffers */
|
||||
dyn = p->inp;
|
||||
p->inp = a->wrBuffer;
|
||||
a->wrBuffer = dyn;
|
||||
DynStringClear(dyn);
|
||||
str = GetCharArray(p->inp);
|
||||
len = GetDynStringLength(p->inp);
|
||||
l = 0;
|
||||
size = 1;
|
||||
type = intType;
|
||||
for (pos = 0; pos < len; ) {
|
||||
if (sscanf(str + pos, "%30s%n", item, &valen) <= 0) {
|
||||
BinError(a, "missing '/'");
|
||||
return 1;
|
||||
}
|
||||
pos += valen;
|
||||
if (strcasecmp(item, "/") == 0) {
|
||||
break;
|
||||
} else if (strcasecmp(item, "crc") == 0) {
|
||||
switch (p->crcAlgorithm) {
|
||||
case kellerCrc:
|
||||
crc = calc_crc(GetCharArray(dyn), l);
|
||||
DynStringConcatChar(dyn, crc / 256);
|
||||
DynStringConcatChar(dyn, crc % 256);
|
||||
break;
|
||||
case modbusCrc:
|
||||
crc = calc_crc(GetCharArray(dyn), l);
|
||||
DynStringConcatChar(dyn, crc % 256);
|
||||
DynStringConcatChar(dyn, crc / 256);
|
||||
break;
|
||||
case rsportCrc:
|
||||
crc = calc_crc8(GetCharArray(dyn), l);
|
||||
DynStringConcatChar(dyn, crc);
|
||||
break;
|
||||
}
|
||||
} else if (strncasecmp(item, "int", 3) == 0) {
|
||||
sscanf(item + 3, "%d", &size);
|
||||
type = intType;
|
||||
} else if (strcasecmp(item, "hex") == 0) {
|
||||
type = hexType;
|
||||
} else if (strcasecmp(item, "float") == 0) {
|
||||
type = floatType;
|
||||
} else {
|
||||
switch (type) {
|
||||
case intType:
|
||||
res = sscanf(item, "%ld", &iValue);
|
||||
if (res != 1) {
|
||||
BinError(a, "invalid integer");
|
||||
return 1;
|
||||
}
|
||||
for (i = size - 1; i >= 0; i--) {
|
||||
if (i < sizeof data) {
|
||||
data[i] = iValue % 256;
|
||||
}
|
||||
iValue /= 256;
|
||||
}
|
||||
for (i = 0; i < size; i++) {
|
||||
if (i >= sizeof data) {
|
||||
DynStringConcatChar(dyn, 0);
|
||||
} else {
|
||||
DynStringConcatChar(dyn, data[i]);
|
||||
}
|
||||
}
|
||||
l += size;
|
||||
break;
|
||||
case hexType:
|
||||
res = sscanf(item, "%lx", &iValue);
|
||||
if (res != 1) {
|
||||
BinError(a, "invalid hex. integer");
|
||||
return 1;
|
||||
}
|
||||
DynStringConcatChar(dyn, (iValue & 255));
|
||||
break;
|
||||
case floatType:
|
||||
res = sscanf(item, "%lf", &fValue);
|
||||
if (res != 1) {
|
||||
BinError(a, "invalid float");
|
||||
return 1;
|
||||
}
|
||||
double2ieee(fValue, data);
|
||||
DynStringConcatChar(dyn, data[0]);
|
||||
DynStringConcatChar(dyn, data[1]);
|
||||
DynStringConcatChar(dyn, data[2]);
|
||||
DynStringConcatChar(dyn, data[3]);
|
||||
l += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p->crcAlgorithm == syconCrc) {
|
||||
BinToSycon(dyn);
|
||||
}
|
||||
|
||||
p->nextFmt = str + pos;
|
||||
p->type = hexType; /* initialize to anything < dumpType */
|
||||
do {
|
||||
res = BinReadItem(a);
|
||||
if (res < 0) {
|
||||
BinError(a, "illegal return format: ");
|
||||
DynStringConcat(a->errmsg, p->nextFmt);
|
||||
return 1;
|
||||
}
|
||||
} while (res == 1);
|
||||
p->nextFmt = str + pos;
|
||||
a->wrPos = 0;
|
||||
if (GetDynStringLength(a->wrBuffer) == 0) {
|
||||
/* prevent to swallow "garbage" */
|
||||
a->state = AsconWriteDone;
|
||||
} else {
|
||||
a->state = AsconWriting;
|
||||
}
|
||||
a->lineCount = 0;
|
||||
return 1;
|
||||
case AsconReadStart:
|
||||
DynStringClear(p->result);
|
||||
p->type = hexType; /* initialize to anything < dumpType */
|
||||
BinReadItem(a);
|
||||
p->syconState = 0;
|
||||
break;
|
||||
case AsconReading:
|
||||
res = AsconBaseHandler(a);
|
||||
if (res == 0) {
|
||||
if (GetDynStringLength(a->rdBuffer) == 0) {
|
||||
/* wait for the first byte - or timeout */
|
||||
return res;
|
||||
}
|
||||
if (p->type >= dumpType) {
|
||||
l = GetDynStringLength(a->rdBuffer);
|
||||
str = GetCharArray(a->rdBuffer);
|
||||
for (i = p->dumpFrom; i < l; i++) {
|
||||
snprintf(item, sizeof item, "%2.2x ", (str[i] & 255));
|
||||
DynStringConcat(p->result, item);
|
||||
}
|
||||
if (p->type == errorType) {
|
||||
DynStringConcat(a->errmsg, GetCharArray(p->result));
|
||||
a->state = AsconFailed;
|
||||
} else {
|
||||
a->state = AsconReadDone;
|
||||
}
|
||||
/* exchange buffers */
|
||||
dyn = a->rdBuffer;
|
||||
a->rdBuffer = p->result;
|
||||
p->result = dyn;
|
||||
return 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
if (p->crcAlgorithm == syconCrc) {
|
||||
switch (p->syconState) {
|
||||
case 0: /* wait for STX */
|
||||
if (a->lastChar == 0x02) {
|
||||
p->syconState = 1;
|
||||
p->chksum = 0;
|
||||
}
|
||||
return res;
|
||||
case 1: /* skip address */
|
||||
case 2: /* skip cmd_rsp */
|
||||
p->syconState++;
|
||||
p->chksum += a->lastChar;
|
||||
return res;
|
||||
case 3: /* detect stuffed bytes */
|
||||
if (a->lastChar == 0x07) {
|
||||
p->syconState = 4;
|
||||
return res;
|
||||
}
|
||||
p->chksum += a->lastChar;
|
||||
break;
|
||||
case 4: /* last byte was 0x07 */
|
||||
switch (a->lastChar) {
|
||||
case '0':
|
||||
a->lastChar = 0x02;
|
||||
break;
|
||||
case '1':
|
||||
a->lastChar = 0x0d;
|
||||
break;
|
||||
case '2':
|
||||
a->lastChar = 0x07;
|
||||
break;
|
||||
}
|
||||
p->chksum += a->lastChar;
|
||||
p->syconState = 3;
|
||||
break;
|
||||
case 5: /* expect 0x0d */
|
||||
if (a->lastChar != 0x0d) {
|
||||
DynStringConcat(p->result, "noCR ");
|
||||
}
|
||||
p->syconState = 6;
|
||||
p->dumpFrom++; /* skip for dump */
|
||||
case 6: /* skip everything else */
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* convert according to type */
|
||||
switch (p->type) {
|
||||
case codeType:
|
||||
if ((a->lastChar & 255) < 128) {
|
||||
p->expectedChars = 0;
|
||||
} else {
|
||||
DynStringCopy(a->errmsg, "BINERR: ");
|
||||
p->expectedChars = 2;
|
||||
p->type = errorType;
|
||||
p->dumpFrom = 0;
|
||||
/* skip to end */
|
||||
p->nextFmt = "";
|
||||
}
|
||||
break;
|
||||
case errorType:
|
||||
if (p->expectedChars > 1) {
|
||||
p->expectedChars--;
|
||||
snprintf(item, sizeof item, "error %d / ", (a->lastChar & 255));
|
||||
DynStringCopy(p->result, item);
|
||||
}
|
||||
break;
|
||||
case dumpType:
|
||||
break;
|
||||
case skipType:
|
||||
p->expectedChars--;
|
||||
break;
|
||||
case intType:
|
||||
p->expectedChars--;
|
||||
p->iValue = p->iValue * 256 + (a->lastChar & 255);
|
||||
if (p->expectedChars <= 0) {
|
||||
snprintf(item, sizeof item, "%ld ", p->iValue);
|
||||
DynStringConcat(p->result, item);
|
||||
}
|
||||
break;
|
||||
case hexType:
|
||||
p->expectedChars--;
|
||||
if (p->expectedChars <= 0) {
|
||||
snprintf(item, sizeof item, "%2.2x ", (a->lastChar & 255));
|
||||
DynStringConcat(p->result, item);
|
||||
}
|
||||
break;
|
||||
case floatType: /* does not work with sycon when stuffed */
|
||||
p->expectedChars--;
|
||||
if (p->expectedChars <= 0) {
|
||||
str = GetCharArray(a->rdBuffer) + GetDynStringLength(a->rdBuffer) - 4;
|
||||
fValue = ieee2double(str);
|
||||
snprintf(item, sizeof item, "%.7g ", fValue);
|
||||
DynStringConcat(p->result, item);
|
||||
}
|
||||
break;
|
||||
case crcType:
|
||||
p->expectedChars--;
|
||||
if (p->expectedChars <= 0) {
|
||||
str = GetCharArray(a->rdBuffer);
|
||||
l = GetDynStringLength(a->rdBuffer);
|
||||
switch (p->crcAlgorithm) {
|
||||
case syconCrc: /* ignore crc check */
|
||||
/* subtract CRC char (undo the addition) and subtract crc higher four bits */
|
||||
p->chksum -= a->lastChar + (a->lastChar & 0x0f);
|
||||
p->syconState = 5;
|
||||
if (p->chksum != 0) {
|
||||
DynStringConcat(p->result, "badCRC ");
|
||||
}
|
||||
break;
|
||||
case kellerCrc:
|
||||
i = str[l-2];
|
||||
str[l-2] = str[l-1];
|
||||
str[l-1] = i;
|
||||
/* fall through */
|
||||
case modbusCrc:
|
||||
case rsportCrc:
|
||||
if (calc_crc(str, l) != 0) {
|
||||
DynStringConcat(p->result, "badCRC ");
|
||||
}
|
||||
}
|
||||
} else if (p->crcAlgorithm == syconCrc) {
|
||||
/* subtract CRC char (undo the addition) and subtract crc higher four bits */
|
||||
p->chksum -= a->lastChar + (a->lastChar & 0x0f) * 16;
|
||||
}
|
||||
}
|
||||
if (p->expectedChars <= 0) {
|
||||
BinReadItem(a);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
return AsconBaseHandler(a);
|
||||
}
|
||||
|
||||
static void BinPrivateKill(void *pVoid) {
|
||||
BinPrivate *p = pVoid;
|
||||
DeleteDynString(p->inp);
|
||||
DeleteDynString(p->result);
|
||||
free(p);
|
||||
}
|
||||
|
||||
static int BinInit(Ascon * a, SConnection * con, int argc, char *argv[])
|
||||
{
|
||||
BinPrivate *p;
|
||||
|
||||
/* argv[2] may be modbus-crc (default), keller-crc, rsport-crc or sycon-crc */
|
||||
|
||||
if (argc < 2) {
|
||||
return 0;
|
||||
}
|
||||
p = calloc(sizeof(*p), 1);
|
||||
a->private = p;
|
||||
a->killPrivate = BinPrivateKill;
|
||||
p->crcAlgorithm = modbusCrc;
|
||||
if (argc > 2 && strcmp(argv[2], "") != 0) {
|
||||
if (strcasecmp(argv[2], "keller-crc") == 0) {
|
||||
p->crcAlgorithm = kellerCrc;
|
||||
} else if (strcasecmp(argv[2], "sycon-crc") == 0) {
|
||||
p->crcAlgorithm = syconCrc;
|
||||
} else if (strcasecmp(argv[2], "rsport-crc") == 0) {
|
||||
p->crcAlgorithm = rsportCrc;
|
||||
} else if (strcasecmp(argv[2], "modbus-crc") != 0) {
|
||||
SCPrintf(con, eError, "ERROR: unknown crc-algorithm %s", argv[2]);
|
||||
a->private = NULL;
|
||||
free(p);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
a->hostport = strdup(argv[1]);
|
||||
p->inp = CreateDynString(60,63);
|
||||
p->result = CreateDynString(60,63);
|
||||
if (argc > 3) {
|
||||
a->timeout = atof(argv[3]);
|
||||
} else {
|
||||
a->timeout = 2.0; /* sec */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void AddBinProtocol()
|
||||
{
|
||||
static AsconProtocol binprot;
|
||||
binprot.name = "bin";
|
||||
binprot.handler = BinHandler;
|
||||
binprot.init = BinInit;
|
||||
AsconInsertProtocol(&binprot);
|
||||
}
|
73
charbychar.c
Normal file
73
charbychar.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* charbychar.c
|
||||
*
|
||||
* This is a variation of the standard AsonHandler which implements
|
||||
* a char by char mode while sending. This means, that the protocol
|
||||
* handler waits for the echoed character from the device before sending
|
||||
* the next character.
|
||||
*
|
||||
* Created on: Apr 1, 2010
|
||||
* Author: koennecke
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <ascon.h>
|
||||
#include <ascon.i>
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* I am abusing the echo field as a flag if we are reading
|
||||
* an echo char or not
|
||||
-----------------------------------------------------------*/
|
||||
static int CharByCharHandler(Ascon *a)
|
||||
{
|
||||
int ret;
|
||||
char chr;
|
||||
|
||||
switch(a->state){
|
||||
case AsconWriting:
|
||||
if(a->wrPos < GetDynStringLength(a->wrBuffer)){
|
||||
ret = AsconWriteChars(a->fd,GetCharArray(a->wrBuffer)+a->wrPos,1);
|
||||
if (ret < 0) {
|
||||
AsconError(a, "ASC4", errno); /* sets state to AsconFailed */
|
||||
return 0;
|
||||
} else {
|
||||
a->wrPos++;
|
||||
a->private = (void *)1;
|
||||
a->state = AsconReading;
|
||||
a->start = DoubleTime();
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
a->private = NULL;
|
||||
a->state = AsconWriteDone;
|
||||
}
|
||||
break;
|
||||
case AsconReading:
|
||||
/**
|
||||
* Here I rely on the fact that the base
|
||||
* handler, in AsconReadStart, clears the
|
||||
* rdBuffer of amassed echo characters.
|
||||
*/
|
||||
ret = AsconStdHandler(a);
|
||||
if(ret == 1){
|
||||
if(a->private != NULL){
|
||||
a->state = AsconWriting;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
return AsconStdHandler(a);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void AddCharByCharProtocoll()
|
||||
{
|
||||
AsconProtocol *prot = NULL;
|
||||
|
||||
prot = calloc(sizeof(AsconProtocol), 1);
|
||||
prot->name = strdup("charbychar");
|
||||
prot->init = AsconStdInit;
|
||||
prot->handler = CharByCharHandler;
|
||||
AsconInsertProtocol(prot);
|
||||
}
|
105
cnvrt.c
Normal file
105
cnvrt.c
Normal file
@ -0,0 +1,105 @@
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "sics.h"
|
||||
|
||||
/*
|
||||
* conversions:
|
||||
* hex2float
|
||||
* float2hex
|
||||
*
|
||||
* Markus Zolliker Aug 2010
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void double2ieee(double input, char ieee[4])
|
||||
{
|
||||
|
||||
/* convert double to IEEE 32 bit floating number (denormalized numbers are considered as zero) */
|
||||
|
||||
long mantissa;
|
||||
int exponent;
|
||||
|
||||
if (input == 0) {
|
||||
ieee[0] = 0;
|
||||
ieee[1] = 0;
|
||||
ieee[2] = 0;
|
||||
ieee[3] = 0;
|
||||
} else {
|
||||
mantissa = 0x1000000 * (frexp(fabs(input), &exponent));
|
||||
exponent = exponent - 1 + 127;
|
||||
if (exponent < 0) {
|
||||
exponent = 0;
|
||||
} else if (exponent > 0xFE) {
|
||||
exponent = 0xFE;
|
||||
}
|
||||
if (input < 0) {
|
||||
ieee[0] = 0x80 | (exponent >> 1);
|
||||
} else {
|
||||
ieee[0] = exponent >> 1;
|
||||
}
|
||||
ieee[1] = (exponent & 1) << 7 | ((mantissa & 0x7F0000) >> 16);
|
||||
ieee[2] = (mantissa & 0xFF00) >> 8;
|
||||
ieee[3] = mantissa & 0xFF;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
double ieee2double(char ieee[4])
|
||||
{
|
||||
|
||||
/* IEEE 32 bit floating number to double (denormalized numbers are considered as zero) */
|
||||
|
||||
long mantissa;
|
||||
double output;
|
||||
int exponent;
|
||||
|
||||
mantissa = ((ieee[1] << 16) & 0x7FFFFF)
|
||||
| ((ieee[2] << 8) & 0xFF00)
|
||||
| ((ieee[3]) & 0xFF);
|
||||
|
||||
exponent = (ieee[0] & 0x7F) * 2 + ((ieee[1] >> 7) & 1); /* raw exponent */
|
||||
if (exponent == 0 && mantissa == 0) {
|
||||
return 0.0;
|
||||
}
|
||||
output = ldexp(mantissa, -23) + 1.0;
|
||||
if (ieee[0] & 0x80) {
|
||||
output = -output;
|
||||
}
|
||||
return output * ldexp(1, exponent - 127);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int CnvrtAction(SConnection *con, SicsInterp *sics, void *data,
|
||||
int argc, char *argv[]) {
|
||||
double f;
|
||||
char ieee[4];
|
||||
char result[32];
|
||||
|
||||
if (argc != 3) goto Usage;
|
||||
if (strcasecmp(argv[1], "float2xieee") == 0) {
|
||||
double2ieee(atof(argv[2]), ieee);
|
||||
SCPrintf(con, eValue, "%2.2x%2.2x%2.2x%2.2x",
|
||||
ieee[0] & 0xFF, ieee[1] & 0xFF, ieee[2] & 0xFF, ieee[3] & 0xFF);
|
||||
return 1;
|
||||
} else if (strcasecmp(argv[1], "xieee2float") == 0) {
|
||||
ieee[0]=0;
|
||||
ieee[1]=0;
|
||||
ieee[2]=0;
|
||||
ieee[3]=0;
|
||||
sscanf(argv[2], "%2hhx%2hhx%2hhx%2hhx",
|
||||
ieee, ieee+1, ieee+2, ieee+3);
|
||||
snprintf(result, sizeof result, "%.7g", ieee2double(ieee));
|
||||
if (strchr(result, '.') == NULL && strchr(result, 'e') == NULL) {
|
||||
SCPrintf(con, eValue, "%s.", result);
|
||||
} else {
|
||||
SCWrite(con, result, eValue);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
Usage:
|
||||
SCPrintf(con, eError, "ERROR: Usage: cnvrt float2xieee <float>");
|
||||
SCPrintf(con, eError, " cnvrt xieee2float <hexadecimal ieee>");
|
||||
return 0;
|
||||
}
|
6
cnvrt.h
Normal file
6
cnvrt.h
Normal file
@ -0,0 +1,6 @@
|
||||
/* convert double to IEEE 32 bit floating number and vice versa
|
||||
(denormalized numbers are considered as zero) */
|
||||
|
||||
void double2ieee(double input, char ieee[4]);
|
||||
double ieee2double(char ieee[4]);
|
||||
|
41
macro.c
41
macro.c
@ -1095,44 +1095,3 @@ int TransactAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
SCWrite(pCon, "TRANSACTIONFINISHED", eLog);
|
||||
return iRet;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
int CaptureAction(SConnection *pCon, SicsInterp * pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
SConnection *comCon = NULL;
|
||||
char buffer[1024];
|
||||
char *command;
|
||||
int status;
|
||||
pDynString reply = NULL;
|
||||
|
||||
if (argc < 2) {
|
||||
SCWrite(pCon, "ERROR: insufficient arguments to capture", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
comCon = SCCopyConnection(pCon);
|
||||
if (comCon == NULL) {
|
||||
SCWrite(pCon, "ERROR: out of memory in capture", eError);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* This line is required to support nested captures
|
||||
*/
|
||||
comCon->data = NULL;
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
command = Arg2Tcl(argc - 1, &argv[1], buffer, sizeof buffer);
|
||||
if (!command) {
|
||||
SCWrite(pCon, "ERROR: no more memory", eError);
|
||||
return 0;
|
||||
}
|
||||
SCStartBuffering(comCon);
|
||||
status = InterpExecute(pSics, comCon, command);
|
||||
if (command != buffer)
|
||||
free(command);
|
||||
reply = SCEndBuffering(comCon);
|
||||
SCWrite(pCon,GetCharArray(reply), eValue);
|
||||
SCDeleteConnection(comCon);
|
||||
return status;
|
||||
|
||||
}
|
||||
|
3
make_gen
3
make_gen
@ -46,7 +46,8 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||
rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.o \
|
||||
histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\
|
||||
singlebinb.o taskobj.o sctcomtask.o tasmono.o multicountersec.o \
|
||||
messagepipe.o sicsget.o remoteobject.o
|
||||
messagepipe.o sicsget.o remoteobject.o pmacprot.o charbychar.o binprot.o \
|
||||
cnvrt.o
|
||||
|
||||
MOTOROBJ = motor.o simdriv.o
|
||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||
|
17
nxdict.c
17
nxdict.c
@ -1,7 +1,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Nexus Dictionary API implementation file.
|
||||
|
||||
@ -696,6 +695,18 @@ static void NXDIAttValue(ParDat * sStat)
|
||||
sStat->pToken[0] = *(sStat->pPtr);
|
||||
sStat->pPtr++;
|
||||
return;
|
||||
} else if(*(sStat->pPtr) == '"') {
|
||||
sStat->pPtr++;
|
||||
sStat->iToken = DWORD;
|
||||
i= 0;
|
||||
while(*(sStat->pPtr) != '"') {
|
||||
sStat->pToken[i] = *(sStat->pPtr);
|
||||
sStat->pPtr++;
|
||||
i++;
|
||||
}
|
||||
sStat->pToken[i] = '\0';
|
||||
sStat->pPtr++;
|
||||
return;
|
||||
} else {
|
||||
sStat->iToken = DWORD;
|
||||
/* copy word to pToken */
|
||||
@ -820,6 +831,10 @@ static int NXDIParseAttr(ParDat * pParse, int iList)
|
||||
}
|
||||
strcpy(sAtt.name, pParse->pToken);
|
||||
|
||||
if(strstr(sAtt.name,"offset") != NULL){
|
||||
printf("%s \n",sAtt.name);
|
||||
}
|
||||
|
||||
/* a , is expected */
|
||||
NXDIDefToken(pParse);
|
||||
if (pParse->iToken != DKOMMA) {
|
||||
|
4
ofac.c
4
ofac.c
@ -46,6 +46,9 @@ static void InitGeneral(void)
|
||||
INIT(AddTestProt);
|
||||
INIT(AddGenBinProtocoll);
|
||||
INIT(AddSyncedProt);
|
||||
INIT(AddBinProtocol);
|
||||
INIT(AddPMACProtocoll);
|
||||
INIT(AddCharByCharProtocoll);
|
||||
INIT(MakeTrace);
|
||||
INIT(InitTaskOBJ);
|
||||
INIT(RemoteObjectInit);
|
||||
@ -72,7 +75,6 @@ static void InitIniCommands(SicsInterp * pInter)
|
||||
/* permanent commands in alphabetic order */
|
||||
PCMD("alias", MakeAlias);
|
||||
PCMD("broadcast", Broadcast);
|
||||
PCMD("Capture", CaptureAction);
|
||||
PCMD("ClientPut", ClientPut);
|
||||
PCMD("ClientLog", ClientLog);
|
||||
PCMD("config", ConfigCon);
|
||||
|
224
pmacprot.c
Normal file
224
pmacprot.c
Normal file
@ -0,0 +1,224 @@
|
||||
/**
|
||||
* This is an asynchronous protocol driver for the Delta-Tau PMAC
|
||||
* series of controllers, connected via TCP/IP. The PMAC needs its
|
||||
* commands in a special purpose data structure, describe below.
|
||||
* As responses, it can send any of the following formats:
|
||||
* data<CR>data<CR>data>CR><ACK>
|
||||
* <BELL>ERRxxx<CR>
|
||||
* <STX>data<CR>
|
||||
* There can be multiple data and errors in a string. However, I wish to
|
||||
* restrict this to processing one command at any time. This driver owes
|
||||
* some insight and little code to the EPICS driver by
|
||||
* Pete Leicester, Diamond.
|
||||
*
|
||||
* ** Before this can be used, I3=2 and I6=1 must be set on the PMAC **
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, December 2008
|
||||
*
|
||||
* Introduced a delay on read in order to throttle requests
|
||||
*
|
||||
* Mark Koennecke, June 2011
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <ascon.h>
|
||||
#include <ascon.i>
|
||||
#include <dynstring.h>
|
||||
|
||||
#define ETHERNET_DATA_SIZE 1492
|
||||
#define INPUT_SIZE (ETHERNET_DATA_SIZE+1) /* +1 to allow space to add terminating ACK */
|
||||
#define STX '\2'
|
||||
#define CTRLB '\2'
|
||||
#define CTRLC '\3'
|
||||
#define ACK '\6'
|
||||
#define CTRLF '\6'
|
||||
#define BELL '\7'
|
||||
#define CTRLG '\7'
|
||||
#define CTRLP '\16'
|
||||
#define CTRLV '\22'
|
||||
#define CTRLX '\24'
|
||||
|
||||
/* PMAC ethernet command structure */
|
||||
#pragma pack(1)
|
||||
typedef struct tagEthernetCmd {
|
||||
unsigned char RequestType;
|
||||
unsigned char Request;
|
||||
unsigned short wValue;
|
||||
unsigned short wIndex;
|
||||
unsigned short wLength; /* length of bData */
|
||||
unsigned char bData[ETHERNET_DATA_SIZE];
|
||||
} ethernetCmd;
|
||||
#pragma pack()
|
||||
|
||||
#define ETHERNET_CMD_HEADER ( sizeof(ethernetCmd) - ETHERNET_DATA_SIZE )
|
||||
|
||||
/* PMAC ethernet commands - RequestType field */
|
||||
#define VR_UPLOAD 0xC0
|
||||
#define VR_DOWNLOAD 0x40
|
||||
|
||||
/* PMAC ethernet commands - Request field */
|
||||
#define VR_PMAC_SENDLINE 0xB0
|
||||
#define VR_PMAC_GETLINE 0xB1
|
||||
#define VR_PMAC_FLUSH 0xB3
|
||||
#define VR_PMAC_GETMEM 0xB4
|
||||
#define VR_PMAC_SETMEN 0xB5
|
||||
#define VR_PMAC_SETBIT 0xBA
|
||||
#define VR_PMAC_SETBITS 0xBB
|
||||
#define VR_PMAC_PORT 0xBE
|
||||
#define VR_PMAC_GETRESPONSE 0xBF
|
||||
#define VR_PMAC_READREADY 0xC2
|
||||
#define VR_CTRL_RESPONSE 0xC4
|
||||
#define VR_PMAC_GETBUFFER 0xC5
|
||||
#define VR_PMAC_WRITEBUFFER 0xC6
|
||||
#define VR_PMAC_WRITEERROR 0xC7
|
||||
#define VR_FWDOWNLOAD 0xCB
|
||||
#define VR_IPADDRESS 0xE0
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* a private data structurli to keep track of the PMAC
|
||||
*---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
ethernetCmd cmd;
|
||||
char *ptr;
|
||||
int bytesToWrite;
|
||||
int expectACK;
|
||||
double startTime;
|
||||
} PMACPrivate, *pPMACPrivate;
|
||||
/*---------------------------------------------------------------------------*
|
||||
* wait period before read
|
||||
----------------------------------------------------------------------------*/
|
||||
#define READDELAY .05
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int PMACHandler(Ascon * a)
|
||||
{
|
||||
char *data = NULL;
|
||||
int ret, l;
|
||||
char chr;
|
||||
pPMACPrivate priv = NULL;
|
||||
|
||||
priv = a->private;
|
||||
|
||||
switch (a->state) {
|
||||
case AsconWriteStart:
|
||||
data = GetCharArray(a->wrBuffer);
|
||||
memset(priv, 0, sizeof(PMACPrivate));
|
||||
priv->cmd.RequestType = VR_DOWNLOAD;
|
||||
priv->cmd.Request = VR_PMAC_GETRESPONSE;
|
||||
priv->cmd.wValue = 0;
|
||||
priv->cmd.wIndex = 0;
|
||||
priv->cmd.wLength = htons(strlen(data)); /* may be one more */
|
||||
priv->bytesToWrite = strlen(data) + 1 + ETHERNET_CMD_HEADER;
|
||||
strcpy((char *) priv->cmd.bData, data);
|
||||
priv->expectACK = 1;
|
||||
priv->ptr = (char *) &priv->cmd;
|
||||
a->state = AsconWriting;
|
||||
a->wrPos = 0;
|
||||
break;
|
||||
case AsconWriting:
|
||||
AsconReadGarbage(a->fd);
|
||||
l = priv->bytesToWrite - a->wrPos;
|
||||
ret = AsconWriteChars(a->fd, priv->ptr, l);
|
||||
if (ret < 0) {
|
||||
if (errno != EINTR && errno != EAGAIN) {
|
||||
AsconError(a, "send failed:", errno);
|
||||
}
|
||||
/*
|
||||
* Ooops: which state shall we go to after a write fail?
|
||||
* This seems to retry.
|
||||
*/
|
||||
} else {
|
||||
a->wrPos += ret;
|
||||
if (a->wrPos >= priv->bytesToWrite) {
|
||||
a->state = AsconWriteDone;
|
||||
priv->startTime = DoubleTime();
|
||||
} else {
|
||||
priv->ptr += ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AsconReadStart:
|
||||
DynStringClear(a->rdBuffer);
|
||||
if(DoubleTime() > priv->startTime + READDELAY){
|
||||
a->start = DoubleTime();
|
||||
a->state = AsconReading;
|
||||
}
|
||||
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) {
|
||||
a->start = DoubleTime();
|
||||
if (chr == STX || chr == BELL) {
|
||||
priv->expectACK = 0;
|
||||
return 1;
|
||||
}
|
||||
if (priv->expectACK && chr == ACK) {
|
||||
if (GetDynStringLength(a->rdBuffer) == 0) {
|
||||
DynStringConcat(a->rdBuffer, "ACK");
|
||||
}
|
||||
DynStringConcatChar(a->rdBuffer, '\0');
|
||||
a->state = AsconReadDone;
|
||||
break;
|
||||
}
|
||||
if (priv->expectACK == 0 && chr == '\r') {
|
||||
DynStringConcatChar(a->rdBuffer, '\0');
|
||||
a->state = AsconReadDone;
|
||||
break;
|
||||
}
|
||||
if (DynStringConcatChar(a->rdBuffer, chr) == 0) {
|
||||
AsconError(a, "DynStringConcatChar failed:", ENOMEM);
|
||||
break;
|
||||
}
|
||||
} else if (ret == 0) {
|
||||
if (a->timeout > 0) {
|
||||
if (DoubleTime() - a->start > a->timeout) {
|
||||
AsconError(a, "read timeout", 0);
|
||||
a->state = AsconTimeout;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return AsconStdHandler(a);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int PMACInit(Ascon * a, SConnection * con, int argc, char *argv[])
|
||||
{
|
||||
pPMACPrivate priv = NULL;
|
||||
|
||||
priv = calloc(sizeof(PMACPrivate), 1);
|
||||
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->private = priv;
|
||||
a->killPrivate = free;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
void AddPMACProtocoll()
|
||||
{
|
||||
AsconProtocol *prot = NULL;
|
||||
|
||||
prot = calloc(sizeof(AsconProtocol), 1);
|
||||
prot->name = strdup("pmac");
|
||||
prot->init = PMACInit;
|
||||
prot->handler = PMACHandler;
|
||||
AsconInsertProtocol(prot);
|
||||
}
|
156
protocol.c
156
protocol.c
@ -21,7 +21,7 @@
|
||||
#define MAXMSG 1024
|
||||
#define INIT_STR_SIZE 256
|
||||
#define STR_RESIZE_LENGTH 256
|
||||
#define NUMPROS 7
|
||||
#define NUMPROS 6
|
||||
#define PROLISTLEN 8
|
||||
typedef struct __Protocol {
|
||||
pObjectDescriptor pDes; /* required as first field */
|
||||
@ -97,7 +97,6 @@ pProtocol CreateProtocol(void)
|
||||
char *pPros[] = { "default",
|
||||
"normal",
|
||||
"withcode",
|
||||
"sycamore",
|
||||
"json",
|
||||
"act",
|
||||
"all",
|
||||
@ -282,19 +281,15 @@ static int ProtocolSet(SConnection * pCon, Protocol * pPro, char *pProName)
|
||||
SCSetWriteFunc(pCon, SCWriteWithOutcode);
|
||||
break;
|
||||
|
||||
case 3: /* sycamore */
|
||||
SCSetWriteFunc(pMaster, SCWriteSycamore);
|
||||
SCSetWriteFunc(pCon, SCWriteSycamore);
|
||||
break;
|
||||
case 4: /* json */
|
||||
case 3: /* json */
|
||||
SCSetWriteFunc(pCon, SCWriteJSON_String);
|
||||
SCSetWriteFunc(pMaster, SCWriteJSON_String);
|
||||
break;
|
||||
case 5: /* ACT */
|
||||
case 4: /* ACT */
|
||||
SCSetWriteFunc(pMaster, SCACTWrite);
|
||||
SCSetWriteFunc(pCon, SCACTWrite);
|
||||
break;
|
||||
case 6:
|
||||
case 5:
|
||||
SCSetWriteFunc(pMaster, SCAllWrite);
|
||||
SCSetWriteFunc(pCon, SCAllWrite);
|
||||
break;
|
||||
@ -340,9 +335,8 @@ int ProtocolGet(SConnection * pCon, void *pData, char *pProName, int len)
|
||||
case 0: /* default = psi_sics */
|
||||
case 1: /* normal (connection start default) */
|
||||
case 2: /* outcodes */
|
||||
case 3: /* sycamore */
|
||||
case 4: /* json */
|
||||
case 5: /* act */
|
||||
case 3: /* json */
|
||||
case 4: /* act */
|
||||
pProName = pPro->pProList[Index];
|
||||
return 1;
|
||||
break;
|
||||
@ -451,133 +445,7 @@ static int InitDefaultProtocol(SConnection * pCon, Protocol * pPro)
|
||||
}
|
||||
return pPro->isDefaultSet;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
void sycformat(char *tag, OutCode msgFlag, pDynString msgString,
|
||||
pDynString msgOut)
|
||||
{
|
||||
DynStringConcat(msgOut, " ");
|
||||
switch (msgFlag) {
|
||||
eEvent:
|
||||
break;
|
||||
eFinish:
|
||||
break;
|
||||
default:
|
||||
DynStringConcat(msgOut, tag);
|
||||
DynStringConcat(msgOut, "={");
|
||||
DynStringConcat(msgOut, GetCharArray(msgString));
|
||||
DynStringConcat(msgOut, "}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
int SCWriteSycamore(SConnection * pCon, char *pBuffer, int iOut)
|
||||
{
|
||||
int iRet;
|
||||
char pBueffel[MAXMSG];
|
||||
long taskID = 0;
|
||||
/* char pPrefix[40];*/
|
||||
pDynString pMsg = NULL;
|
||||
pDynString pMsgString = NULL;
|
||||
commandContext comCon;
|
||||
|
||||
|
||||
if (strlen(pBuffer) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!SCVerifyConnection(pCon)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* log it for any case */
|
||||
if (pCon->pSock) {
|
||||
iRet = pCon->pSock->sockid;
|
||||
} else {
|
||||
iRet = 0;
|
||||
}
|
||||
snprintf(pBueffel,sizeof(pBueffel)-1, "Next line intended for socket: %d", iRet);
|
||||
SICSLogWrite(pBueffel, eInternal);
|
||||
SICSLogWrite(pBuffer, iOut);
|
||||
|
||||
/* write to commandlog if user or manager privilege */
|
||||
if (SCGetRights(pCon) <= usUser) {
|
||||
WriteToCommandLogId(NULL, iRet, pBuffer);
|
||||
}
|
||||
|
||||
/* put it into the interpreter if present */
|
||||
if (SCinMacro(pCon)) {
|
||||
InterpWrite(pServ->pSics, pBuffer);
|
||||
/* print it to client if error message */
|
||||
/* FIXME should report errors via sycamore
|
||||
if((iOut== eError) || (iOut == eWarning) )
|
||||
iRet = SCDoSockWrite(pCon,GetCharArray(pMsgOut)); */
|
||||
} else { /* not in interpreter, normal logic */
|
||||
|
||||
comCon = SCGetContext(pCon);
|
||||
|
||||
/* Return 0 without dying if no message data */
|
||||
if (pBuffer == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
taskID = comCon.transID;
|
||||
|
||||
pMsg = CreateDynString(INIT_STR_SIZE, STR_RESIZE_LENGTH);
|
||||
pMsgString = CreateDynString(INIT_STR_SIZE, STR_RESIZE_LENGTH);
|
||||
pBueffel[0] = '\0';
|
||||
|
||||
snprintf(pBueffel,sizeof(pBueffel)-1, "[con%4.4d:", (int) pCon->ident); /* field 1: connID */
|
||||
DynStringConcat(pMsg, pBueffel);
|
||||
snprintf(pBueffel,sizeof(pBueffel)-1, "t%6.6d:", (int) taskID); /* field 2: taskID */
|
||||
DynStringConcat(pMsg, pBueffel);
|
||||
/* deviceID */
|
||||
DynStringConcat(pMsg, comCon.deviceID);
|
||||
DynStringConcatChar(pMsg, ':');
|
||||
|
||||
/* msgFlag */
|
||||
switch (iOut) {
|
||||
case 5: /* eValue */
|
||||
DynStringConcat(pMsg, "out");
|
||||
break;
|
||||
default:
|
||||
DynStringConcat(pMsg, pCode[iOut]);
|
||||
break;
|
||||
}
|
||||
DynStringConcatChar(pMsg, ']');
|
||||
if (iOut == eStart) {
|
||||
DynStringConcat(pMsgString, comCon.deviceID);
|
||||
}
|
||||
|
||||
if (iOut == eEvent) {
|
||||
DynStringConcat(pMsgString, " type=");
|
||||
/* Default type to VALUECHANGE if conEventType not set */
|
||||
if (-1 == pCon->conEventType)
|
||||
DynStringConcat(pMsgString, pEventType[0]);
|
||||
else
|
||||
DynStringConcat(pMsgString, pEventType[pCon->conEventType]);
|
||||
/* DynStringConcat(pMsgString, " status=");
|
||||
DynStringConcat(pMsgString, pStatus[pCon->conStatus]);*/
|
||||
DynStringConcat(pMsgString, ",");
|
||||
}
|
||||
DynStringConcat(pMsgString, " ");
|
||||
DynStringConcat(pMsgString, pBuffer);
|
||||
sycformat(comCon.deviceID, iOut, pMsgString, pMsg);
|
||||
|
||||
/* is this really to be printed ? */
|
||||
if (iOut < pCon->iOutput) {
|
||||
if (pMsg != NULL)
|
||||
DeleteDynString(pMsg);
|
||||
return 0;
|
||||
}
|
||||
/* first the socket */
|
||||
/*strcat(pMsg, pBueffel); */
|
||||
iRet = SCDoSockWrite(pCon, GetCharArray(pMsg));
|
||||
}
|
||||
if (pMsg != NULL)
|
||||
DeleteDynString(pMsg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Only work for hipadaba commands, hlist, hset, hget, hnotify
|
||||
* A multiline string (ie have crnl) will be converted to an array.
|
||||
* Strings with '=' will be converted to name value pairs
|
||||
@ -763,8 +631,7 @@ char *GetProtocolName(SConnection * pCon)
|
||||
case 0: /* default = psi_sics */
|
||||
case 1: /* normal (connection start default) */
|
||||
case 2: /* outcodes */
|
||||
case 3: /* sycamore */
|
||||
case 4: /* json */
|
||||
case 3: /* json */
|
||||
return strdup(pPro->pProList[pCon->iProtocolID]);
|
||||
break;
|
||||
default:
|
||||
@ -790,13 +657,10 @@ writeFunc GetProtocolWriteFunc(SConnection * pCon)
|
||||
case 2: /* outcodes */
|
||||
return SCWriteWithOutcode;
|
||||
break;
|
||||
case 3: /* sycamore */
|
||||
return SCWriteSycamore;
|
||||
break;
|
||||
case 4: /* json */
|
||||
case 3: /* json */
|
||||
return SCWriteJSON_String;
|
||||
break;
|
||||
case 5:
|
||||
case 4:
|
||||
return SCACTWrite;
|
||||
break;
|
||||
default:
|
||||
|
@ -24,9 +24,6 @@ void MakeProtocol(void);
|
||||
/*--------------------- operations --------------------------------------*/
|
||||
int ProtocolAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
/*--------------------- implement protocol sycamore ---------------------*/
|
||||
int SCWriteSycamore(SConnection * pCon, char *pBuffer, int iOut);
|
||||
|
||||
/*--------------------- implement protocol API -----------------------*/
|
||||
char *GetProtocolName(SConnection * pCon);
|
||||
int GetProtocolID(SConnection * pCon);
|
||||
|
85
simindex.c
85
simindex.c
@ -167,6 +167,88 @@ static int RunIndexCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
|
||||
|
||||
return status;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void InternalOutFunc(void *data, char *text)
|
||||
{
|
||||
pDynString tData = (pDynString) data;
|
||||
if (tData!= NULL) {
|
||||
DynStringConcat(tData, text);
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int RunIntIndexCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar)
|
||||
{
|
||||
int i, j, status, err;
|
||||
pSingleDiff diffi;
|
||||
pSICSOBJ reflist;
|
||||
double ang[5], z1[3];
|
||||
IndexSolution is;
|
||||
MATRIX ub;
|
||||
pHdb nSol = NULL;
|
||||
pDynString tData;
|
||||
char fString[512];
|
||||
|
||||
tData = CreateDynString(256,256);
|
||||
|
||||
SimIdxSetLambda(SXGetLambda());
|
||||
SimIdxSetCell((double *) SXGetCell());
|
||||
SimIdxSetSpacegroup(SXGetSpaceGroup());
|
||||
SimIdxOutput(tData, InternalOutFunc, 10);
|
||||
|
||||
reflist = SXGetReflectionList();
|
||||
diffi = SXGetDiffractometer();
|
||||
SimIdxClearReflection();
|
||||
for (i = 0; i < ReflectionListCount(reflist); i++) {
|
||||
GetRefAngles(reflist, i, ang);
|
||||
diffi->calcZ1(diffi, GetRefName(reflist, i), z1);
|
||||
SimIdxAddReflection(z1);
|
||||
}
|
||||
|
||||
nSol = GetHipadabaNode(self->objectNode,"nsolutions");
|
||||
assert(nSol != NULL);
|
||||
|
||||
status = SimIdxRun();
|
||||
filterSolutions();
|
||||
if (status == 1) {
|
||||
if (SimIdxGetNSolutions() < 1) {
|
||||
DynStringConcat(tData,"No solutions were found\n");
|
||||
UpdateHipadabaPar(nSol,MakeHdbInt(0), pCon);
|
||||
return 0;
|
||||
}
|
||||
DynStringConcat(tData, "Indexing Suggestions:\n");
|
||||
UpdateHipadabaPar(nSol,MakeHdbInt(SimIdxGetNSolutions()), pCon);
|
||||
for (i = 0; i < SimIdxGetNSolutions(); i++) {
|
||||
is = SimIdxGetSolution(i);
|
||||
|
||||
snprintf(fString,sizeof(fString), "Solution No : %d, GOF = %6.3f\n", i,
|
||||
is.diff * 100);
|
||||
DynStringConcat(tData,fString);
|
||||
for (j = 0; j < 3; j++) {
|
||||
if (is.originalID[j] != 999) {
|
||||
snprintf(fString,sizeof(fString)," Ref = %2d, HKL = %4d %4d %4d \n",
|
||||
is.originalID[j], is.h[j], is.k[j], is.l[j]);
|
||||
DynStringConcat(tData,fString);
|
||||
}
|
||||
}
|
||||
SCPrintf(pCon,eLog," UB:");
|
||||
DynStringConcat(tData," UB\n");
|
||||
ub = calcUBForSolution(is,&err);
|
||||
if(ub != NULL) { /* should never happen, as filtered */
|
||||
for(j = 0; j < 3; j++){
|
||||
snprintf(fString,sizeof(fString)," %8.5f %8.5f %8.5f\n",
|
||||
ub[j][0], ub[j][1], ub[j][2]);
|
||||
DynStringConcat(tData,fString);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCWrite(pCon,GetCharArray(tData),eValue);
|
||||
DeleteDynString(tData);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int ChooseCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar)
|
||||
@ -315,6 +397,9 @@ void InitSimpleIndex(SConnection * pCon, SicsInterp * pSics)
|
||||
cmd = AddSICSHdbPar(pNew->objectNode, "run", usUser,
|
||||
MakeSICSFunc(RunIndexCmd));
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode, "runint", usUser,
|
||||
MakeSICSFunc(RunIntIndexCmd));
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode, "choose", usUser,
|
||||
MakeSICSFunc(ChooseCmd));
|
||||
cmd = AddSICSHdbPar(cmd, "solution", usUser, MakeHdbInt(0));
|
||||
|
Reference in New Issue
Block a user