- Currently disabled attempts at logging commands
- Added a warning for excessive data rates on monitors - Added statistics to devser and thus to scriptcontext - Added byte concatenation to dynstring - Added aborting for reflection generation to fourmess.c - Added data checksum testing to hipadaba, use for update tests - Fixed interrupt discovery in network.c, caused invalid interrupt codes which in turn confused sicscron which had to be fixed too. - Renamed ubcalc into ubcalcint in order to reclaim the ubcalc for Jurg - Added an a3offset to tasub in order to fix what I perceive an IS problem - Added support for the newer version of the Siemens SPS, the S7 - Added a not yet fully working sinqhttpopt driver which talks to http HM without libghttp
This commit is contained in:
24
delcam.c
24
delcam.c
@ -43,6 +43,7 @@
|
||||
typedef struct {
|
||||
AUD_HANDLE aud_handle;
|
||||
int amplictrl;
|
||||
int amplion;
|
||||
int shutterctrl;
|
||||
int nClear;
|
||||
int running;
|
||||
@ -76,6 +77,16 @@ static int DelcamConfigure(pHistDriver self, SConnection * pCon,
|
||||
SCWrite(pCon, "ERROR: invalid amplictrl value, range 0 - 8", eError);
|
||||
pPriv->amplictrl = 0;
|
||||
}
|
||||
if (StringDictGet(pOpt, "amplion", buffer, 79) == 1) {
|
||||
pPriv->amplion = atoi(buffer);
|
||||
} else {
|
||||
pPriv->amplion = 1;
|
||||
}
|
||||
if(pPriv->amplion != 0 && pPriv->amplion != 1){
|
||||
SCWrite(pCon, "ERROR: invalid amplion value, 0,1 allowed", eError);
|
||||
pPriv->amplion = 1;
|
||||
}
|
||||
|
||||
if (StringDictGet(pOpt, "shutterctrl", buffer, 79) == 1) {
|
||||
pPriv->shutterctrl = atoi(buffer);
|
||||
} else {
|
||||
@ -252,6 +263,7 @@ static int DelcamCountStatus(pHistDriver self, SConnection * pCon)
|
||||
return HWBusy;
|
||||
}
|
||||
if (status != HWBusy && pPriv->running == 1) {
|
||||
pPriv->count->pDriv->ReadValues(pPriv->count->pDriv);
|
||||
pPriv->running = 0;
|
||||
/*
|
||||
* stop the CCD and transfer data
|
||||
@ -267,21 +279,23 @@ static int DelcamCountStatus(pHistDriver self, SConnection * pCon)
|
||||
}
|
||||
usleep(SHUTTER_DELAY * 1000);
|
||||
}
|
||||
if(pPriv->amplion == 1){
|
||||
status = aud_amplifier_set(pPriv->aud_handle, 1);
|
||||
if (status != 0) {
|
||||
snprintf(buffer, 80, "ERROR: failed to stop amplifier, errno = %d",
|
||||
snprintf(buffer, 80, "ERROR: failed to start amplifier, errno = %d",
|
||||
errno);
|
||||
SCWrite(pCon, buffer, eError);
|
||||
pPriv->error = FAULT;
|
||||
status = HWFault;
|
||||
}
|
||||
/* usleep(AMPLIFIER_DELAY*1000); */
|
||||
usleep(AMPLIFIER_DELAY*1000);
|
||||
}
|
||||
|
||||
|
||||
usleep(pPriv->schnarch * 1000);
|
||||
|
||||
SCWrite(pCon,
|
||||
"WARNING: computer freeze for ~15 sec is normal during readout",
|
||||
"WARNING: starting readout, computer freeze for ~15 sec is normal during readout",
|
||||
eWarning);
|
||||
|
||||
status = aud_image_read(pPriv->aud_handle, &shittyCompiler,
|
||||
@ -301,7 +315,10 @@ static int DelcamCountStatus(pHistDriver self, SConnection * pCon)
|
||||
}
|
||||
free(imData);
|
||||
}
|
||||
SCWrite(pCon,
|
||||
"WARNING: CCD read",eWarning);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -506,6 +523,7 @@ pHistDriver MakeDelcamHM(pStringDict pOption)
|
||||
|
||||
/* add our options */
|
||||
StringDictAddPair(pOption, "amplictrl", "0");
|
||||
StringDictAddPair(pOption, "amplion", "1");
|
||||
StringDictAddPair(pOption, "shutterctrl", "0");
|
||||
StringDictAddPair(pOption, "clear", "1");
|
||||
StringDictAddPair(pOption, "schnarch", "1");
|
||||
|
80
fetchwrite.c
80
fetchwrite.c
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* fetchwrite.c
|
||||
*
|
||||
* This is the implementation for the Siemens S5 FETCH/Write
|
||||
* protocol support functions. Docs see header file
|
||||
*
|
||||
* Created on: Mar 24, 2010
|
||||
* Author: koennecke
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "fetchwrite.h"
|
||||
|
||||
Request makeS5WriteRequest(int orgID, unsigned char dbNo,
|
||||
int offset, int length, void *data)
|
||||
{
|
||||
Request result;
|
||||
|
||||
result.totalLength = 16 + length;
|
||||
result.data = malloc(result.totalLength*sizeof(char));
|
||||
if(result.data == NULL){
|
||||
return result;
|
||||
}
|
||||
memset(result.data,0,result.totalLength*sizeof(char));
|
||||
|
||||
result.data[0] = 'S';
|
||||
result.data[1] = '5';
|
||||
result.data[2] = 0x10;
|
||||
result.data[3] = 0x01;
|
||||
result.data[4] = 0x03;
|
||||
result.data[5] = 0x03;
|
||||
result.data[6] = 0x03;
|
||||
result.data[7] = 0x08;
|
||||
result.data[8] = (unsigned char)orgID;
|
||||
result.data[9] = dbNo;
|
||||
result.data[10] = (unsigned short)offset;
|
||||
result.data[12] = (unsigned short)length;
|
||||
result.data[14] = 0xFF;
|
||||
result.data[15] = 0x02;
|
||||
memcpy(result.data+16,data,length);
|
||||
|
||||
return result;
|
||||
}
|
||||
/*-------------------------------------------------------------*/
|
||||
int decodeS5Response(unsigned char data[16])
|
||||
{
|
||||
if(data[0] != 'S' || data[1] != '5'){
|
||||
return S5INVALID;
|
||||
}
|
||||
return (int)data[8];
|
||||
}
|
||||
/*---------------------------------------------------------------*/
|
||||
Request makeS5FetchRequest(int orgID, unsigned char dbNo,
|
||||
int offset, int length)
|
||||
{
|
||||
Request result;
|
||||
|
||||
result.totalLength = 16;
|
||||
result.data = malloc(result.totalLength*sizeof(char));
|
||||
if(result.data == NULL){
|
||||
return result;
|
||||
}
|
||||
memset(result.data,0,result.totalLength*sizeof(char));
|
||||
|
||||
result.data[0] = 'S';
|
||||
result.data[1] = '5';
|
||||
result.data[2] = 0x10;
|
||||
result.data[3] = 0x01;
|
||||
result.data[4] = 0x03;
|
||||
result.data[5] = 0x05;
|
||||
result.data[6] = 0x03;
|
||||
result.data[7] = 0x08;
|
||||
result.data[8] = (unsigned char)orgID;
|
||||
result.data[9] = dbNo;
|
||||
result.data[10] = (unsigned short)offset;
|
||||
result.data[12] = (unsigned short)length;
|
||||
result.data[14] = 0xFF;
|
||||
result.data[15] = 0x02;
|
||||
return result;
|
||||
}
|
4
make_gen
4
make_gen
@ -10,7 +10,7 @@
|
||||
tjxp $*.tc $*.c
|
||||
|
||||
OBJ=psi.o buffer.o ruli.o sps.o pimotor.o charbychar.o\
|
||||
pipiezo.o sanswave.o faverage.o fetchwrite.o\
|
||||
pipiezo.o sanswave.o faverage.o spss7.o\
|
||||
amorstat.o tasinit.o ptasdrive.o tasutil.o tasscan.o swmotor.o \
|
||||
polterwrite.o ecb.o frame.o el734driv.o el734dc.o ecbdriv.o \
|
||||
ecbcounter.o el737driv.o sinqhmdriv.o tdchm.o velodorn.o \
|
||||
@ -20,7 +20,7 @@ OBJ=psi.o buffer.o ruli.o sps.o pimotor.o charbychar.o\
|
||||
t_rlp.o t_conv.o el737hpdriv.o dornier2.o el734hp.o \
|
||||
el737hpv2driv.o swmotor2.o tricssupport.o amorcomp.o \
|
||||
$(MZOBJ) amordrive.o amorset.o sinqhttp.o slsecho.o\
|
||||
dgrambroadcast.o sinq.o tabledrive.o julcho.o \
|
||||
dgrambroadcast.o sinq.o tabledrive.o julcho.o sinqhttpopt.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 phytron.o autowin.o
|
||||
|
3
psi.c
3
psi.c
@ -65,6 +65,7 @@ void SiteInit(void)
|
||||
*/
|
||||
INIT(AddJulChoProtocoll);
|
||||
INIT(AddHttpProtocoll);
|
||||
INIT(AddHttpOptProtocoll);
|
||||
INIT(AddPMACProtocoll);
|
||||
INIT(AddPfeifferProtocoll);
|
||||
INIT(AddTermProtocoll);
|
||||
@ -112,7 +113,9 @@ static void AddPsiCommands(SicsInterp * pInter)
|
||||
SCMD("MakeSansliRebin", MakeSansliRebin);
|
||||
SCMD("MakeSANSWave", MakeSANSWave);
|
||||
SCMD("MakeSinq", SinqFactory);
|
||||
SCMD("MakeSinqRedirect", SinqRedirectFactory);
|
||||
SCMD("MakeSPS", SPSFactory);
|
||||
SCMD("MakeSPSS7", MakeSPSS7);
|
||||
PCMD("MakeSWHPMotor", MakeSWHPMotor);
|
||||
SCMD("MakeSWMotor", MakeSWMotor);
|
||||
SCMD("MakeTableDrive", TableDriveFactory);
|
||||
|
96
sinq.c
96
sinq.c
@ -12,6 +12,12 @@
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, July 2005
|
||||
*
|
||||
* Modified to also hold the code for a second version which
|
||||
* uses the redirector on lnsl15. This has to be used by instruments in
|
||||
* the private network as they cannot receive the ACS broadacst.
|
||||
*
|
||||
* Mark Koennecke, July 2010
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -26,6 +32,8 @@
|
||||
#include "dgrambroadcast.h"
|
||||
|
||||
#include "sinq.h"
|
||||
#include <asynnet.h>
|
||||
|
||||
#ifdef SEND_PORT
|
||||
#define RECEIVE_PORT SEND_PORT
|
||||
#else
|
||||
@ -83,9 +91,11 @@ static void KillSinq(void *data)
|
||||
if (self->pDes != NULL) {
|
||||
DeleteDescriptor(self->pDes);
|
||||
}
|
||||
if(self->anet){
|
||||
ANETclose(self->receiveSocket);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int SinqFactory(SConnection * pCon, SicsInterp * pSics,
|
||||
void *pData, int argc, char *argv[])
|
||||
@ -202,3 +212,87 @@ int SinqWrapper(SConnection * pCon, SicsInterp * pSics,
|
||||
SCWrite(pCon, pBueffel, eValue);
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static char* searchMessage(char *pPtr, int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < length; i++){
|
||||
if(pPtr[i] == (char) 4 && pPtr[i+1] == (char)4){
|
||||
return pPtr + i-1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int SINQRedirectCallback(int handle, void *userData){
|
||||
pSinq self = (pSinq)userData;
|
||||
char *pPtr = NULL, *pTerm = NULL,pID[5];
|
||||
int length, sinq;
|
||||
|
||||
pPtr = ANETreadPtr(handle, &length);
|
||||
pTerm = searchMessage(pPtr,length);
|
||||
while(pTerm != NULL){
|
||||
/*
|
||||
strlcpy(pID, pPtr, 5);
|
||||
printf("Received message with ID: %s\n", pID);
|
||||
*/
|
||||
if (memcmp(pPtr, "D110", 4) == 0) {
|
||||
strlcpy(self->d110, pPtr, pTerm - pPtr);
|
||||
sinq = getSinqBeam(self, SINQBEAM);
|
||||
self->lastSinq[self->lastCount] = sinq;
|
||||
self->lastCount++;
|
||||
if (self->lastCount >= MAXLOG) {
|
||||
self->lastCount = 0;
|
||||
}
|
||||
}
|
||||
if (memcmp(pPtr, "A110", 4) == 0) {
|
||||
strlcpy(self->a110, pPtr, pTerm - pPtr);
|
||||
}
|
||||
ANETreadConsume(handle, (pTerm - pPtr) + 3);
|
||||
pPtr = ANETreadPtr(handle, &length);
|
||||
pTerm = searchMessage(pPtr,length);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int SinqRedirectFactory(SConnection * pCon, SicsInterp * pSics,
|
||||
void *pData, int argc, char *argv[])
|
||||
{
|
||||
pSinq pNew = NULL;
|
||||
int i;
|
||||
|
||||
if(argc < 3){
|
||||
SCWrite(pCon,"ERROR: need host port argument to SinqRedirectFactory", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pNew = (pSinq) malloc(sizeof(Sinq));
|
||||
if (pNew == NULL) {
|
||||
SCWrite(pCon, "ERROR: out of memory allocating Sinq", eError);
|
||||
return 0;
|
||||
}
|
||||
memset(pNew, 0, sizeof(Sinq));
|
||||
pNew->pDes = CreateDescriptor("Sinq");
|
||||
if (pNew->pDes == NULL) {
|
||||
SCWrite(pCon, "ERROR: out of memory allocating Sinq", eError);
|
||||
free(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->receiveSocket = ANETconnect(argv[1],atoi(argv[2]));
|
||||
if (pNew->receiveSocket < 0) {
|
||||
SCWrite(pCon, "ERROR: failed to open Sinq Status port",
|
||||
eError);
|
||||
KillSinq(pNew);
|
||||
return 0;
|
||||
}
|
||||
ANETsetReadCallback(pNew->receiveSocket, SINQRedirectCallback, pNew, NULL);
|
||||
pNew->anet = 1;
|
||||
|
||||
for (i = 0; i < MAXLOG; i++) {
|
||||
pNew->lastSinq[i] = -200;
|
||||
}
|
||||
return AddCommand(pSics, "sinq", SinqWrapper, KillSinq, pNew);
|
||||
}
|
||||
|
||||
|
3
sinq.h
3
sinq.h
@ -22,10 +22,13 @@ typedef struct {
|
||||
int receiveSocket;
|
||||
int lastSinq[MAXLOG];
|
||||
int lastCount;
|
||||
int anet;
|
||||
} Sinq, *pSinq;
|
||||
/*----------------------- interpreter interface ------------------------*/
|
||||
int SinqFactory(SConnection * pCon, SicsInterp * pSics,
|
||||
void *pData, int argc, char *argv[]);
|
||||
int SinqRedirectFactory(SConnection * pCon, SicsInterp * pSics,
|
||||
void *pData, int argc, char *argv[]);
|
||||
int SinqWrapper(SConnection * pCon, SicsInterp * pSics,
|
||||
void *pData, int argc, char *argv[]);
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
470
sinqhttpopt.c
Normal file
470
sinqhttpopt.c
Normal file
@ -0,0 +1,470 @@
|
||||
/**
|
||||
* This is an asynchronous protocol implementation for HTTP.
|
||||
* It includes special features to store binary data coming
|
||||
* from a SINQ http histogram memory in a sinqdata object.
|
||||
* Which has to be specified on initialisation.
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* After finding that libghttp actually blocks on sockets, this is
|
||||
* a reimplementation doing everything itself.
|
||||
*
|
||||
* Mark Koennecke, November 2010
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <ascon.h>
|
||||
#include <ascon.i>
|
||||
#include <unistd.h>
|
||||
#include <sicsdata.h>
|
||||
#include <HistMem.h>
|
||||
#include "sicshipadaba.h"
|
||||
#include <stptok.h>
|
||||
extern char *trim(char *txt);
|
||||
/*-------------------------------------------------------------------------------
|
||||
* taken from libghttp
|
||||
*/
|
||||
static const char b64_alphabet[65] = {
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/=" };
|
||||
|
||||
static char *
|
||||
http_base64_encode(const char *text) {
|
||||
/* The tricky thing about this is doing the padding at the end,
|
||||
* doing the bit manipulation requires a bit of concentration only */
|
||||
char *buffer = NULL;
|
||||
char *point = NULL;
|
||||
int inlen = 0;
|
||||
int outlen = 0;
|
||||
|
||||
/* check our args */
|
||||
if (text == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Use 'buffer' to store the output. Work out how big it should be...
|
||||
* This must be a multiple of 4 bytes */
|
||||
|
||||
inlen = strlen( text );
|
||||
/* check our arg...avoid a pesky FPE */
|
||||
if (inlen == 0)
|
||||
{
|
||||
buffer = malloc(sizeof(char));
|
||||
buffer[0] = '\0';
|
||||
return buffer;
|
||||
}
|
||||
outlen = (inlen*4)/3;
|
||||
if( (inlen % 3) > 0 ) /* got to pad */
|
||||
outlen += 4 - (inlen % 3);
|
||||
|
||||
buffer = malloc( outlen + 1 ); /* +1 for the \0 */
|
||||
memset(buffer, 0, outlen + 1); /* initialize to zero */
|
||||
|
||||
/* now do the main stage of conversion, 3 bytes at a time,
|
||||
* leave the trailing bytes (if there are any) for later */
|
||||
|
||||
for( point=buffer; inlen>=3; inlen-=3, text+=3 ) {
|
||||
*(point++) = b64_alphabet[ *text>>2 ];
|
||||
*(point++) = b64_alphabet[ (*text<<4 & 0x30) | *(text+1)>>4 ];
|
||||
*(point++) = b64_alphabet[ (*(text+1)<<2 & 0x3c) | *(text+2)>>6 ];
|
||||
*(point++) = b64_alphabet[ *(text+2) & 0x3f ];
|
||||
}
|
||||
|
||||
/* Now deal with the trailing bytes */
|
||||
if( inlen ) {
|
||||
/* We always have one trailing byte */
|
||||
*(point++) = b64_alphabet[ *text>>2 ];
|
||||
*(point++) = b64_alphabet[ (*text<<4 & 0x30) |
|
||||
(inlen==2?*(text+1)>>4:0) ];
|
||||
*(point++) = (inlen==1?'=':b64_alphabet[ *(text+1)<<2 & 0x3c ] );
|
||||
*(point++) = '=';
|
||||
}
|
||||
|
||||
*point = '\0';
|
||||
|
||||
return buffer;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
char *userName;
|
||||
char *password;
|
||||
pSICSData binData;
|
||||
pHdb node;
|
||||
int sockHandle;
|
||||
int bytesExpected;
|
||||
char *contentType;
|
||||
} HttpProt, *pHttpProt;
|
||||
/*---------------------------------------------------------------------*/
|
||||
static int HTTPcallback(int handle, void *userData)
|
||||
{
|
||||
Ascon *a = (Ascon *)userData;
|
||||
pHttpProt pHttp = NULL;
|
||||
unsigned char ch;
|
||||
int length;
|
||||
char *data;
|
||||
|
||||
if(a == NULL){
|
||||
printf("really serious error in HTTPcallback\n");
|
||||
return 0;
|
||||
}
|
||||
pHttp = (pHttpProt)a->private;
|
||||
|
||||
data = (char *)ANETreadPtr(handle,&length);
|
||||
if(data != NULL){
|
||||
DynStringConcatBytes(a->rdBuffer,data,length);
|
||||
}
|
||||
ANETreadConsume(handle,length);
|
||||
return 1;
|
||||
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static void sendAuth(pHttpProt pHttp)
|
||||
{
|
||||
char buffer[256];
|
||||
char *encoded = NULL;
|
||||
|
||||
if(pHttp->userName != NULL){
|
||||
snprintf(buffer,255,"%s:%s", pHttp->userName,pHttp->password);
|
||||
encoded = http_base64_encode(buffer);
|
||||
if(encoded != NULL){
|
||||
snprintf(buffer,255,"Authorization: Basic %s\r\n\r\n", encoded);
|
||||
free(encoded);
|
||||
}
|
||||
} else {
|
||||
strcpy(buffer,"\r\n");
|
||||
}
|
||||
ANETwrite(pHttp->sockHandle,buffer,strlen(buffer));
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static void sendGet(pHttpProt pHttp, char *path)
|
||||
{
|
||||
char buffer[1024];
|
||||
char hostname[256];
|
||||
|
||||
gethostname(hostname,255);
|
||||
snprintf(buffer,1024,"GET %s HTTP/1.1\r\nHost: %s\r\nConnection: keep-alive\r\n",
|
||||
path, hostname);
|
||||
ANETwrite(pHttp->sockHandle, buffer,strlen(buffer));
|
||||
sendAuth(pHttp);
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static void sendPost(pHttpProt pHttp, char *path, char *data)
|
||||
{
|
||||
char buffer[1024];
|
||||
char hostname[256];
|
||||
|
||||
gethostname(hostname,255);
|
||||
snprintf(buffer,1024,"POST %s HTTP/1.1\r\nHost: %s\r\nConnection: keep-alive\r\n",
|
||||
path, hostname);
|
||||
ANETwrite(pHttp->sockHandle, buffer,strlen(buffer));
|
||||
snprintf(buffer,1024,"Content-Length: %d\r\n", strlen(data));
|
||||
ANETwrite(pHttp->sockHandle, buffer,strlen(buffer));
|
||||
sendAuth(pHttp);
|
||||
ANETwrite(pHttp->sockHandle,data,strlen(data));
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static void sendRequest(pHttpProt pHttp, char *data)
|
||||
{
|
||||
char *path, *dataCopy, *pPtr;
|
||||
|
||||
dataCopy = strdup(data);
|
||||
|
||||
pPtr = strchr(dataCopy,':');
|
||||
if(pPtr == NULL){
|
||||
path = dataCopy;
|
||||
sendGet(pHttp,path);
|
||||
free(dataCopy);
|
||||
return;
|
||||
} else {
|
||||
if(strstr(dataCopy,"node") != NULL){
|
||||
path = pPtr+1;
|
||||
pPtr = strchr(path,':');
|
||||
*pPtr = '\0';
|
||||
pHttp->node = FindHdbNode(NULL,path,pServ->dummyCon);
|
||||
path = pPtr+1;
|
||||
sendGet(pHttp,path);
|
||||
free(dataCopy);
|
||||
return;
|
||||
} else if(strstr(dataCopy,"post") != NULL){
|
||||
path = pPtr+1;
|
||||
pPtr = strchr(path,':');
|
||||
*pPtr = '\0';
|
||||
sendPost(pHttp,path, pPtr+1);
|
||||
free(dataCopy);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static void handleReply(Ascon * a)
|
||||
{
|
||||
char *pPtr = NULL, *pType = NULL, *path = NULL;
|
||||
int len, i, *dataPtr = NULL;
|
||||
HistInt *hmData = NULL;
|
||||
pHttpProt pHttp = (pHttpProt) a->private;
|
||||
|
||||
pPtr = GetCharArray(a->rdBuffer);
|
||||
len = GetDynStringLength(a->rdBuffer);
|
||||
if (strstr(pPtr, "ERROR") != NULL) {
|
||||
AsconError(a, pPtr, 0);
|
||||
} else if (strstr(pPtr, "Authentication Error") != NULL) {
|
||||
AsconError(a, pPtr, 0);
|
||||
} else {
|
||||
pType = pHttp->contentType;
|
||||
if (strstr(pType, "sinqhm") != NULL) {
|
||||
hmData = (HistInt *) pPtr;
|
||||
len = len / sizeof(HistInt);
|
||||
if(pHttp->node == NULL){
|
||||
clearSICSData(pHttp->binData);
|
||||
dataPtr = getSICSDataPointer(pHttp->binData, 0, len);
|
||||
for (i = 0; i < len; i++) {
|
||||
dataPtr[i] = htonl(hmData[i]);
|
||||
}
|
||||
assignSICSType(pHttp->binData, 0, len, INTTYPE);
|
||||
DynStringClear(a->rdBuffer);
|
||||
DynStringCopy(a->rdBuffer, "SICSDATA");
|
||||
} else {
|
||||
if(pHttp->node->value.arrayLength != len){
|
||||
if(pHttp->node->value.v.intArray != NULL){
|
||||
free(pHttp->node->value.v.intArray);
|
||||
}
|
||||
pHttp->node->value.v.intArray = malloc(len*sizeof(int));
|
||||
if(pHttp->node->value.v.intArray == NULL){
|
||||
AsconError(a,"Out of memory ",0);
|
||||
return;
|
||||
}
|
||||
pHttp->node->value.arrayLength = len;
|
||||
}
|
||||
for(i = 0; i < len; i++){
|
||||
pHttp->node->value.v.intArray[i] = htonl(hmData[i]);
|
||||
}
|
||||
NotifyHipadabaPar(pHttp->node,NULL);
|
||||
/*
|
||||
path = GetHipadabaPath(pHttp->node);
|
||||
if(path != NULL){
|
||||
printf("Sinqhttpprot has updated node: %s\n", path);
|
||||
free(path);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static int processHeader(Ascon *a)
|
||||
{
|
||||
char line[132], *pPtr, *data, *colon;
|
||||
pHttpProt pHttp = (pHttpProt) a->private;
|
||||
int status, length;
|
||||
|
||||
data = GetCharArray(a->rdBuffer);
|
||||
assert(data != NULL);
|
||||
/*
|
||||
* printf("%s",data);
|
||||
*/
|
||||
|
||||
pPtr = data;
|
||||
pPtr = stptok(pPtr, line, 132, "\n");
|
||||
sscanf(line,"HTTP/1.%*d %03d", &status);
|
||||
if(status != 200 && status != 201){
|
||||
AsconError(a,line,AsconFailure);
|
||||
return 0;
|
||||
}
|
||||
while((pPtr = stptok(pPtr,line,132,"\n")) != NULL){
|
||||
colon = strchr(line,':');
|
||||
if(colon != NULL){
|
||||
*colon = '\0';
|
||||
colon++;
|
||||
strtolower(line);
|
||||
if(strstr(line,"content-length") != NULL){
|
||||
pHttp->bytesExpected = atoi(trim(colon));
|
||||
}
|
||||
if(strstr(line,"content-type") != NULL){
|
||||
if(pHttp->contentType != NULL){
|
||||
free(pHttp->contentType);
|
||||
}
|
||||
pHttp->contentType = strdup(trim(colon));
|
||||
}
|
||||
if(strstr(line,"connection") != NULL){
|
||||
strtolower(colon);
|
||||
if(strstr(colon,"close") != NULL){
|
||||
pHttp->bytesExpected = INT32_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Hack off the header
|
||||
*/
|
||||
pPtr = strstr(data, "\r\n\r\n");
|
||||
length = GetDynStringLength(a->rdBuffer);
|
||||
length -= 4 + (pPtr - data);
|
||||
if(length > 0){
|
||||
data = malloc(length*sizeof(char));
|
||||
if(data == NULL){
|
||||
AsconError(a,"Out of memory", AsconFailure);
|
||||
return 0;
|
||||
}
|
||||
memcpy(data,pPtr+4,length);
|
||||
DynStringClear(a->rdBuffer);
|
||||
DynStringConcatBytes(a->rdBuffer,data,length);
|
||||
free(data);
|
||||
} else {
|
||||
DynStringClear(a->rdBuffer);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static int HttpHandler(Ascon * a)
|
||||
{
|
||||
pHttpProt pHttp = (pHttpProt) a->private;
|
||||
int socke, selStat, port, status;
|
||||
fd_set rmask;
|
||||
struct timeval tmo = { 0, 0 };
|
||||
char buffer[1024];
|
||||
char *hostport, *colon;
|
||||
|
||||
switch (a->state) {
|
||||
case AsconConnectStart:
|
||||
a->state = AsconConnecting;
|
||||
break;
|
||||
case AsconConnecting:
|
||||
a->state = AsconConnectDone; /* success */
|
||||
break;
|
||||
case AsconWriteStart:
|
||||
if(!ANETvalidHandle(pHttp->sockHandle)){
|
||||
hostport = strdup(a->hostport);
|
||||
colon = strchr(hostport, ':');
|
||||
if (colon == NULL){
|
||||
port = 80;
|
||||
} else {
|
||||
*colon = '\0';
|
||||
port = atoi(colon + 1);
|
||||
}
|
||||
if (port <= 0) {
|
||||
AsconError(a, "bad port number", 0);
|
||||
return 1;
|
||||
}
|
||||
pHttp->sockHandle = ANETconnect(hostport,port);
|
||||
free(hostport);
|
||||
if(pHttp->sockHandle < 0){
|
||||
AsconError(a,"Failed to connect", 0);
|
||||
} else {
|
||||
ANETsetReadCallback(pHttp->sockHandle,
|
||||
HTTPcallback, a,NULL);
|
||||
a->state = AsconWriting;
|
||||
}
|
||||
} else {
|
||||
a->state = AsconWriting;
|
||||
}
|
||||
return 1;
|
||||
break;
|
||||
case AsconWriting:
|
||||
sendRequest(pHttp,GetCharArray(a->wrBuffer));
|
||||
a->state = AsconWriteDone;
|
||||
a->start = DoubleTime();
|
||||
pHttp->bytesExpected = -1;
|
||||
DynStringClear(a->rdBuffer);
|
||||
return 1;
|
||||
break;
|
||||
case AsconReading:
|
||||
ANETprocess();
|
||||
/**
|
||||
* Here we have basically three conditions to check:
|
||||
* - <cr><ld><cr><lf> detected means that we received
|
||||
* the complete header.
|
||||
* - enough bytes read: termination
|
||||
* - socket closed means all data has been read
|
||||
*/
|
||||
if(strstr(GetCharArray(a->rdBuffer), "\r\n\r\n") != NULL){
|
||||
status = processHeader(a);
|
||||
if(status != 1){
|
||||
a->state = AsconReadDone;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(!ANETvalidHandle(pHttp->sockHandle)){
|
||||
handleReply(a);
|
||||
a->state = AsconReadDone;
|
||||
return 1;
|
||||
}
|
||||
if(pHttp->bytesExpected > 0 && GetDynStringLength(a->rdBuffer) >= pHttp->bytesExpected ){
|
||||
handleReply(a);
|
||||
a->state = AsconReadDone;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return AsconStdHandler(a);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
static void killHttp(void *data)
|
||||
{
|
||||
pHttpProt prot = (pHttpProt) data;
|
||||
if (prot == NULL) {
|
||||
return;
|
||||
}
|
||||
if (prot->password != NULL) {
|
||||
free(prot->password);
|
||||
}
|
||||
if (prot->userName != NULL) {
|
||||
free(prot->userName);
|
||||
}
|
||||
if(prot->contentType != NULL){
|
||||
free(prot->contentType);
|
||||
}
|
||||
free(prot);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int HttpProtInit(Ascon * a, SConnection * con,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pHttpProt pHttp = NULL;
|
||||
|
||||
pHttp = calloc(sizeof(HttpProt), 1);
|
||||
if (pHttp == NULL) {
|
||||
SCWrite(con, "ERROR: out of memory in HttpProtInit", eError);
|
||||
return 0;
|
||||
}
|
||||
if (argc < 3) {
|
||||
return 0;
|
||||
}
|
||||
a->hostport = strdup(argv[1]);
|
||||
pHttp->binData = (pSICSData) FindCommandData(pServ->pSics,
|
||||
argv[2], "SICSData");
|
||||
if (pHttp->binData == NULL) {
|
||||
SCWrite(con, "ERROR: SICSData object not found", eError);
|
||||
return 0;
|
||||
}
|
||||
if (argc > 3) {
|
||||
a->timeout = atof(argv[3]);
|
||||
} else {
|
||||
a->timeout = 10.;
|
||||
}
|
||||
if (argc > 5) {
|
||||
pHttp->userName = strdup(argv[4]);
|
||||
pHttp->password = strdup(argv[5]);
|
||||
}
|
||||
pHttp->sockHandle = -10;
|
||||
pHttp->contentType = strdup("text/html");
|
||||
a->private = pHttp;
|
||||
a->killPrivate = killHttp;
|
||||
a->state = AsconConnectStart;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void AddHttpOptProtocoll()
|
||||
{
|
||||
AsconProtocol *prot = NULL;
|
||||
|
||||
prot = calloc(sizeof(AsconProtocol), 1);
|
||||
prot->name = strdup("sinqhttpopt");
|
||||
prot->init = HttpProtInit;
|
||||
prot->handler = HttpHandler;
|
||||
AsconInsertProtocol(prot);
|
||||
}
|
4
slsvme.c
4
slsvme.c
@ -87,8 +87,12 @@ static void locateValue(char *rawReply, char *value, int valLen)
|
||||
|
||||
pPtr = rawReply;
|
||||
pPtr = stptok(pPtr, value, valLen, " ");
|
||||
if(pPtr != NULL){
|
||||
pPtr = stptok(pPtr, value, valLen, " ");
|
||||
}
|
||||
if(pPtr != NULL){
|
||||
stptok(pPtr, value, valLen, " ");
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
576
spss7.c
Normal file
576
spss7.c
Normal file
@ -0,0 +1,576 @@
|
||||
/*
|
||||
* spss7.c
|
||||
*
|
||||
* This is an interface between SICS and a S7 Siemens SPS speaking the
|
||||
* Fetch/Write protocol via TCP/IP. On initialization, the S7 DB area reserved
|
||||
* for communication with SICS is read, parsed and nodes created representing the
|
||||
* various data items in there. Suitable callbacks allow to write values into the
|
||||
* SPS. Communication is via the device serializer and the genbin protocol handler.
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Created on: Jul 7, 2010
|
||||
* Author: Mark Koennecke
|
||||
*/
|
||||
#include <sics.h>
|
||||
#include <sicsobj.h>
|
||||
#include <devser.h>
|
||||
#include <sicshipadaba.h>
|
||||
#define MAXDATA 65552 /* 64KB + 16 Byte for headers */
|
||||
|
||||
/*----------------------- private data structure --------------*/
|
||||
typedef struct {
|
||||
DevSer *devser;
|
||||
int dbnum;
|
||||
int dblength;
|
||||
int switchdbnum;
|
||||
int switchdblength;
|
||||
}SPSS7, *pSPSS7;
|
||||
/*------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
pSPSS7 sps;
|
||||
pHdb spsNode;
|
||||
char sendData[MAXDATA];
|
||||
char replyData[MAXDATA];
|
||||
int toSend;
|
||||
int toRead;
|
||||
char message[132];
|
||||
SConnection *pCon; /* only used when writing */
|
||||
}S7Action, *pS7Action;
|
||||
/*------------------------------------------------------------------*/
|
||||
static int S7ActionMatch(void *a1, void *a2)
|
||||
{
|
||||
if (a1 == a2){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------*/
|
||||
static void MakeFetchMessage(pS7Action self, int db, int start, int length)
|
||||
{
|
||||
unsigned short num;
|
||||
|
||||
memset(self->sendData,0,MAXDATA);
|
||||
memset(self->replyData,0,MAXDATA);
|
||||
self->sendData[0] = 'S';
|
||||
self->sendData[1] = '5';
|
||||
self->sendData[2] = 0x10;
|
||||
self->sendData[3] = 0x01;
|
||||
self->sendData[4] = 0x03;
|
||||
self->sendData[5] = 0x05;
|
||||
self->sendData[6] = 0x03;
|
||||
self->sendData[7] = 0x08;
|
||||
self->sendData[8] = 0x01;
|
||||
self->sendData[9] = db;
|
||||
self->sendData[6] = 0x03;
|
||||
/*
|
||||
* addresses are in words which is 16 bit = 2 bytes
|
||||
*/
|
||||
num = htons(start/2);
|
||||
memcpy(self->sendData+10,&num,2);
|
||||
num = htons(length/2);
|
||||
memcpy(self->sendData+12,&num,2);
|
||||
self->sendData[14] = 0xFF;
|
||||
self->sendData[15] = 0x02;
|
||||
self->toSend = 16;
|
||||
self->toRead = 16 + length;
|
||||
|
||||
sprintf(self->message,"%lx:%d:%lx:%d", (long) self->sendData, self->toSend,
|
||||
(long)self->replyData, self->toRead);
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
static void MakeWriteMessage(pS7Action self,
|
||||
int start, int length, void *data)
|
||||
{
|
||||
unsigned short num;
|
||||
|
||||
memset(self->sendData,0,MAXDATA);
|
||||
memset(self->replyData,0,MAXDATA);
|
||||
self->sendData[0] = 'S';
|
||||
self->sendData[1] = '5';
|
||||
self->sendData[2] = 0x10;
|
||||
self->sendData[3] = 0x01;
|
||||
self->sendData[4] = 0x03;
|
||||
self->sendData[5] = 0x03;
|
||||
self->sendData[6] = 0x03;
|
||||
self->sendData[7] = 0x08;
|
||||
self->sendData[8] = 0x01;
|
||||
self->sendData[9] = self->sps->switchdbnum;
|
||||
self->sendData[6] = 0x03;
|
||||
/*
|
||||
* Start is in bytes, length is in words which is 2 bytes....
|
||||
*/
|
||||
num = htons(start);
|
||||
memcpy(self->sendData+10,&num,2);
|
||||
num = htons(length/2);
|
||||
memcpy(self->sendData+12,&num,2);
|
||||
self->sendData[14] = 0xFF;
|
||||
self->sendData[15] = 0x02;
|
||||
memcpy(self->sendData+16, data, length);
|
||||
self->toSend = 16 + length;
|
||||
self->toRead = 16;
|
||||
|
||||
sprintf(self->message,"%lx:%d:%lx:%d", (long) self->sendData, self->toSend,
|
||||
(long)self->replyData, self->toRead);
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static int decodeString(char *pPtr, char *string, int maxlen)
|
||||
{
|
||||
int fullength, used;
|
||||
fullength = (int)pPtr[0];
|
||||
used = (int)pPtr[1];
|
||||
if(fullength != maxlen || used > maxlen){
|
||||
printf("Correcting DB String error\n");
|
||||
fullength = maxlen;
|
||||
used = maxlen;
|
||||
}
|
||||
memset(string,0,fullength);
|
||||
memcpy(string, pPtr+2, used);
|
||||
return fullength + 2;
|
||||
}
|
||||
/*------------------------------------------------------------------
|
||||
* This is the action handler for writing SPS data
|
||||
*-------------------------------------------------------------------*/
|
||||
static char *S7WriteHandler(void *actionData, char *reply, int comerror)
|
||||
{
|
||||
pS7Action self = (pS7Action)actionData;
|
||||
char message[132];
|
||||
SConnection *pCon = NULL;
|
||||
|
||||
if(reply == NULL){
|
||||
return self->message;
|
||||
}
|
||||
|
||||
pCon = self->pCon;
|
||||
if(self->replyData[8] != 0){
|
||||
snprintf(message,132,"ERROR: code %d when writing to S7/%s",
|
||||
self->replyData[8], GetHipadabaPath(self->spsNode));
|
||||
if(pCon != NULL){
|
||||
SCWrite(pCon,message,eError);
|
||||
printf("Write Shit %d happened\n", self->replyData[8]);
|
||||
} else {
|
||||
printf("%s\n", message);
|
||||
}
|
||||
} else {
|
||||
if(pCon != NULL){
|
||||
SCSendOK(pCon);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static void UpdateSPSDataBase(pS7Action self)
|
||||
{
|
||||
char *pPtr;
|
||||
char name[14], unit[8], description[24], reference[10], error[50];
|
||||
unsigned char type, alarm;
|
||||
short val;
|
||||
int ival;
|
||||
unsigned char bval;
|
||||
float fval;
|
||||
pHdb node = NULL;
|
||||
hdbValue hdbVal;
|
||||
|
||||
pPtr = self->replyData + 16 + 2;
|
||||
while(pPtr - self->replyData < self->toRead){
|
||||
type = pPtr[0];
|
||||
alarm = pPtr[1];
|
||||
pPtr+= 2;
|
||||
pPtr += decodeString(pPtr, name,14);
|
||||
pPtr += decodeString(pPtr, unit,8);
|
||||
pPtr += decodeString(pPtr, description,24);
|
||||
pPtr += decodeString(pPtr, reference,10);
|
||||
node = GetHipadabaNode(self->spsNode,name);
|
||||
switch (type) {
|
||||
case 1:
|
||||
case 4:
|
||||
memcpy(&bval,pPtr+1,1);
|
||||
hdbVal = MakeHdbInt(bval);
|
||||
UpdateHipadabaPar(node,hdbVal,NULL);
|
||||
pPtr += 2;
|
||||
break;
|
||||
case 2:
|
||||
memcpy(&ival,pPtr,4);
|
||||
hdbVal = MakeHdbInt(ntohl(ival));
|
||||
UpdateHipadabaPar(node,hdbVal,NULL);
|
||||
pPtr += 4;
|
||||
break;
|
||||
case 3:
|
||||
memcpy(&ival,pPtr+2,4);
|
||||
ival = htonl(ival);
|
||||
memcpy(&fval,&ival,4);
|
||||
hdbVal = MakeHdbFloat(fval);
|
||||
UpdateHipadabaPar(node,hdbVal,NULL);
|
||||
pPtr += 6;
|
||||
break;
|
||||
}
|
||||
if(alarm == 0){
|
||||
SetHdbProperty(node,"geterror", NULL);
|
||||
} else {
|
||||
snprintf(error,50,"Alarm %d on par",alarm);
|
||||
SetHdbProperty(node,"geterror", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------
|
||||
* This is the action handler for updating the SPS data in SICS
|
||||
*-------------------------------------------------------------------*/
|
||||
static char *S7UpdateHandler(void *actionData, char *reply, int comerror)
|
||||
{
|
||||
pS7Action self = (pS7Action)actionData;
|
||||
|
||||
if(reply == NULL){
|
||||
if(self->sps->dblength > 0){
|
||||
MakeFetchMessage(self,self->sps->dbnum, 0,self->sps->dblength);
|
||||
return self->message;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateSPSDataBase(self);
|
||||
return NULL;
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
static hdbCallbackReturn S7WriteCallback(pHdb currentNode,
|
||||
void *userData, pHdbMessage message)
|
||||
{
|
||||
pS7Action writeAction = NULL, updateAction = NULL;
|
||||
pSPSS7 self = (pSPSS7)userData;
|
||||
pHdbDataMessage mm = NULL;
|
||||
SConnection *pCon = NULL;
|
||||
int offset, type, length, idata;
|
||||
float fval;
|
||||
short sdata;
|
||||
unsigned char bdata;
|
||||
char prop[50];
|
||||
|
||||
mm = GetHdbSetMessage(message);
|
||||
if(mm != NULL){
|
||||
writeAction = calloc(1,sizeof(S7Action));
|
||||
if(writeAction == NULL && mm->callData != NULL){
|
||||
pCon = (SConnection *)mm->callData;
|
||||
SCWrite(pCon, "ERROR: out of memory in S7WriteCallback", eError);
|
||||
return hdbContinue;
|
||||
}
|
||||
writeAction->sps = self;
|
||||
writeAction->pCon = mm->callData;
|
||||
writeAction->spsNode = currentNode;
|
||||
GetHdbProperty(currentNode,"offset",prop,50);
|
||||
offset = atoi(prop);
|
||||
GetHdbProperty(currentNode,"type",prop,50);
|
||||
type = atoi(prop);
|
||||
switch(type){
|
||||
case 1:
|
||||
case 4:
|
||||
sdata = (short)mm->v->v.intValue;
|
||||
/* sdata = htons(sdata); */
|
||||
MakeWriteMessage(writeAction,offset,2,&sdata);
|
||||
break;
|
||||
case 2:
|
||||
idata = mm->v->v.intValue;
|
||||
idata = htonl(idata);
|
||||
MakeWriteMessage(writeAction,offset,4,&idata);
|
||||
break;
|
||||
case 3:
|
||||
fval = (float)mm->v->v.doubleValue;
|
||||
idata = htonl((int)fval);
|
||||
MakeWriteMessage(writeAction,offset,4,&idata);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
DevQueue(self->devser, writeAction, WritePRIO,
|
||||
S7WriteHandler, S7ActionMatch, free, NULL);
|
||||
|
||||
updateAction = calloc(1,sizeof(S7Action));
|
||||
if(updateAction != NULL){
|
||||
updateAction->sps = self;
|
||||
updateAction->spsNode = currentNode->mama->mama;
|
||||
DevQueue(self->devser, updateAction, ProgressPRIO,
|
||||
S7UpdateHandler, S7ActionMatch, free, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return hdbContinue;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static void InitializeSPSDataBase(pS7Action self, pHdb parent)
|
||||
{
|
||||
char *pPtr;
|
||||
char name[14], unit[8], description[24], reference[10], num[10], error[50];
|
||||
unsigned char type, alarm;
|
||||
short val;
|
||||
int ival;
|
||||
float fval;
|
||||
unsigned char bval;
|
||||
pHdb node = NULL;
|
||||
hdbValue hdbVal;
|
||||
|
||||
pPtr = self->replyData + 16 + 2;
|
||||
while(pPtr - self->replyData < self->toRead){
|
||||
type = pPtr[0];
|
||||
alarm = pPtr[1];
|
||||
pPtr+= 2;
|
||||
pPtr += decodeString(pPtr, name,14);
|
||||
pPtr += decodeString(pPtr, unit,8);
|
||||
pPtr += decodeString(pPtr, description,24);
|
||||
pPtr += decodeString(pPtr, reference,10);
|
||||
switch (type) {
|
||||
case 1:
|
||||
case 4:
|
||||
node = MakeHipadabaNode(name,HIPINT,1);
|
||||
memcpy(&bval,pPtr+1,1);
|
||||
hdbVal = MakeHdbInt(bval);
|
||||
UpdateHipadabaPar(node,hdbVal,NULL);
|
||||
snprintf(num,10,"%d", pPtr - self->replyData - 16);
|
||||
SetHdbProperty(node,"offset",num);
|
||||
pPtr += 2;
|
||||
break;
|
||||
case 2:
|
||||
node = MakeHipadabaNode(name,HIPINT,1);
|
||||
memcpy(&ival,pPtr,4);
|
||||
hdbVal = MakeHdbInt(ntohl(ival));
|
||||
UpdateHipadabaPar(node,hdbVal,NULL);
|
||||
snprintf(num,10,"%d", pPtr - self->replyData - 16);
|
||||
SetHdbProperty(node,"offset",num);
|
||||
pPtr += 4;
|
||||
break;
|
||||
case 3:
|
||||
node = MakeHipadabaNode(name,HIPFLOAT,1);
|
||||
memcpy(&ival,pPtr+2,4);
|
||||
ival = htonl(ival);
|
||||
memcpy(&fval,&ival,4);
|
||||
hdbVal = MakeHdbFloat(fval);
|
||||
UpdateHipadabaPar(node,hdbVal,NULL);
|
||||
snprintf(num,10,"%d", pPtr - self->replyData + 2 - 16);
|
||||
SetHdbProperty(node,"offset",num);
|
||||
pPtr += 6;
|
||||
break;
|
||||
}
|
||||
snprintf(num,10,"%d",type);
|
||||
SetHdbProperty(node,"type", num);
|
||||
if(alarm != 0){
|
||||
snprintf(error,10,"Alarm %d on par",alarm);
|
||||
SetHdbProperty(node,"geterror", error);
|
||||
}
|
||||
SetHdbProperty(node,"unit", unit);
|
||||
SetHdbProperty(node,"description", description);
|
||||
SetHdbProperty(node,"reference", reference);
|
||||
AddHipadabaChild(parent,node, NULL);
|
||||
printf("Found parameter %s\n", name);
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------
|
||||
* This is the action handler for doing the initialisation of
|
||||
* The SPS
|
||||
*-------------------------------------------------------------------*/
|
||||
static char *S7InitHandler(void *actionData, char *reply, int comerror)
|
||||
{
|
||||
pS7Action self = (pS7Action)actionData;
|
||||
short dblength;
|
||||
|
||||
/*
|
||||
* Start: read length of the database
|
||||
*/
|
||||
if(reply == NULL){
|
||||
self->sps->dblength = 0;
|
||||
MakeFetchMessage(self,self->sps->dbnum, 0,2);
|
||||
return self->message;
|
||||
}
|
||||
|
||||
/*
|
||||
* we are reading the database length
|
||||
*/
|
||||
if(self->sps->dblength == 0){
|
||||
memcpy(&dblength, self->replyData+16,2);
|
||||
self->sps->dblength = ntohs(dblength);
|
||||
MakeFetchMessage(self,self->sps->dbnum, 0,ntohs(dblength));
|
||||
return self->message;
|
||||
} else {
|
||||
memcpy(&dblength, self->replyData+16,2);
|
||||
dblength = ntohs(dblength);
|
||||
InitializeSPSDataBase(self,self->spsNode);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void InitializeSwitches(pS7Action self)
|
||||
{
|
||||
pHdb switches = NULL, node = NULL;
|
||||
int i;
|
||||
char name[20];
|
||||
|
||||
switches = GetHipadabaNode(self->spsNode,"switches");
|
||||
assert(switches != NULL);
|
||||
|
||||
/*
|
||||
* TODO: Add write callbacks to switches
|
||||
*/
|
||||
node = switches->child;
|
||||
while(node != NULL){
|
||||
AppendHipadabaCallback(node,
|
||||
MakeHipadabaCallback(S7WriteCallback,self->sps,NULL));
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
node = GetHipadabaNode(self->spsNode,"init");
|
||||
if(node != NULL){
|
||||
UpdateHipadabaPar(node,MakeHdbInt(1), NULL);
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static char *S7InitSwitchHandler(void *actionData, char *reply, int comerror)
|
||||
{
|
||||
pS7Action self = (pS7Action)actionData;
|
||||
short dblength;
|
||||
pHdb parent = NULL;
|
||||
|
||||
/*
|
||||
* Start: read length of the database
|
||||
*/
|
||||
if(reply == NULL){
|
||||
self->sps->switchdblength = 0;
|
||||
MakeFetchMessage(self,self->sps->switchdbnum, 0,2);
|
||||
return self->message;
|
||||
}
|
||||
|
||||
/*
|
||||
* we are reading the database length
|
||||
*/
|
||||
if(self->sps->switchdblength == 0){
|
||||
memcpy(&dblength, self->replyData+16,2);
|
||||
self->sps->switchdblength = ntohs(dblength);
|
||||
MakeFetchMessage(self,self->sps->switchdbnum,
|
||||
0,ntohs(dblength));
|
||||
return self->message;
|
||||
} else {
|
||||
parent = GetHipadabaNode(self->spsNode,"switches");
|
||||
assert(parent != NULL);
|
||||
InitializeSPSDataBase(self,parent);
|
||||
InitializeSwitches(self);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*===================================================================*/
|
||||
static int S7UpdateCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
pSPSS7 self = (pSPSS7)ccmd->pPrivate;
|
||||
pS7Action updateAction = NULL;
|
||||
|
||||
updateAction = calloc(1,sizeof(S7Action));
|
||||
if(updateAction == NULL){
|
||||
SCWrite(con,"ERROR: out of memory in S7 update", eError);
|
||||
return 0;
|
||||
}
|
||||
updateAction->sps = self;
|
||||
updateAction->spsNode = ccmd->objectNode;
|
||||
DevQueue(self->devser, updateAction, ProgressPRIO,
|
||||
S7UpdateHandler, S7ActionMatch, free, NULL);
|
||||
SCSendOK(con);
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static void KillSPSS7(void *data)
|
||||
{
|
||||
pSPSS7 self = (pSPSS7)data;
|
||||
if(self == NULL){
|
||||
return;
|
||||
}
|
||||
if(self->devser != NULL){
|
||||
DevKill(self->devser);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
int MakeSPSS7(SConnection * con, SicsInterp * sics,
|
||||
void *object, int argc, char *argv[])
|
||||
{
|
||||
pSPSS7 self = NULL;
|
||||
pSICSOBJ pNew = NULL;
|
||||
char *devArgs[3];
|
||||
pS7Action initAction = NULL, updateAction = NULL,
|
||||
initSwitchAction = NULL;
|
||||
|
||||
int status;
|
||||
|
||||
if(argc < 5){
|
||||
SCWrite(con,"ERROR: not enough arguments for MakeSPSS7", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
self = calloc(1,sizeof(SPSS7));
|
||||
if(self == NULL){
|
||||
SCWrite(con,"ERROR: out of memory in MakeSPSS7", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
devArgs[0] = strdup("genbin");
|
||||
devArgs[1] = strdup(argv[4]);
|
||||
|
||||
self->devser = DevMake(con,2,devArgs);
|
||||
if(self->devser == NULL){
|
||||
return 0;
|
||||
}
|
||||
free(devArgs[0]);
|
||||
free(devArgs[1]);
|
||||
|
||||
self->dbnum = atoi(argv[2]);
|
||||
self->switchdbnum = atoi(argv[3]);
|
||||
|
||||
pNew = MakeSICSOBJv(argv[1],"SPS-S7", HIPNONE, usInternal);
|
||||
if(pNew == NULL){
|
||||
SCWrite(con,"ERROR: out of memory in MakeSPSS7", eError);
|
||||
return 0;
|
||||
}
|
||||
pNew->pPrivate = self;
|
||||
pNew->KillPrivate = KillSPSS7;
|
||||
|
||||
status = AddCommand(sics,
|
||||
argv[1], InterInvokeSICSOBJ, KillSICSOBJ, pNew);
|
||||
if (status != 1) {
|
||||
KillSICSOBJ(pNew);
|
||||
SCPrintf(con, eError, "ERROR: failed create duplicate command %s",
|
||||
argv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
AddSICSHdbPar(pNew->objectNode,
|
||||
"update", usSpy, MakeSICSFunc(S7UpdateCmd));
|
||||
|
||||
AddHipadabaChild(pNew->objectNode,
|
||||
MakeSICSROPar("init",MakeHdbInt(0)),NULL);
|
||||
|
||||
AddHipadabaChild(pNew->objectNode,
|
||||
MakeHipadabaNode("switches",HIPNONE,0),NULL);
|
||||
|
||||
|
||||
initAction = calloc(1,sizeof(S7Action));
|
||||
initSwitchAction = calloc(1,sizeof(S7Action));
|
||||
updateAction = calloc(1,sizeof(S7Action));
|
||||
if(initAction == NULL || updateAction == NULL || initSwitchAction == NULL){
|
||||
SCWrite(con,"ERROR: out of memory in MakeSPSS7", eError);
|
||||
return 0;
|
||||
}
|
||||
initAction->sps = self;
|
||||
initAction->spsNode = pNew->objectNode;
|
||||
DevQueue(self->devser, initAction, WritePRIO,
|
||||
S7InitHandler, S7ActionMatch, free, NULL);
|
||||
|
||||
initSwitchAction->sps = self;
|
||||
initSwitchAction->spsNode = pNew->objectNode;
|
||||
DevQueue(self->devser, initSwitchAction, WritePRIO,
|
||||
S7InitSwitchHandler, S7ActionMatch, free, NULL);
|
||||
|
||||
updateAction->sps = self;
|
||||
updateAction->spsNode = pNew->objectNode;
|
||||
DevSchedule(self->devser, updateAction,
|
||||
ReadPRIO, 60.,
|
||||
S7UpdateHandler, S7ActionMatch, free, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
Reference in New Issue
Block a user