Commit 229c1e7d authored by claes's avatar claes

Module remote created

parent cb2e67d1
include $(pwre_dir_symbols)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(hw_name)/$(type_name)_generic.mk
ifeq ($($(type_name)_generic_mk),)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(type_name)_generic.mk
endif
ifeq ($($(type_name)_generic_mk),)
include $(pwre_kroot)/tools/bld/src/$(type_name)_generic.mk
endif
ifndef link_rule_mk
link_rule_mk := 1
link = $(ldxx) $(elinkflags) $(domap) -o $(export_exe) \
$(export_obj) $(objects) $(rt_msg_eobjs) \
-lpwr_remote -lpwr_rt -lpwr_co -lpwr_msg_dummy -lpthread -lm
endif
/*
* Proview $Id: rs_remote_3964r.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*************************************************************************
*
* 3 9 6 4 R
* ==========
**************************************************************************
*
* Filename: rs_remote_3964r.c
*
* Date Pgm. Read. Remark
* Modified 010401 ulflj - for lynx
* 010815 ulflj fixed for pwr 3.3a
* 020530 ulflj modified serial parameter
* read in lynx version
* 030814 ulflj Linux version improved
* 030830 ulflj fixed timeouts for DLE-answer/characters
* 031118 ulflj set longer char timeout to get magnemag marker to work (longer then specs)
*
* Description: Implements remote transport process 3964R.
*
**************************************************************************
**************************************************************************/
/*_Include files_________________________________________________________*/
/*System includes*/
#include <time.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
//#include <uio.h>
#include <termios.h>
#include <termio.h>
#include <sgtty.h>
#include <sys/ioctl.h>
/*PWR includes*/
#include "pwr_class.h"
#include "pwr_baseclasses.h"
#include "pwr_remoteclasses.h"
#include "remote_mq.h"
#include "co_cdh.h"
#include "rt_gdh.h"
#include "rt_aproc.h"
#include "rt_pwr_msg.h"
#include "remote.h"
#include "remote_utils.h"
#include "remote_remtrans_utils.h"
#include "remote_remio_utils.h"
#include "pwr.h"
#include "rt_gdh.h"
#include "rt_gdh_msg.h"
#include "rt_plc_utl.h"
#include "rt_errh.h"
#include "co_time.h"
/*_Function prototypes___________________________________________________*/
void send_pollbuff(remnode_item *remnode, pssupd_buffer_vnet *buf);
static unsigned int remnode_send(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buffer_size);
static unsigned int send_it(char *buf,
int buffer_size);
static unsigned int Receive();
static unsigned int ReceiveHandler();
/*_defines_________________________________________________________________*/
#define NUMBER_OF_STOP_CHAR 3
#define NET_HEADER_SIZE_IO 6
#define NET_HEADER_SIZE_COMMON 8
#define MAX_SIZE_TELEGRAM 2048
//#define TIMEOUT_REC_ANSWER_SEC 2
//#define TIMEOUT_REC_ANSWER_USEC 0
//#define TIMEOUT_REC_CHAR_SEC 0
//#define TIMEOUT_REC_CHAR_USEC 900000
//#define TIMEOUT_SND_ANSWER_SEC 2
//#define TIMEOUT_SND_ANSWER_USEC 0
//#define TIMEOUT_SND_CHAR_SEC 0
//#define TIMEOUT_SND_CHAR_USEC 900000
#define NUL 0
#define STX 2
#define ETX 3
#define DLE 16
#define NAK 21
#define DLE_BITMASK 0x10000
/*_variables_______________________________________________________________*/
remnode_item rn;
pwr_sClass_Remnode3964R *rn_3964R;
int ser_fd; /* file domininator for serial port */
unsigned char debug=0; /* 1 if debug mode activated */
float time_since_poll;
float time_since_io;
float time_since_scan;
int stall_action = 1;
int use_remote_io;
void load_timeval(struct timeval *tv, float t)
{
tv->tv_sec = t;
tv->tv_usec = (t-(float)tv->tv_sec) * 1000000;
}
short poll_id[2];
/*_variables_______________________________________________________________*/
/*************************************************************************
**************************************************************************
*
* Namn : send_pollbuff
*
* Typ : void
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends a poll or IO update message to Remote node
*
**************************************************************************
**************************************************************************/
void send_pollbuff(remnode_item *remnode, pssupd_buffer_vnet *buf)
{
unsigned int sts, buf_size;
/* Fill in remaining data in poll telegram */
RemUtils_AsciiToR50("PSSUPD", (short *) &buf->receive_task);
buf->common_name[0] = poll_id[0];
buf->common_name[1] = poll_id[1];
buf_size = buf->length * 2; /* Convert to bytes */
sts = send_it((char*)buf, buf_size);
return;
}
/*************************************************************************
**************************************************************************
*
* Namn : remnode_send
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends a RemTrans message to Remote node
*
**************************************************************************
**************************************************************************/
static unsigned int remnode_send(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buffer_size)
{
unsigned int sts;
sts = send_it(buf, buffer_size);
return sts;
}
/*************************************************************************
**************************************************************************
*
* Namn : send_it
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends a buffer
*
**************************************************************************
**************************************************************************/
static unsigned int send_it(char *buf, int buffer_size)
{
int sts, i;
unsigned int size_of_telegram;
unsigned int number_of_DLE = 0;
unsigned char ch;
unsigned char BCC = DLE ^ ETX;
unsigned char *restore_buf_ptr = buf;
unsigned char telegram[MAX_SIZE_TELEGRAM];
unsigned char buff;
static unsigned char sstx[2] = {STX, '\0'};
//static unsigned char sdle[2] = {DLE, '\0'};
static unsigned char snak[2] = {NAK, '\0'};
fd_set read_fd;
struct timeval tv;
/*************************************************************************/
/** Count DLE characters and calculate the size of the telegram. **/
/*************************************************************************/
for ( i=0 ; i < buffer_size ; i++ )
{
if ( *buf++ == DLE )
number_of_DLE += 1;
}
size_of_telegram = buffer_size + number_of_DLE + NUMBER_OF_STOP_CHAR;
/*************************************************************************/
/** Fill up telegram with contents of message and calculate BCC **/
/*************************************************************************/
buf = restore_buf_ptr;
for ( i=0 ; i<(buffer_size + number_of_DLE) ; i++ )
{
ch = telegram[i] = *buf++;
BCC ^= ch;
if ( ch == DLE )
{
telegram[++i] = DLE;
BCC ^= ch;
}
}
telegram[i++] = DLE;
telegram[i++] = ETX;
telegram[i] = BCC;
/*************************************************************************/
/** Execute the send procedure **/
/*************************************************************************/
/**** set up timeout ****/
// tv.tv_sec = TIMEOUT_SND_ANSWER_SEC;
// tv.tv_usec = TIMEOUT_SND_ANSWER_USEC;
load_timeval(&tv, rn_3964R->AckTimeout);
FD_ZERO(&read_fd);
FD_SET(ser_fd, &read_fd);
sts=TRUE;
write(ser_fd, sstx, 1); /*send stx and wait for answer*/
select(ser_fd+1, &read_fd, NULL, NULL, &tv); /*wait for char or timeout*/
sts=read(ser_fd,&buff,1); /*read port*/
if(sts < 1) /*if timeout*/
{
errh_Error("Remtrans 3964R, sndning, inget svar frn mottagaren, frsker igen");
write(ser_fd, sstx, 1); /*try once more*/
FD_ZERO(&read_fd);
FD_SET(ser_fd, &read_fd);
load_timeval(&tv, rn_3964R->AckTimeout);
select(ser_fd+1, &read_fd, NULL, NULL, &tv);
sts=read(ser_fd,&buff,1);
}
if(sts > 0 && buff==DLE) /*if DLE ok send telegram*/
{
write(ser_fd, telegram, size_of_telegram);
// tv.tv_sec = TIMEOUT_SND_ANSWER_SEC;
// tv.tv_usec = TIMEOUT_SND_ANSWER_USEC;
load_timeval(&tv, rn_3964R->AckTimeout);
FD_ZERO(&read_fd);
FD_SET(ser_fd, &read_fd);
select(ser_fd+1, &read_fd, NULL, NULL, &tv);
sts=read(ser_fd,&buff,1);
}
if(sts < 1 || buff!=DLE) /*if somthing went wrong*/
{
write(ser_fd,snak, 1);
if(sts<1)
errh_Error("Remtrans 3964R sndning misslyckades, inget initierande DLE-tecken frn mottagaren");
else if(buff!=DLE)
errh_Error("Remtrans 3964R sndning misslyckades, inget avslutande DLE-tecken frn mottagaren");
sts=FALSE;
}
return sts; /*and return status*/
}
/*************************************************************************
**************************************************************************
*
* Namn : Receive
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Waits for STX on serial line
*
**************************************************************************
**************************************************************************/
static unsigned int Receive()
{
static int sts;
unsigned char received_char = NUL;
static unsigned char snak[2] = {NAK, NUL};
static unsigned char sdle[2] = {DLE, NUL};
//static int error_logged = 0;
fd_set read_fd;
struct timeval tv;
/**** set up timeout ****/
load_timeval(&tv, 0); // poll
// load_timeval(&tv, rn_3964R->ScanTime);
// tv.tv_sec = TIMEOUT_REC_ANSWER_SEC;
// tv.tv_usec = TIMEOUT_REC_ANSWER_USEC;
/**routine**/
FD_ZERO(&read_fd);
FD_SET(ser_fd, &read_fd);
sts=select(ser_fd+1, &read_fd, NULL, NULL, &tv);
sts=read(ser_fd, &received_char, 1);
if (sts > 0)
{
if (received_char == STX)
{
/* Write DLE to respond */
if(!write(ser_fd, sdle, 1))
return 0;
sts = ReceiveHandler(ser_fd);
}
else
{
/* We don't understand, Send NAK unless NAK is received */
if (received_char != NAK)
write(ser_fd, snak, 1);
errh_Error("3964R felaktigt meddelande i mottagning, annat starttecken n STX (0x%x)", received_char);
sts=0; //felstatus
}
if (sts < 1)
{
rn_3964R->ErrCount++;
}
}
return(1);
}
/*************************************************************************
**************************************************************************
*
* Namn : ReceiveHandler
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Invoked when a telegram is received.
*
**************************************************************************
**************************************************************************/
static unsigned int ReceiveHandler(int fd)
{
unsigned int sts;
//unsigned int nbr_of_bytes_written = 0;
//unsigned int nbr_of_bytes_read = 0;
unsigned int data_size = 0;
unsigned int io_size = 0;
unsigned int common_offset = 0;
char cont = TRUE;
char search_remtrans = FALSE;
char name[7];
unsigned char BCC = '\0';
unsigned char receive_buffer[MAX_SIZE_TELEGRAM];
unsigned char sdle = DLE;
unsigned char received_char;
remtrans_item *remtrans;
int i;
fd_set read_fd;
struct timeval tv;
char type_name[4];
common_buffer_vnet *c_buf;
/**** set up timeout,****/
load_timeval(&tv, rn_3964R->CharTimeout);
// tv.tv_sec = TIMEOUT_REC_CHAR_SEC;
// tv.tv_usec = TIMEOUT_REC_CHAR_USEC;
/*************************************************************************/
/** Read telegram **/
/*************************************************************************/
cont = TRUE;
data_size = 0;
while (cont)
{
/* Read until DLE is received */
received_char=0;
while(received_char != DLE)
{
load_timeval(&tv, rn_3964R->CharTimeout);
FD_ZERO(&read_fd);
FD_SET(fd, &read_fd);
select(fd+1, &read_fd, NULL, NULL, &tv);
if (read(fd, &received_char, 1) > 0) { //om det inte var timeout
// Prevent writing oob
if (data_size > MAX_SIZE_TELEGRAM - 10) return (FALSE);
receive_buffer[data_size++]=received_char;
}
else //timeout g tillbaka
{
errh_Error("3964R mottagning, character timeout");
return(FALSE);
}
}
/* Read one more */
load_timeval(&tv, rn_3964R->CharTimeout);
FD_ZERO(&read_fd);
FD_SET(fd, &read_fd);
select(fd+1, &read_fd, NULL, NULL, &tv);
if (read(fd, &receive_buffer[data_size], 1) < 1) {
errh_Error("3964R mottagning, character timeout");
return(FALSE);
}
if (receive_buffer[data_size] == ETX)
{
data_size++;
/* Read one more, should be checksum */
load_timeval(&tv, rn_3964R->CharTimeout);
FD_ZERO(&read_fd);
FD_SET(fd, &read_fd);
select(fd+1, &read_fd, NULL, NULL, &tv);
if (read(fd, &receive_buffer[data_size], 1) < 1) {
errh_Error("3964R mottagning, character timeout");
return(FALSE);
}
data_size++;
cont = FALSE;
}
else
if (receive_buffer[data_size] != DLE ) data_size++;
}
/*************************************************************************/
/** A complete message is received. Check BCC. **/
/*************************************************************************/
BCC = DLE ^ ETX;
for (i=0; i<data_size-3; i++)
if (receive_buffer[i] != DLE)
BCC ^= receive_buffer[i];
if ( BCC == receive_buffer[data_size-1] ) {
if(!write(fd,&sdle, 1)) return(FALSE);
}
else
{
/* Checksum in this telegram is wrong */
errh_Error("3964R mottagning, felaktig checksumma, %d, %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
data_size, receive_buffer[0], receive_buffer[1], receive_buffer[2], receive_buffer[3], receive_buffer[4], receive_buffer[5],
receive_buffer[6], receive_buffer[7], receive_buffer[8], receive_buffer[9], receive_buffer[10], receive_buffer[11]);
if (debug) printf(" Checksum error\n");
if (use_remote_io) {
if(!write(fd,&sdle, 1)) return(FALSE);
}
else
return(FALSE);
}
/*************************************************************************/
/** Find out if the received message is a array of io updates. **/
/** Treat the message and exit. **/
/*************************************************************************/
{
io_buffer_vnet *io_buf = (io_buffer_vnet *) &receive_buffer;
RemUtils_R50ToAscii((unsigned short *) &io_buf->io_name, (char *) &name);
if (strstr(name, "PSS")) {
io_size = io_buf->length * 2; /* Converted to bytes */
sts = RemIO_Receive_3964R(&rn,
(unsigned char *) &io_buf->data,
io_size-NET_HEADER_SIZE_IO);
if (debug) printf(" Receiving I/O area\n");
time_since_io = 0;
rn_3964R->LinkUp = 1;
return(sts);
}
}
/*************************************************************************/
/** Find out if the received message is a array of common data **/
/** Search for the RemTrans object that is the target. **/
/*************************************************************************/
c_buf = (common_buffer_vnet *) &receive_buffer;
RemUtils_R50ToAscii((unsigned short *) &c_buf->common_name, (char *) &name);
for ( i=0 ; i<4 ; i++ )
{
type_name[i] = name[i+3];
}
if ( (strncmp(type_name, "COM", 3)) == 0 ){
search_remtrans = true;
remtrans = rn.remtrans;
while(remtrans && search_remtrans)
{
if ( remtrans->objp->Address[0] == c_buf->common_name[0] &&
remtrans->objp->Address[1] == c_buf->common_name[1] )
search_remtrans = false;
if ( search_remtrans )
remtrans = (remtrans_item *) remtrans->next;
} /* endwhile */
/*************************************************************************/
/** Treat the common data update message and exit. **/
/*************************************************************************/
if ( !search_remtrans ){
io_size = c_buf->length * 2; /* Converted to bytes */
common_offset = c_buf->offset;
if (io_size > remtrans->objp->MaxLength ){
remtrans->objp->ErrCount++;
remtrans->objp->LastSts = STATUS_LENGTH;
return(FALSE);
}
else {
memcpy(&remtrans->datap[common_offset], c_buf, io_size);
clock_gettime( CLOCK_REALTIME, &remtrans->objp->TransTime);
remtrans->objp->TransCount++;
remtrans->objp->DataValid = TRUE;
remtrans->objp->LastSts = STATUS_OK;
remtrans->objp->DataLength = data_size;
}
return(TRUE);
}
}
/*************************************************************************/
/** This message contains a ordinary remtrans **/
/** Search for the RemTrans object that is the target. **/
/** If remote I/O is not used, the message is stored in the first **/
/** found (ingoing) remtrans object. If we use remote I/O we check for**/
/** matching message header **/
/*************************************************************************/
search_remtrans = true;
remtrans = rn.remtrans;
while(remtrans && search_remtrans)
{
if (remtrans->objp->Direction == REMTRANS_IN) {
if (!use_remote_io) {
search_remtrans = false;
}
else {
if (remtrans->objp->Address[0] == c_buf->common_name[0] &&
remtrans->objp->Address[1] == c_buf->common_name[1])
search_remtrans = false;
}
}
if ( search_remtrans ) remtrans = (remtrans_item *) remtrans->next;
}
/*************************************************************************/
/** Treat the remtrans message and exit. **/
/*************************************************************************/
if (!search_remtrans)
{
sts = RemTrans_Receive(remtrans, receive_buffer, data_size-3);
if ( EVEN(sts) )
{
remtrans->objp->ErrCount++;
return (FALSE);
}
}
else
{
/* No remtrans */
errh_Error("Remtrans 3964R no remtrans for this message");
rn_3964R->ErrCount++;
return (FALSE);
}
return (TRUE);
}
/***************************************************
****** Main routine *****************
***************************************************/
int main(int argc, char *argv[]) /*argv[2]=remnode name*/
{
unsigned int sts; /* Status from function calls etc. */
unsigned char id[32];
unsigned char pname[32];
remtrans_item *remtrans;
int i;
char first;
pssupd_buffer_vnet buff; /* Buffer for 'hello' */
pssupd_order_header *header; /* Header for 'hello' */
char name[80];
/* Read arg number 2, should be id for this instance */
if (argc >= 2)
strcpy(id, argv[1]);
else
strcpy(id, "0");
/* Build process name with id */
sprintf((char *) pname, "rs_rem3964r_%s", id);
/* Init of errh */
errh_Init((char *) pname, errh_eAnix_remote);
errh_SetStatus(PWR__SRVSTARTUP);
/* Init of gdh */
sts = gdh_Init((char *) pname);
if ( EVEN(sts)) {
errh_Error("gdh_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Arg number 3 should be my remnodes objid in string representation,
read it, convert to real objid and store in remnode_item */
sts = 0;
if (argc >= 3) sts = cdh_StringToObjid(argv[2], &rn.objid);
if ( EVEN(sts)) {
errh_Error("cdh_StringToObjid, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Get pointer to Remnode3964R object and store locally */
sts = gdh_ObjidToPointer(rn.objid, (pwr_tAddress *) &rn_3964R);
if ( EVEN(sts)) {
errh_Error("cdh_ObjidToPointer, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Get name of object to use in sending poll */
sts = gdh_ObjidToName(rn.objid, name, sizeof(name), cdh_mName_object);
name[3] = 'P';
name[4] = 'S';
name[5] = 'S';
name[6] = 0;
RemUtils_AsciiToR50((char *) &name, (short *) &poll_id);
if (debug) printf("%s, %d %d\n", name, poll_id[0], poll_id[1]);
/* Initialize some internal data and make standard remtrans init */
rn.next = NULL;
rn.local = NULL; // We dont use local structure since we only have one remnode
rn.retransmit_time = 10.0; // Not used, but initialize anyway
rn_3964R->ErrCount = 0;
sts = RemTrans_Init(&rn);
if ( EVEN(sts)) {
errh_Error("RemTrans_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
sts = RemIO_Init_3964R(&rn);
if ( EVEN(sts)) {
errh_Error("RemIO_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
if (rn.remio_data == NULL)
use_remote_io = 0;
else
use_remote_io = 1;
time_since_poll = 0.0;
time_since_io = 0.0;
time_since_scan = 0.0;
/* Store remtrans objects objid in remnode_3964R object */
remtrans = rn.remtrans;
i = 0;
while(remtrans) {
rn_3964R->RemTransObjects[i++] = remtrans->objid;
if ( i >= (int)(sizeof(rn_3964R->RemTransObjects)/sizeof(rn_3964R->RemTransObjects[0])))
break;
remtrans = (remtrans_item *) remtrans->next;
}
/* Initialize device */
ser_fd = RemUtils_InitSerialDev(rn_3964R->DevName,
rn_3964R->Speed,
rn_3964R->DataBits,
rn_3964R->StopBits,
rn_3964R->Parity);
if (!ser_fd) {
errh_Error("InitDev, %d", ser_fd);
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
first = TRUE;
rn_3964R->LinkUp = 1;
/* Loop forever */
while (1)
{
if (rn_3964R->Disable == 1) {
errh_Fatal("Disabled, exiting");
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
// Wait micro time
// Wait cycle time
// timer = (int) (rn_3964R->ScanTime * 1000000.0);
usleep(30000);
Receive();
// time_since_poll += rn_3964R->ScanTime;
// time_since_io += rn_3964R->ScanTime;
time_since_poll += 0.03;
time_since_io += 0.03;
time_since_scan += 0.03;
if (first && use_remote_io) {
/* Send Hello to subsystem if we have poll */
header = (pssupd_order_header *) &buff.data;
header->type = PSS_Switch_Done;
header->size = 0;
header->signal = 0;
buff.no_of_updates = 1;
buff.length = (sizeof(pssupd_buffer_vnet) -
MAX_ORDER_BUFFERSIZE_VNET + sizeof(pssupd_order_header) + 1) / 2;
send_pollbuff(&rn, &buff);
}
// if (debug) printf("Remtrans Cyclic\n");
if (time_since_scan >= rn_3964R->ScanTime) {
if (debug) printf("Remtrans Cyclic\n");
RemTrans_Cyclic(&rn, &remnode_send);
time_since_scan = 0.0;
}
if (use_remote_io) {
if ((rn_3964R->LinkUp && time_since_poll >= rn_3964R->ScanTime*2.0) ||
(!rn_3964R->LinkUp && time_since_poll >= rn_3964R->ScanTime*10.0))
{
if (debug) printf("RemIO Cyclic\n");
sts = RemIO_Cyclic_3964R(&rn, &send_pollbuff);
time_since_poll = 0.0;
}
if (time_since_io >= rn_3964R->LinkTimeout && rn_3964R->LinkTimeout > 0) {
if (debug) printf("RemIO Stall\n");
sts = RemIO_Stall_3964R(&rn, stall_action);
}
}
first = FALSE;
}
}
/*
* Proview $Id: rs_remote_3964r_vnet.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*************************************************************************
*
* 3 9 6 4 R
* ==========
**************************************************************************
*
* Filename: remote_3964r_vnet.c
*
* Date Pgm. Read. Remark
* Modified
*
*
* Description: Implements remote transport process 3964R.
* For poll off io and commondata from PSS7000(VNET).
*
**************************************************************************
**************************************************************************/
/*_Include files_________________________________________________________*/
#ifdef OS_ELN
#include $vaxelnc
#include $exit_utility
#include $function_descriptor
#include $dda_utility
#include $elnmsg
#include $kernelmsg
#include ssdef
#include stdio
#include stdlib
#include string
#include math
#include iodef
#include descrip
#include psldef
#include libdtdef
#include starlet
#include lib$routines
#endif
#ifdef OS_VMS
#include <ssdef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <iodef.h>
#include <descrip.h>
#include <psldef.h>
#include <libdtdef.h>
#include <starlet.h>
#include <lib$routines.h>
#endif
#include "pwr_class.h"
#include "pwr_systemclasses.h"
#include "co_time.h"
#include "rt_gdh.h"
#include "pwr_baseclasses.h"
#include "pwr_ssabclasses.h"
#include "rs_remote_msg.h"
#include "rs_remote.h"
#include "rs_remtrans_utils.h"
#include "rs_remio_utils.h"
#include "rs_remote_rad50.h"
/*_Function prototypes___________________________________________________*/
static void exith(void);
static void DeclareExitHandler(void);
static unsigned int InitTimers(void);
static unsigned int InitNet(void);
static unsigned int remnode_send(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buf_size);
static unsigned int send_it(char *buf,
int buf_size);
static unsigned int Receive();
static unsigned int ReceiveHandler();
#ifdef OS_VMS
int WaitFor_PLC_Change();
#endif
/*_defines_________________________________________________________________*/
#define NUMBER_OF_STOP_CHAR 3
#define NET_HEADER_SIZE_IO 6
#define NET_HEADER_SIZE_COMMON 8
#define MAX_SIZE_TELEGRAM 512
#define NUL 0
#define STX 2
#define ETX 3
#define DLE 16
#define NAK 21
/*_variables_______________________________________________________________*/
#ifdef OS_ELN
/*
* ELN specific variables
*/
PORT virtual_serial_line_port;
PORT job_port;
PROCESS my_proc;
LARGE_INTEGER timeout_ack; /* Ack. time out on STX request */
LARGE_INTEGER timeout_char; /* Time out receive of next character */
LARGE_INTEGER timeout_cycle; /* Init. from remnode:CycleTime */
#else
/*
* VMS specific variables
*/
unsigned int receive_ef;
unsigned int timer_ef;
unsigned int ef_mask;
#endif
/*
* Variables common for VMS and ELN
*/
remnode_item remnode_struct;
remnode_item *remnode = &remnode_struct;
/*************************************************************************
**************************************************************************
*
* Namn : exith
*
* Typ : void
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Exit handler that is called before process termination
*
**************************************************************************
**************************************************************************/
static void exith(void)
{
#ifdef OS_ELN
return;
#else
return;
#endif
}
/*************************************************************************
**************************************************************************
*
* Namn : DeclareExitHandler
*
* Typ : void
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Declares an exit handler that is called before
* process termination
*
**************************************************************************
**************************************************************************/
static void DeclareExitHandler(void)
{
#ifdef OS_ELN
FUNCTION_DESCRIPTOR fn_descriptor;
eln$declare_exit_handler(ELN$PASS_FUNCTION_DESCRIPTOR(fn_descriptor, exith),
NULL);
#else
atexit(exith);
#endif
}
/************************************************************************
**************************************************************************
*
* Namn : InitTimers
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Initiates the timers used in this process.
*
**************************************************************************
**************************************************************************/
static unsigned int InitTimers(void)
{
unsigned int sts;
unsigned int time_function_code = LIB$K_DELTA_SECONDS_F;
float max_acknowledge_delay = 2.0;
float max_char_delay = 0.22;
/* Konvertera cykeltiden till intern deltatid */
sts = lib$cvtf_to_internal_time(&time_function_code,
&remnode->objp->CycleTime,
&timeout_cycle);
if ( ODD(sts) ){
/* Set timeout for response character from receiver */
sts = lib$cvtf_to_internal_time(&time_function_code,
&max_acknowledge_delay,
&timeout_ack);
}
if ( ODD(sts) ){
/* Set timeout for max delay between receive of two characters */
sts = lib$cvtf_to_internal_time(&time_function_code,
&max_char_delay,
&timeout_char);
}
return(sts);
}
/************************************************************************
**************************************************************************
*
* Namn : InitNet
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Assigns and sets up device
*
**************************************************************************
**************************************************************************/
static unsigned int InitNet(void)
{
unsigned int i, sts;
char ch = '\0';
char namestring[80];
char portname[100];
PORT DDA_destination_port;
struct dsc$descriptor_s dataportname;
for ( i=0 ; ( ch != ':' )&&( i < 80 ) ; i++ )
{
namestring[i] = ch = remnode->objp->NodeName[i];
}
namestring[--i] = '\0';
sprintf(portname, "%s$ACCESS", namestring);
dataportname.dsc$a_pointer = portname;
dataportname.dsc$w_length = strlen(portname);
dataportname.dsc$b_class = DSC$K_CLASS_S;
dataportname.dsc$b_dtype = DSC$K_DTYPE_T;
/* Associate portnamne with serial line port ID */
ker$translate_name(&sts, &DDA_destination_port, &dataportname, NAME$LOCAL);
if ( ODD(sts) )
/* Create a new port object */
ker$create_port(&sts, &virtual_serial_line_port, NULL);
if ( ODD(sts) )
/* Connect the port object to the destination_port */
ker$connect_circuit(&sts,
&virtual_serial_line_port,
&DDA_destination_port,
NULL, NULL, NULL, NULL);
return(sts);
}
/*************************************************************************
**************************************************************************
*
* Namn : send_pollbuff
*
* Typ : void
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends a poll or IO update message to Remote node
*
**************************************************************************
**************************************************************************/
void send_pollbuff(remnode_item *remnode, pssupd_buffer *buf)
{
unsigned int sts, buf_size;
pssupd_buffer_vnet *vnet_buf = buf;
/* Fill in remaining data in poll telegram */
AsciiToR50("PSSUPD", &vnet_buf->receive_task);
vnet_buf->common_name[0] = remnode->objp->Address[0];
vnet_buf->common_name[1] = remnode->objp->Address[1];
buf_size = vnet_buf->length * 2; /* Convert to bytes */
sts = send_it((char*)vnet_buf, buf_size);
return;
}
/*************************************************************************
**************************************************************************
*
* Namn : remnode_send
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends a RemTrans message to Remote node
*
**************************************************************************
**************************************************************************/
static unsigned int remnode_send(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buffer_size)
{
unsigned int sts;
sts = send_it(buf, buffer_size);
return sts;
}
/*************************************************************************
**************************************************************************
*
* Namn : send_it
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Executes the sending of a message according to 3964r.
*
**************************************************************************
**************************************************************************/
static unsigned int send_it(char *buf, int buf_size)
{
unsigned int sts, i;
unsigned int size_of_telegram;
unsigned int number_of_DLE = 0;
unsigned int nbr_of_bytes_written = 0;
unsigned int nbr_of_bytes_read = 0;
unsigned char ch;
unsigned char BCC = DLE ^ ETX;
unsigned char received_char = '\0';
unsigned char *restore_buf_ptr = buf;
unsigned char telegram[MAX_SIZE_TELEGRAM];
static unsigned char sstx[2] = {STX, '\0'};
static unsigned char sdle[2] = {DLE, '\0'};
static unsigned char snak[2] = {NAK, '\0'};
/*************************************************************************/
/** Count DLE characters and calculate the size of the telegram. **/
/*************************************************************************/
for ( i=0 ; i<buf_size ; i++ )
{
if ( *buf++ == DLE )
number_of_DLE += 1;
}
size_of_telegram = buf_size + number_of_DLE + NUMBER_OF_STOP_CHAR;
/*************************************************************************/
/** Fill up telegram with contents of message and calculate BCC **/
/*************************************************************************/
buf = restore_buf_ptr;
for ( i=0 ; i<(buf_size + number_of_DLE) ; i++ )
{
ch = telegram[i] = *buf++;
BCC ^= ch;
if ( ch == DLE ){
telegram[++i] = DLE;
BCC ^= ch;
}
}
telegram[i++] = DLE;
telegram[i++] = ETX;
telegram[i] = BCC;
/*************************************************************************/
/** Execute the send procedure **/
/*************************************************************************/
/* Send STX and wait for answer */
eln$tty_write(&sts, &virtual_serial_line_port, 1, &sstx,
&nbr_of_bytes_written, NULL, NULL);
if ( ODD(sts) ){
/* wait for character or timeout */
eln$tty_read(&sts, &virtual_serial_line_port, 1, &received_char,
&nbr_of_bytes_read, 2, NULL, &timeout_ack,
NULL, NULL, NULL, NULL);
}
if ( EVEN(sts) || (received_char != DLE) || (sts == ELN$_TIMEOUT) ){
/* Try one more time to establish contact */
eln$tty_write(&sts, &virtual_serial_line_port, 1, &sstx,
&nbr_of_bytes_written, NULL, NULL);
if ( ODD(sts) ){
/* wait for character or timeout */
eln$tty_read(&sts, &virtual_serial_line_port, 1, &received_char,
&nbr_of_bytes_read, 2, NULL, &timeout_ack,
NULL, NULL, NULL, NULL);
}
if ( EVEN(sts) || (received_char != DLE) || (sts == ELN$_TIMEOUT) )
sts = FALSE;
}
if ( ODD(sts) ){
/* Contact is established. Send telegram */
eln$tty_write(&sts, &virtual_serial_line_port, size_of_telegram,
&telegram,
&nbr_of_bytes_written, NULL, NULL);
if ( ODD(sts) ){
/* wait for character or timeout */
eln$tty_read(&sts, &virtual_serial_line_port, 1, &received_char,
&nbr_of_bytes_read, 2, NULL, &timeout_ack,
NULL, NULL, NULL, NULL);
}
if ( EVEN(sts) || (received_char != DLE) || (sts == ELN$_TIMEOUT) )
sts = FALSE;
}
/*************************************************************************/
/** Check final status. **/
/*************************************************************************/
if ( EVEN(sts) ){
/* The send procedure has failed */
eln$tty_write(NULL, &virtual_serial_line_port, 1, &snak,
&nbr_of_bytes_written, NULL, NULL);
errh_CErrLog(REM__SNDFAIL3964R);
}
return(sts);
}
/*************************************************************************
**************************************************************************
*
* Namn : Receive
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Waits for STX on serial line
*
**************************************************************************
**************************************************************************/
static unsigned int Receive()
{
static int sts;
static int nbr_of_bytes_read = 0;
static int nbr_of_bytes_written = 0;
unsigned char received_char = NUL;
static unsigned char snak[2] = {NAK, NUL};
static int opt=2;
static DDA$BREAK_MASK code={0,0,0,0,0,0,0,0};
static DDA$_EXTENDED_STATUS_INFO stsblk;
static int error_logged = 0;
eln$tty_read(&sts, &virtual_serial_line_port, 1,
&received_char, &nbr_of_bytes_read, opt, NULL,
&timeout_cycle, 1, stsblk, NULL, NULL);
if (sts == ELN$_SUCCESS){
if ( error_logged) {
errh_CErrLog(REM__RCVSUCC3964R);
error_logged = 0;
}
if (received_char == STX){
sts = ReceiveHandler();
}
else {
/* We don't understand, Send NAK unless NAK is received */
if (received_char != NAK)
eln$tty_write(NULL, &virtual_serial_line_port, 1, &snak,
&nbr_of_bytes_written, NULL, NULL);
}
}
else if (sts != ELN$_TIMEOUT){
/* Wait a full cycle time to avoid loop */
if ( !error_logged) {
errh_CErrLog(REM__RCVFAIL3964R);
error_logged = 1;
}
remnode->objp->ErrTransCount++;
eln$tty_write(NULL, &virtual_serial_line_port, 1, &snak,
&nbr_of_bytes_written, NULL, NULL);
ker$wait_any(NULL, NULL, &timeout_cycle);
}
return(1);
}
/*************************************************************************
**************************************************************************
*
* Namn : ReceiveHandler
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Invoked when a telegram is received.
*
**************************************************************************
**************************************************************************/
static unsigned int ReceiveHandler()
{
unsigned int sts, i;
unsigned int nbr_of_bytes_written = 0;
unsigned int nbr_of_bytes_read = 0;
unsigned int data_size = 0;
unsigned int common_offset = 0;
unsigned int length = 0;
char search_remtrans = FALSE;
char terminate = FALSE;
char name[7];
unsigned char BCC = '\0';
unsigned char char_buffer, BCC_checksum;
unsigned char received_char = '\0';
unsigned char ReceiveBuffer[MAX_SIZE_TELEGRAM];
unsigned char *ReceiveBuffer_ptr;
unsigned char sstx[2] = {STX, '\0'};
unsigned char sdle[2] = {DLE, '\0'};
unsigned char snak[2] = {NAK, '\0'};
remtrans_item *remtrans;
/*************************************************************************/
/** We have received STX earlier, send DLE to responde **/
/*************************************************************************/
eln$tty_write(&sts, &virtual_serial_line_port, 1, &sdle,
&nbr_of_bytes_written, NULL, NULL);
if ( EVEN(sts) )
return(FALSE);
/*************************************************************************/
/** Store the received telegram temporary **/
/*************************************************************************/
eln$tty_read(&sts, &virtual_serial_line_port, 1, &received_char,
&nbr_of_bytes_read, 2, NULL, &timeout_char,
NULL, NULL, NULL, NULL);
if ( EVEN(sts) || (sts == ELN$_TIMEOUT) )
return(FALSE);
ReceiveBuffer[0] = char_buffer = received_char;
BCC ^= received_char;
for ( i=1 ; (terminate==FALSE)&&(i<MAX_SIZE_TELEGRAM) ; i++ )
{
eln$tty_read(&sts, &virtual_serial_line_port, 1, &received_char,
&nbr_of_bytes_read, 2, NULL, &timeout_char,
NULL, NULL, NULL, NULL);
if ( EVEN(sts) || (sts == ELN$_TIMEOUT) )
return(FALSE);
if ( (char_buffer == DLE) && (received_char == ETX) ){
/* End of message. Read checksum and terminate. */
ReceiveBuffer[i] = received_char;
BCC ^= received_char;
eln$tty_read(&sts, &virtual_serial_line_port, 1, &received_char,
&nbr_of_bytes_read, 2, NULL, &timeout_char,
NULL, NULL, NULL, NULL);
if ( EVEN(sts) || (sts == ELN$_TIMEOUT) )
return(FALSE);
BCC_checksum = received_char;
terminate = TRUE;
}
else{
/* Store one more received character in the buffer */
BCC ^= received_char;
if ( (received_char != DLE) ||
((received_char == DLE) && (char_buffer != DLE)) ){
ReceiveBuffer[i] = char_buffer = received_char;
}
else{
/* This is a duplicated DLE character. Throw away. */
i--;
char_buffer = '\0';
}
}
} /* endfor */
/*************************************************************************/
/** A complete message is received. Check BCC. **/
/*************************************************************************/
if ( BCC == BCC_checksum ){
eln$tty_write(&sts, &virtual_serial_line_port, 1, &sdle,
&nbr_of_bytes_written, NULL, NULL);
if ( EVEN(sts) )
return(FALSE);
}
else{
/* Checksum in this telegram is wrong */
return(FALSE);
}
/*************************************************************************/
/** Find out if the received message is a array of io updates. **/
/** Treat the message and exit. **/
/*************************************************************************/
{
io_buffer_vnet *io_buf = (io_buffer_vnet *) &ReceiveBuffer;
if ( io_buf->io_name[0] == remnode->objp->Address[0] &&
io_buf->io_name[1] == remnode->objp->Address[1] ){
data_size = io_buf->length * 2; /* Converted to bytes */
sts = RemIO_Receive_3964R(remnode,
&io_buf->data,
data_size-NET_HEADER_SIZE_IO);
return(sts);
}
}
/*************************************************************************/
/** Find out if the received message is a array of common data **/
/** Search for the RemTrans object that is the target. **/
/*************************************************************************/
{
char type_name[4];
common_buffer_vnet *c_buf = (common_buffer_vnet *) &ReceiveBuffer;
R50ToAscii(&c_buf->common_name, &name);
for ( i=0 ; i<4 ; i++ )
{
type_name[i] = name[i+3];
}
if ( (strncmp(type_name, "COM", 3)) == 0 ){
search_remtrans = true;
remtrans = remnode->remtrans;
while(remtrans && search_remtrans)
{
if ( remtrans->objp->Address[0] == c_buf->common_name[0] &&
remtrans->objp->Address[1] == c_buf->common_name[1] )
search_remtrans = false;
if ( search_remtrans )
remtrans = (remtrans_item *) remtrans->next;
} /* endwhile */
/*************************************************************************/
/** Treat the common data update message and exit. **/
/*************************************************************************/
if ( !search_remtrans ){
data_size = c_buf->length * 2; /* Converted to bytes */
common_offset = c_buf->offset;
if ( data_size > remtrans->objp->MaxLength ){
remtrans->objp->ErrCount++;
remtrans->objp->LastSts = STATUS_LENGTH;
return(FALSE);
}
else{
memcpy(&remtrans->datap[common_offset], c_buf, data_size);
clock_gettime( CLOCK_REALTIME, &remtrans->objp->TransTime);
remtrans->objp->TransCount++;
remtrans->objp->DataValid = TRUE;
remtrans->objp->LastSts = STATUS_OK;
remtrans->objp->DataLength = data_size;
}
return(TRUE);
}
}
else{
/*************************************************************************/
/** This message contains a ordinary remtrans **/
/** Search for the RemTrans object that is the target. **/
/*************************************************************************/
search_remtrans = true;
remtrans = remnode->remtrans;
while(remtrans && search_remtrans)
{
if ( remtrans->objp->Address[0] == c_buf->common_name[0] &&
remtrans->objp->Address[1] == c_buf->common_name[1] )
search_remtrans = false;
if ( search_remtrans )
remtrans = (remtrans_item *) remtrans->next;
} /* endwhile */
/*************************************************************************/
/** Treat the remtrans message and exit. **/
/*************************************************************************/
if ( !search_remtrans ){
data_size = c_buf->length * 2; /* Converted to bytes */
sts = RemTrans_Receive(remtrans,
&ReceiveBuffer,
data_size);
if ( EVEN(sts) ){
remtrans->objp->ErrCount++;
return (FALSE);
}
}
}
if (search_remtrans){
/* No corresponding RemTrans object found */
remnode->objp->ErrTransCount++;
return (FALSE);
}
}
return (TRUE);
}
#ifdef OS_ELN
/*************************************************************************
**************************************************************************
*
* Namn : WaitFor_PLC_Change
*
* Typ : int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Subprocess waits for message from REMOTEHANDLER on job_port,
* that will kill transport when switch is done.
*
**************************************************************************
**************************************************************************/
int WaitFor_PLC_Change()
{
pwr_tStatus sts;
MESSAGE msg_id;
char *mess;
int size;
while (TRUE) {
ker$wait_any(&sts, NULL, NULL, &job_port);
ker$receive(&sts, &msg_id, &mess, &size, &job_port, NULL, NULL);
if (*mess == 1){
/* Hot switch init. Do nothing but delete the message */
ker$delete(&sts, msg_id);
}
else if (*mess == 2){
/* Switch is done. Execute harakiri! */
ker$delete(&sts, msg_id); /* Delete message */
exith();
ker$delete(&sts, my_proc);
}
else {
printf("Fel telegram PLC-byte %%x%x\n",*mess);
ker$delete(&sts, msg_id);
}
}
}
#endif
/*
* Main routine
*/
main(int argc, char *argv[])
{
unsigned int sts, i; /* Status from function calls etc. */
pwr_tObjid pwr_node; /* Own Pwr node */
pwr_sClass_PlcProcess *pwr_nodep; /* Ref to own Pwr node */
pwr_tTime OriginChgTime; /* LastChgTime at start */
pwr_tClassId remnode_class; /* Vr remnod's class */
char first; /* Send Hello first time */
pssupd_buffer_vnet buff; /* Buffer for 'Hello' */
pssupd_order_header *header; /* Header for Hello */
#ifdef OS_ELN
PROCESS id_p;
static struct dsc$descriptor_s name_desc = {0, DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
NAME name_id;
/* Get process-id to be able to kill myself.
Create subprocess to kill or to signal switch. */
ker$job_port(&sts, &job_port);
ker$current_process(&sts, &my_proc);
/* Create a name for my own process (first process in job) */
name_desc.dsc$a_pointer = argv[3];
name_desc.dsc$w_length = strlen(argv[3]);
ker$create_name(&sts, &name_id, &name_desc, my_proc, NULL);
ker$create_process( &sts, &id_p, WaitFor_PLC_Change,NULL);
#endif
DeclareExitHandler();
sts = gdh_Init("rs_remote_3964r_vnet");
if (EVEN(sts)) exit(sts);
/* Hmta remnodens objid frn argumentvektorn */
if (argc >= 3)
{
sts = cdh_StringToObjid( argv[2], &remnode->objid);
if (EVEN(sts)) exit(sts);
}
else
remnode->objid = pwr_cNObjid;
/* Kontrollera att objektet verkligen r en remnod */
sts = gdh_GetObjectClass(remnode->objid, &remnode_class);
if (EVEN(sts)) exit(sts);
if (remnode_class != pwr_cClass_RemNode) exit(0);
/* Hmta en pekare till remnoden */
sts = gdh_ObjidToPointer(remnode->objid, (pwr_tAddress *) &remnode->objp);
if (EVEN(sts)) exit(sts);
/* Kontrollera att det r rtt transport */
if (remnode->objp->TransportType != REMNODE_TRANSPORT_3964R_VNET) exit(0);
/* Get pointer to $Node-object */
sts = gdh_GetClassList( pwr_cClass_PlcProcess, &pwr_node);
sts = gdh_ObjidToPointer(pwr_node, (pwr_tAddress *) &pwr_nodep);
/* Initialize remtrans objects */
sts = RemTrans_Init(remnode, 0);
if (EVEN(sts)) exit(sts);
/* Initialize remote I/O */
sts = RemIO_Init(remnode);
if (EVEN(sts)) exit(sts);
/* Initialize device */
sts = InitNet();
if (EVEN(sts)) exit(sts);
/* Initialize timers */
sts = InitTimers();
if (EVEN(sts)) exit(sts);
remnode->Time_since_poll = 0;
remnode->Time_since_IO = 0;
remnode->Time_since_send = 0;
/* Loop forever */
first = TRUE;
while (!doomsday)
{
sts = Receive();
/* Om LastChgTime r ndrad (PLC-programbyte), avsluta */
/*
if (memcmp(&OriginChgTime, &pwr_nodep->LastChgTime,
sizeof(pwr_tTime)) != 0)
exit(0);
*/
if (first && remnode->objp->Poll) {
/* Send Hello to subsystem if we have poll */
header = &buff.data;
header->type = PSS_Switch_Done;
header->size = 0;
header->signal = 0;
buff.no_of_updates = 1;
buff.length = (sizeof(pssupd_buffer_vnet) -
MAX_ORDER_BUFFERSIZE_VNET + sizeof(pssupd_order_header) + 1) / 2;
send_pollbuff(remnode, &buff);
}
remnode->Time_since_poll += remnode->objp->CycleTime;
remnode->Time_since_IO += remnode->objp->CycleTime;
remnode->Time_since_send += remnode->objp->CycleTime;
sts = RemTrans_Cyclic(remnode, &remnode_send);
if (((!remnode->objp->IOStallFlag || EVEN(remnode->objp->IOStallAction)) &&
(remnode->Time_since_poll >= remnode->objp->IOCycleTime)) ||
(remnode->objp->IOStallFlag && ODD(remnode->objp->IOStallAction) &&
(remnode->Time_since_poll >= remnode->objp->ErrTime) &&
(remnode->Time_since_poll >= remnode->objp->IOCycleTime)))
{
sts = RemIO_Cyclic_3964R(remnode, &send_pollbuff);
remnode->Time_since_poll = 0.0;
}
if ((remnode->Time_since_IO >= remnode->objp->IOStallTime) &&
(remnode->objp->IOStallTime > 0))
sts = RemIO_Stall(remnode);
first = FALSE;
}
}
include $(pwre_dir_symbols)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(hw_name)/$(type_name)_generic.mk
ifeq ($($(type_name)_generic_mk),)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(type_name)_generic.mk
endif
ifeq ($($(type_name)_generic_mk),)
include $(pwre_kroot)/tools/bld/src/$(type_name)_generic.mk
endif
ifndef link_rule_mk
link_rule_mk := 1
link = $(ldxx) $(elinkflags) $(domap) -o $(export_exe) \
$(export_obj) $(objects) $(rt_msg_eobjs) \
-lpwr_remote -lpwr_rt -lpwr_co -lpwr_msg_dummy -lpthread -lrt -lm
endif
/*
* Proview $Id: rs_remote_alcm.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*************************************************************************
* ===============
* P r o v i e w
* ===============
**************************************************************************
*
* Filename: rs_remote_alcm.c
*
* Date Pgm. Read. Remark
* Modified 010102 CJ Frsta version fr Lynx/linux
* 030227 CJ Remote I/O infrt
* 040504 CJ v4.0.0
*
* Description: Remote transport ALCM fr plattformarna Lynx och Linux.
* ALCM r ett lgniv ethernetprotokoll. P Linux anvnds
* en "raw ethernet socket" fr att hantera ethernetpaket
* med protokoll-id 60-06 som r DEC's gamla "owner protocol"
*
**************************************************************************
**************************************************************************/
#include "rt_gdh.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/sockios.h>
#include <linux/if.h>
#include <fcntl.h>
#include <netinet/in.h>
#include "rt_errh.h"
#include "rt_pwr_msg.h"
#include "rt_aproc.h"
#include "pwr_class.h"
#include "pwr_systemclasses.h"
#include "pwr_baseclasses.h"
#include "pwr_remoteclasses.h"
#include "remote.h"
#include "remote_utils.h"
#include "remote_remtrans_utils.h"
#include "remote_remio_utils.h"
#include "rs_remote_alcm.h"
#define TIME_INCR 0.02
typedef struct {
pwr_sClass_RemnodeALCM *ref;
unsigned char address[6];
float time_since_scan;
float time_since_rcv;
float time_since_poll;
float time_since_io;
} remnode_alcm;
remnode_item *rnl = NULL; // Lista med remnoder
int my_socket; // Egen socket
unsigned char my_mac_address[6]; // Egen nods MAC-adress
typedef struct {
unsigned char dst[6];
unsigned char src[6];
unsigned short type;
unsigned short size;
} eth_header;
typedef struct {
unsigned char type;
unsigned char seqnum;
unsigned char filler[46];
} alcm_header;
/*************************************************************************
**************************************************************************
*
* Namn : RemoteSleep
*
* Beskrivning : Vntar angiven tid (sekunder)
*
**************************************************************************
**************************************************************************/
void RemoteSleep(float seconds)
{
struct timespec rqtp, rmtp;
rqtp.tv_sec = (int) seconds;
rqtp.tv_nsec = (seconds - (float) rqtp.tv_sec) * 1000000000;
nanosleep(&rqtp, &rmtp);
return;
}
/*************************************************************************
**************************************************************************
*
* Namn : CalcAddress
*
* Beskrivning : Berknar ethernetadress frn DECnet-area och -nod
*
**************************************************************************
**************************************************************************/
int CalcAddress(unsigned char *str, unsigned char *address)
{
int i1, i2, i3, i4, i5, i6;
unsigned short int node, area;
if (strchr(str, '.')) {
sscanf(str, "%d.%d", &i1, &i2);
area = (unsigned short int) i1;
node = (unsigned short int) i2;
if (area > 64 || node > 1024) return(-1);
address[0] = 0xAA;
address[1] = 0x00;
address[2] = 0x04;
address[3] = 0x00;
node = node | (area << 10);
address[4] = (unsigned char) (node & 255);
address[5] = (unsigned char) (node >> 8);
return 1;
}
else if (strchr(str, ':')) {
sscanf(str, "%x:%x:%x:%x:%x:%x", &i1, &i2, &i3, &i4, &i5, &i6);
address[0] = (unsigned char) i1;
address[1] = (unsigned char) i2;
address[2] = (unsigned char) i3;
address[3] = (unsigned char) i4;
address[4] = (unsigned char) i5;
address[5] = (unsigned char) i6;
return 1;
}
else {
return -1;
}
}
/*************************************************************************
**************************************************************************
*
* Namn : InitNet
*
* Beskrivning : Skapar raw socket och gr bind till interfacet
*
**************************************************************************
**************************************************************************/
void InitNet()
{
struct ifreq ifr;
struct sockaddr_ll my_addr;
// Skapa en raw ethernet socket
my_socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_CUST));
if (my_socket < 0) {
errh_Error("Error in socket()");
exit(0);
}
// Stt noblock
fcntl(my_socket, F_SETFL, O_NONBLOCK);
// Ls egen nods MAC-adress frn interfacet (eth0)
strcpy(ifr.ifr_name, "eth0");
ioctl(my_socket, SIOCGIFHWADDR, &ifr);
memcpy(&my_mac_address, &ifr.ifr_hwaddr.sa_data, 6);
// Hmta interface-index gr bind
ioctl(my_socket, SIOCGIFINDEX, &ifr);
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sll_family = AF_PACKET;
my_addr.sll_protocol = htons(ETH_P_CUST);
my_addr.sll_ifindex = ifr.ifr_ifindex;
bind(my_socket, (struct sockaddr *) &my_addr, sizeof(my_addr));
return;
}
/*************************************************************************
**************************************************************************
*
* Namn : SendAck
*
* Beskrivning : Skickar ack-meddelande till remote-nod
*
**************************************************************************
**************************************************************************/
unsigned int SendAck(remnode_item *remnode, unsigned char seqnum)
{
struct {
eth_header eh;
alcm_header ah;
} snd;
remnode_alcm *local = (remnode_alcm *) remnode->local;
memcpy(&snd.eh.dst, &local->address, sizeof(snd.eh.dst));
memcpy(&snd.eh.src, &my_mac_address, sizeof(snd.eh.src));
snd.eh.type = htons(ETH_P_CUST);
snd.eh.size = sizeof(alcm_header);
snd.ah.type = ALCM_MTYP_RESP;
snd.ah.seqnum = seqnum;
write(my_socket, &snd, sizeof(snd));
return(1);
}
/*************************************************************************
**************************************************************************
*
* Namn : SendPoll
*
* Beskrivning : Skickar poll eller IO-uppdatering till remote-noderna
*
**************************************************************************
**************************************************************************/
static void SendPoll(remnode_item *remnode, pssupd_buffer *buf)
{
char common_name[] = " PSS";
struct {
eth_header eh;
alcm_header ah;
apl_buffer apl;
} snd;
remnode_alcm *local = (remnode_alcm *) remnode->local;
memcpy(&snd.eh.dst, &local->address, sizeof(snd.eh.dst));
memcpy(&snd.eh.src, &my_mac_address, sizeof(snd.eh.src));
snd.eh.type = htons(ETH_P_CUST);
snd.eh.size = sizeof(alcm_header) + buf->length;
snd.ah.type = ALCM_MTYP_DATA;
snd.ah.seqnum = 0;
RemUtils_AsciiToR50("PSSUPD", buf->receive_task);
memcpy(&common_name, &local->ref->RemoteHostname, 3);
RemUtils_AsciiToR50(common_name, buf->common_name);
buf->transcode = ALCM_TRACO_APLNAK;
memcpy(&snd.apl, buf, buf->length);
if (write(my_socket, &snd, sizeof(eth_header)+sizeof(alcm_header)+buf->length) < 0) {
errh_Error("Send failure");
local->ref->ErrCount++;
}
return;
}
/*************************************************************************
**************************************************************************
*
* Namn : SendAppl
*
* Beskrivning : Skickar applikationstransen som beskrivs av remtransen
*
**************************************************************************
**************************************************************************/
unsigned int SendAppl(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buf_size)
{
static unsigned char message_counter = 0;
struct {
eth_header eh;
alcm_header ah;
apl_buffer apl;
} snd;
csp_buffer *c_buf;
remnode_alcm *local = (remnode_alcm *) remnode->local;
if (message_counter++ >= 255) message_counter = 1;
memcpy(&snd.eh.dst, &local->address, sizeof(snd.eh.dst));
memcpy(&snd.eh.src, &my_mac_address, sizeof(snd.eh.src));
snd.eh.type = htons(ETH_P_CUST);
snd.eh.size = sizeof(alcm_header) + buf_size;
snd.ah.type = ALCM_MTYP_DATA;
snd.ah.seqnum = message_counter;
memcpy(&snd.apl, buf, buf_size);
c_buf = (csp_buffer *) &snd.apl;
if (snd.apl.trans_code == ALCM_TRACO_APLACK ||
snd.apl.trans_code == ALCM_TRACO_APLNAK ||
snd.apl.trans_code == ALCM_TRACO_CSPNAK ||
snd.apl.trans_code == ALCM_TRACO_COFNAK)
{
if (snd.apl.trans_code == ALCM_TRACO_APLACK ||
snd.apl.trans_code == ALCM_TRACO_APLNAK) {
RemUtils_AsciiToR50(remtrans->TransName, snd.apl.receive_task);
// Lgg tillbaka headern till buf s folk ser vad vi pillat p!
memcpy(buf, &snd.apl, 10);
}
else {
RemUtils_AsciiToR50(remtrans->TransName, c_buf->common_name);
}
if (write(my_socket, &snd, sizeof(eth_header)+sizeof(alcm_header)+buf_size) < 0)
{
errh_Error("Send failure");
return(-1);
}
if (snd.apl.trans_code == ALCM_TRACO_APLACK)
return(STATUS_BUFACK);
else
return(1);
}
else
return(-1);
}
/*************************************************************************
**************************************************************************
*
* Namn : Receive
*
* Beskrivning : Tar emot ethernetpaket frn interfacet
*
**************************************************************************
**************************************************************************/
unsigned short int Receive()
{
remnode_item *remnode;
unsigned char search_remnode = TRUE;
remtrans_item *remtrans;
unsigned char search_remtrans = TRUE;
unsigned char send_response = FALSE;
int msg_size;
unsigned int sts;
char name[7];
unsigned int apl_size;
unsigned char reject;
int loop_count;
remtrans_item *transp;
struct {
eth_header eh;
alcm_header ah;
apl_buffer apl;
} rcv;
csp_buffer *csp; // Fr speglad commonarea
int common_offset, common_length;
reject = true;
loop_count = 0;
remnode_alcm *local;
// Avvisa multicast- och broadcastpaket
while (reject) {
msg_size = read(my_socket, &rcv, sizeof(rcv));
if (msg_size < 0) {
return(1);
}
if (rcv.eh.dst[0] & 1) {
reject = true;
}
else {
reject = false;
}
if (loop_count++ > 100) return(1);
}
remnode = rnl;
search_remnode = TRUE;
while (remnode && search_remnode)
{
local = (remnode_alcm *) remnode->local;
if (memcmp(rcv.eh.src, local->address, 6) == 0)
search_remnode = FALSE;
else
remnode = (remnode_item *) remnode->next;
}
if (search_remnode)
{
if (rcv.eh.dst[0] != 0xAB)
errh_Info("Message from unknown source %02x-%02x-%02x-%02x-%02x-%02x",
rcv.eh.src[0], rcv.eh.src[1], rcv.eh.src[2],
rcv.eh.src[3], rcv.eh.src[4], rcv.eh.src[5]);
}
else
{
if (rcv.ah.type == ALCM_MTYP_DATA && !local->ref->Disable)
{
apl_size = msg_size-sizeof(eth_header)-sizeof(alcm_header);
// Applikationstrans
if (rcv.apl.trans_code == ALCM_TRACO_APLACK ||
rcv.apl.trans_code == ALCM_TRACO_APLNAK)
{
RemUtils_R50ToAscii( (unsigned short *) &rcv.apl.receive_task, name);
name[6] = '\0';
search_remtrans = TRUE;
remtrans = remnode->remtrans;
while(remtrans && search_remtrans)
{
if ((strncmp(name, remtrans->objp->TransName, 6) == 0) &&
remtrans->objp->Direction == REMTRANS_IN)
{
search_remtrans = FALSE;
sts = RemTrans_Receive(remtrans, (char *) &rcv.apl, apl_size);
if ((rcv.apl.trans_code == ALCM_TRACO_APLACK) && ODD(sts))
send_response = TRUE;
break;
}
remtrans = (remtrans_item *) remtrans->next;
}
if (search_remtrans) {
local->ref->ErrCount++;
errh_Info("Unknown message %s from %s", name,
((remnode_alcm *) (remnode->local))->ref->RemoteHostname);
}
else {
// Skicka alltid kvittens p DUMMY0 (om APLACK)
if (strncmp(name, "DUMMY0", 6) == 0 && rcv.apl.trans_code == ALCM_TRACO_APLACK)
send_response = TRUE;
}
}
// Spegling av common-area. Behandlas i princip som en remtrans
// Tyvrr lite special eftersom det finns mjlighet att spegla med offset
else if (rcv.apl.trans_code == ALCM_TRACO_CSPACK ||
rcv.apl.trans_code == ALCM_TRACO_CSPNAK ||
rcv.apl.trans_code == ALCM_TRACO_COFACK ||
rcv.apl.trans_code == ALCM_TRACO_COFNAK) {
csp = (csp_buffer *) &rcv.apl;
RemUtils_R50ToAscii((unsigned short *)csp->common_name, name);
name[6] = '\0';
if (csp->trans_code == ALCM_TRACO_COFACK ||
csp->trans_code == ALCM_TRACO_COFNAK)
common_offset = csp->offset;
else
common_offset = 0;
search_remtrans = true;
remtrans = remnode->remtrans;
while(remtrans && search_remtrans)
{
if ((strncmp(name, remtrans->objp->TransName, 6) == 0) &&
remtrans->objp->Direction == REMTRANS_IN)
{
search_remtrans = false;
common_length = msg_size-sizeof(eth_header)-sizeof(alcm_header)+common_offset;
if (common_length > remtrans->objp->MaxLength)
{
remtrans->objp->ErrCount++;
remtrans->objp->LastSts = STATUS_LENGTH;
}
else
{
memcpy(&remtrans->datap[common_offset], csp,
msg_size-sizeof(eth_header)-sizeof(alcm_header));
clock_gettime( CLOCK_REALTIME, &remtrans->objp->TransTime);
remtrans->objp->TransCount++;
remtrans->objp->DataValid = TRUE;
remtrans->objp->LastSts = STATUS_OK;
if (common_length > remtrans->objp->DataLength)
remtrans->objp->DataLength = common_length;
if (csp->trans_code == ALCM_TRACO_CSPACK ||
csp->trans_code == ALCM_TRACO_COFACK) send_response = TRUE;
}
}
remtrans = (remtrans_item *) remtrans->next;
}
if (search_remtrans) {
local->ref->ErrCount++;
errh_Info("Unknown message %s from %s", name,
((remnode_alcm *) (remnode->local))->ref->RemoteHostname);
}
}
// I/O-spegling
else if (rcv.apl.trans_code == ALCM_TRACO_BSPACK || rcv.apl.trans_code == ALCM_TRACO_BSPNAK) {
sts = RemIO_Receive_ALCM(remnode, (bsp_buffer *) &rcv.apl, apl_size);
local->time_since_io = 0;
if (rcv.apl.trans_code == ALCM_TRACO_BSPACK) send_response = TRUE;
}
}
else if (rcv.ah.type == ALCM_MTYP_RESP)
{
// Applikationskvittens
rem_t_transbuff *transbuff;
transbuff = remnode->transbuff;
if (transbuff)
{
transp = (remtrans_item *) transbuff->remtrans;
remnode->transbuff = (rem_t_transbuff *) transbuff->next;
transp->objp->Buffers--;
free(transbuff);
}
send_response = FALSE; // Skicka ingen kvittens
}
else if (rcv.ah.type == ALCM_MTYP_INIT && !local->ref->Disable)
{
send_response = TRUE; // Svara alltid init-meddelande med kvittens
}
if (send_response) {
sts = SendAck(remnode, rcv.ah.seqnum);
}
if (local->ref->LinkUp != 1) {
local->ref->LinkUp = 1;
errh_Error("ALCM link up to node %s", local->ref->RemoteHostname, 0);
}
local->time_since_rcv = 0.0;
}
return(1);
}
/*************************************************************************
**************************************************************************
*
* Main
*
**************************************************************************
**************************************************************************/
int main(int argc, char *argv[]) {
remnode_item *rn = NULL;
remnode_alcm *rn_local = NULL;
remtrans_item *remtrans;
pwr_tObjid objid; // Fr loop
unsigned int sts; // Status frn funktionsanrop
unsigned char pname[32];
pwr_tTime tmptime;
int i;
// Build process name
sprintf(pname, "rs_remalcm");
// Init of errh
errh_Init(pname, errh_eAnix_remote);
errh_SetStatus(PWR__SRVSTARTUP);
// Init of gdh
sts = gdh_Init(pname);
if ( EVEN(sts)) {
errh_Error("gdh_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
// Leta reda p samtliga RemnodeALCM objekt, skapa lnkad lista med lokala
sts = gdh_GetClassList(pwr_cClass_RemnodeALCM, &objid);
if ( EVEN(sts)) {
errh_Error("gdh_GetClassList, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
// Loopa ver alla remnoder och skapa en intern lnkad lista
while (ODD(sts))
{
// Allokera lokala datastrukturer
rn = malloc(sizeof(remnode_item));
rn_local = malloc(sizeof(remnode_alcm));
rn->local = rn_local;
if (!rn || !rn_local) {
errh_Error("Malloc");
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
// Lnka in
rn->next = rnl;
rnl = rn;
// Initiera data
sts = gdh_ObjidToPointer(objid, (pwr_tAddress *) &rn_local->ref);
rn->objid = objid;
rn->retransmit_time = rn_local->ref->RetransmitTime;
rn_local->time_since_scan = 0;
rn_local->time_since_rcv = 0;
rn_local->time_since_poll = 0;
rn_local->time_since_io = 0;
sts = RemTrans_Init(rn);
if ( EVEN(sts)) {
errh_Error("RemTrans_Init, %d", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
sts = RemIO_Init_ALCM(rn);
if ( EVEN(sts)) {
errh_Error("RemIO_Init, %d", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
// Berkna ethernet-adress frn adress-strng i objektet
sts = CalcAddress(rn_local->ref->RemoteAddress, rn_local->address);
sts = gdh_GetNextObject(objid, &objid);
}
// Initialize socket
InitNet();
// Set running status
errh_SetStatus(PWR__SRUN);
// Set (re)start time in all remnode objects
clock_gettime(CLOCK_REALTIME, &tmptime);
rn = rnl;
while (rn) {
rn_local = (remnode_alcm *) rn->local;
rn_local->ref->RestartTime = tmptime;
rn = rn->next;
}
/* Store remtrans objects objid in every remnode_alcm object */
rn = rnl;
i = 0;
while (rn) {
rn_local = (remnode_alcm *) rn->local;
remtrans = rn->remtrans;
while(remtrans) {
rn_local->ref->RemTransObjects[i++] = remtrans->objid;
if (i >= (int)(sizeof(rn_local->ref->RemTransObjects)/sizeof(rn_local->ref->RemTransObjects[0])))
break;
remtrans = (remtrans_item *) remtrans->next;
}
rn = rn->next;
}
// Loopa nu fr evigt och vervaka remnoderna
while (!doomsday)
{
/* Timestamp */
aproc_TimeStamp();
RemoteSleep(TIME_INCR);
sts = Receive();
rn = rnl;
while (rn) {
rn_local = (remnode_alcm *) rn->local;
/* Increase time counters in local remnode and prevent big counters */
rn_local->time_since_scan += TIME_INCR;
rn_local->time_since_rcv += TIME_INCR;
rn_local->time_since_poll += TIME_INCR;
rn_local->time_since_io += TIME_INCR;
rn_local->time_since_scan = min(rn_local->time_since_scan, rn_local->ref->ScanTime + 1.0);
rn_local->time_since_rcv = min(rn_local->time_since_rcv, rn_local->ref->LinkTimeout + 1.0);
rn_local->time_since_poll = min(rn_local->time_since_poll, rn_local->ref->IOPollTimeSlow + 1.0);
rn_local->time_since_io = min(rn_local->time_since_io, rn_local->ref->IOStallTime + 1.0);
/* Increase send timer for every remtrans */
remtrans = rn->remtrans;
while(remtrans) {
remtrans->time_since_send += TIME_INCR;
/* Prevent big counter */
remtrans->time_since_send = min(remtrans->time_since_send, rn->retransmit_time + 1.0);
remtrans = (remtrans_item *) remtrans->next;
}
// Berkna ethernet-adress frn objektet
CalcAddress(rn_local->ref->RemoteAddress, rn_local->address);
// Update retransmit time, could have been changed
rn->retransmit_time = rn_local->ref->RetransmitTime;
if (rn_local->ref->IOPoll && !rn_local->ref->Disable) {
// Dags att polla remote I/O ?
if (!rn_local->ref->Disable) {
if (((!rn_local->ref->IOStallFlag || EVEN(rn_local->ref->IOStallAction)) &&
(rn_local->time_since_poll >= rn_local->ref->IOPollTime)) ||
(rn_local->ref->IOStallFlag && ODD(rn_local->ref->IOStallAction) &&
(rn_local->time_since_poll >= rn_local->ref->IOPollTimeSlow) &&
(rn_local->time_since_poll >= rn_local->ref->IOPollTime))) {
sts = RemIO_Cyclic_ALCM(rn, &SendPoll);
rn_local->time_since_poll = 0;
}
}
// Dags fr stall ?
if ((rn_local->time_since_io >= rn_local->ref->IOStallTime) && (rn_local->ref->IOStallTime > 0)) {
sts = RemIO_Stall_ALCM(rn);
}
}
else {
rn_local->ref->IOStallFlag = 0;
rn_local->time_since_poll = 0;
rn_local->time_since_io = 0;
}
// Dags att scanna remtransar ?
if (rn_local->time_since_scan >= rn_local->ref->ScanTime) {
if (!rn_local->ref->Disable) sts = RemTrans_Cyclic(rn, &SendAppl);
rn_local->time_since_scan = 0;
}
// Link up ?
if (rn_local->time_since_rcv >= rn_local->ref->LinkTimeout && rn_local->ref->LinkTimeout > 0) {
if (rn_local->ref->LinkUp != 0) {
rn_local->ref->LinkUp = 0;
errh_Error("ALCM link down to node %s", rn_local->ref->RemoteHostname, 0);
}
}
rn = rn->next;
}
}
}
/*
* Proview $Id: rs_remote_alcm.h,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/***** Meddelandekoder i ethernetheader *****/
#define ALCM_MTYP_DATA 0
#define ALCM_MTYP_RESP 1
#define ALCM_MTYP_INIT 2
/***** Transkoder i applikationsbufferten *****/
#define ALCM_TRACO_CSPACK 1
#define ALCM_TRACO_APLACK 2
#define ALCM_TRACO_CSPNAK 3
#define ALCM_TRACO_APLNAK 4
#define ALCM_TRACO_BSPACK 5
#define ALCM_TRACO_BSPNAK 6
#define ALCM_TRACO_COFACK 7
#define ALCM_TRACO_COFNAK 8
#define NET_HEADER_SIZE 48
/*
* Type definitions
*/
typedef unsigned short int channel_type;
typedef struct
{
unsigned short int completion_status, transfer_size, w3, w4;
} iosb_type;
typedef struct
{
char destination_address[6]; /* Destination address (us) */
char source_address[6]; /* Source address (remnode) */
short int protocol_type; /* Type of protocol (60-06) */
} net_header_type;
typedef struct
{
char msg_type; /* Type of message */
unsigned char msg_seqnum; /* Sequence number */
unsigned char filler[46]; /* Padding */
unsigned short data[725]; /* Data */
} net_buffer_type;
typedef struct
{
short int trans_code;
short int future_use;
short int length;
short int receive_task[2];
unsigned char data[1440];
} apl_buffer;
typedef struct
{
short int trans_code;
short int future_use;
short int length;
short int receive_task[2];
unsigned short int time[7];
} clock_buffer;
typedef struct
{
short int trans_code;
short int common_name[2];
short int offset;
unsigned char data[1442];
} csp_buffer;
/*
* Proview $Id: rs_remote_dmq.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*************************************************************************
*
* Filename: remote_dmq.c
*
* Date Pgm. Read. Remark
* Modified 971016 CJu
*
* Description: Implements remote transport process DMQ
*
**************************************************************************/
#ifdef __DECC
#pragma message disable GLOBALEXT
#endif
/*_Include files_________________________________________________________*/
#include <ssdef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <iodef.h>
#include <descrip.h>
#include <psldef.h>
#include <libdtdef.h>
#include <lib$routines.h>
#include "p_entry.h"
#include "p_proces.h"
#include "p_return.h"
#include "p_symbol.h"
#include "p_typecl.h"
#include "pwr_class.h"
#include "rs_remote_mq.h"
#include "rt_gdh.h"
#include "rt_errh.h"
#include "pwr_baseclasses.h"
#include "pwr_ssabclasses.h"
#include "rs_remote_msg.h"
#include "rs_remote.h"
#include "rs_remtrans_utils.h"
#define CLASS_APL_RESP 101
#define CLASS_RESP 102
mq_uAddress my_queue; /* Queue number */
char receive_buffer[32767]; /* Pointer to received message */
char *receive_msg = (char *) &receive_buffer;
short buffer_size = sizeof(receive_buffer);
char receive_prio = 0; /* Prio for messages */
q_address receive_src; /* group, process received message */
short int receive_class; /* Class of received message */
short int receive_type; /* Type of received message */
short int receive_size; /* Size of received message */
struct PSB receive_psb; /* Status block from PSB */
char receive_force_j = PDEL_DEFAULT_JRN; /* Journal flag */
remnode_item *remnode_list = NULL; /* List of remnodes (internal structure) */
float cycle_time = 1.0; /* Cycle time in seconds */
float min_cycle_time = 0.01; /* Shortest scan time */
int32 timer_id = 1;
/*************************************************************************
**************************************************************************
*
* Namn : exith
*
* Typ : void
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Exit handler that is called before process termination
*
**************************************************************************
**************************************************************************/
void exith(void)
{
int32 sts;
sts = pams_cancel_timer(&timer_id);
sts = pams_exit();
return;
}
/*************************************************************************
**************************************************************************
*
* Namn : DeclareExitHandler
*
* Typ : void
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Declares an exit handler that is called before
* process termination
*
**************************************************************************
**************************************************************************/
void DeclareExitHandler(void)
{
atexit(exith);
}
/*************************************************************************
**************************************************************************
*
* Namn : InitCycleTimer
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sets DMQ scan timer
*
**************************************************************************
**************************************************************************/
unsigned int InitCycleTimer()
{
unsigned int sts;
int32 dmq_sts;
unsigned int time_function_code = LIB$K_DELTA_SECONDS_F;
char format = 'S';
int32 delta_time[2];
int32 tick_count = 0;
/* Konvertera cykeltiden till intern deltatid */
sts = lib$cvtf_to_internal_time(&time_function_code,
&cycle_time,
&delta_time);
if (EVEN(sts)) exit(sts);
dmq_sts = pams_set_timer(&timer_id, &format, &tick_count, (int32 *) &delta_time);
return(sts);
}
/*************************************************************************
**************************************************************************
*
* Namn : WaitEvent
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Waits for Net receive or timer expiration.
*
**************************************************************************
**************************************************************************/
unsigned int WaitEvent(void)
{
int32 dmq_sts;
int32 receive_timeout = 0;
dmq_sts = pams_get_msgw(receive_msg, &receive_prio, &receive_src,
&receive_class, &receive_type, &buffer_size,
&receive_size, &receive_timeout, 0, &receive_psb,
0, 0, 0, 0, 0);
if (ODD(dmq_sts))
{
if (receive_type == MSG_TYPE_TIMER_EXPIRED)
return(RT_TIMEREXP);
else
return(RT_RECEIVE);
}
else
return(dmq_sts);
}
/*************************************************************************
**************************************************************************
*
* Namn : send_pollbuff
*
* Typ : void
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends a poll or IO update message to Remote node
*
**************************************************************************
**************************************************************************/
void send_pollbuff( remnode_item *remnode,
pssupd_buffer *buf)
{
return;
}
/*************************************************************************
**************************************************************************
*
* Namn : remnode_send
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends a message to Remote node
*
**************************************************************************
**************************************************************************/
unsigned int remnode_send(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buf_size)
{
unsigned int sts;
int32 dmq_sts;
char put_prio = 0; /* Prio for messages */
q_address dest;
short class;
short type;
short msg_size;
int32 timeout = 100;
struct PSB put_psb;
char delivery = PDEL_MODE_WF_DQF;
char put_uma = PDEL_UMA_SAF;
dest.au.group = remnode->objp->Address[0];
class = remtrans->Address[0];
type = remtrans->Address[1];
dest.au.queue = remtrans->Address[2];
msg_size = buf_size;
dmq_sts = pams_put_msg(buf,
&put_prio,
&dest,
&class,
&type,
&delivery,
&msg_size,
&timeout,
&put_psb,
&put_uma,
0, 0, 0, 0);
return(dmq_sts);
}
/*************************************************************************
**************************************************************************
*
* Namn : ReceiveComplete
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Invoked when a message is received on the ethernet.
*
**************************************************************************
**************************************************************************/
unsigned int ReceiveComplete()
{
unsigned int sts;
int32 dmq_sts;
char search_remnode = TRUE;
char search_remtrans = TRUE;
char send_response = FALSE;
remnode_item *remnode;
remtrans_item *remtrans;
char *response_buffer; /* Pointer to response message */
int response_prio = 0; /* Prio for response */
short int response_class = CLASS_RESP; /* Class of response */
int response_size = 4; /* Size of response = 4 bytes */
search_remnode = TRUE;
remnode = remnode_list;
while (remnode && search_remnode)
{
if (receive_src.au.group == remnode->objp->Address[0])
search_remnode = FALSE;
else
remnode = (remnode_item *) remnode->next;
}
if (search_remnode)
errh_CErrLog(REM__UNKNOWNSOURCE);
else
{
search_remtrans = true;
remtrans = remnode->remtrans;
while(remtrans && search_remtrans)
{
if (remtrans->objp->Address[0] == receive_class &&
remtrans->objp->Address[1] == receive_type &&
remtrans->objp->Direction == REMTRANS_IN)
{
search_remtrans = false;
sts = RemTrans_Receive(remtrans, receive_buffer, receive_size);
break;
}
remtrans = (remtrans_item *) remtrans->next;
}
if (search_remtrans)
{
remnode->objp->ErrTransCount++;
errh_CErrLog(REM__NOREMTRANS, errh_ErrArgAF(remnode->objp->NodeName));
}
} /* if search_remnode ... */
/* Kvittera till MRS om s behvs */
if (receive_psb.del_psb_status == PAMS__CONFIRMREQ ||
receive_psb.del_psb_status == PAMS__POSSDUPL)
pams_confirm_msg(receive_psb.seq_number, &dmq_sts, &receive_force_j);
return(1);
}
/*
* Main routine
*/
main(int argc, char *argv[])
{
remnode_item *remnode = NULL; /* Temporary remnode */
unsigned int sts; /* Status from function calls etc. */
unsigned int sts2; /* Status from function calls etc. */
pwr_tObjid node; /* Loop node */
pwr_sClass_RemNode *nodep;
pwr_tObjid pwr_node; /* Own Pwr node */
pwr_sClass_PlcProcess *pwr_nodep; /* Ref to own Pwr node */
pwr_tTime OriginDnoChgTime; /* LastDnoChgTime at start */
int mygroup; /* DMQ group no */
mq_uAddress gdhpams_process;
DeclareExitHandler();
/* Get our DMQ queue from argument list */
if (argc >= 2)
sscanf(argv[1], "%ld", &my_queue.All);
else
my_queue.All = 125;
/* Declare us as a DMQ and GDH process. Max 5 retries */
sts = mq_AttachQueue ( &my_queue, &gdhpams_process);
if (EVEN(sts)) exit(sts);
sts = gdh_Init("rs_remote_dmq");
if (EVEN(sts)) exit(sts);
/* Get pointer to $Node-object */
sts = gdh_GetClassList(pwr_cClass_PlcProcess, &pwr_node);
sts = gdh_ObjidToPointer(pwr_node, (pwr_tAddress *) &pwr_nodep);
memcpy(&OriginDnoChgTime, &pwr_nodep->LastChgTime, sizeof(pwr_tTime));
/* Get first remnode object, only on local node */
sts = gdh_GetClassList(pwr_cClass_RemNode, &node);
if (EVEN(sts)) exit(sts);
while (ODD(sts))
{
sts = gdh_ObjidToPointer(node, (pwr_tAddress *) &nodep);
/* Check if transport type is DMQ and if remnode's process number matches ours */
if (nodep->TransportType == REMNODE_TRANSPORT_DMQ &&
nodep->Address[1] == my_queue.All)
{
/* Allocate a new item and link it */
remnode = malloc(sizeof(remnode_item));
if (!remnode) exit(REM__NOMEMORY);
remnode->objp = nodep;
remnode->objid = node;
remnode->next = (struct remnode_item *) remnode_list;
remnode_list = remnode;
remnode->Time_since_scan = 0;
remnode->Time_since_poll = 0;
remnode->Time_since_IO = 0;
remnode->Time_since_send = 0;
/* Initialize remtrans objects */
mygroup = gdhpams_process.au.Group;
sts = RemTrans_Init(remnode, mygroup);
if (EVEN(sts)) exit(sts);
/* Check if any cycle time is the shortest so far */
if (remnode->objp->CycleTime < cycle_time &&
remnode->objp->CycleTime >= min_cycle_time)
cycle_time = remnode->objp->CycleTime;
} /* if transport_type... */
sts = gdh_GetNextObject(node, &node);
} /* while */
/* Init Cycle Timer */
sts = InitCycleTimer();
if (EVEN(sts)) exit(sts);
/* Loop forever and wait for net message or timeout */
while (!doomsday)
{
sts = WaitEvent();
if (EVEN(sts)) exit(sts);
/* Om LastDnoChgTime r ndrad (PLC-programbyte), avsluta */
if (memcmp(&OriginDnoChgTime, &pwr_nodep->LastChgTime,
sizeof(pwr_tTime)) != 0) exit(0);
if (sts == RT_RECEIVE)
{
sts = ReceiveComplete();
if (EVEN(sts)) exit(sts);
}
else if (sts == RT_TIMEREXP)
{
remnode = remnode_list;
while(remnode)
{
remnode->Time_since_scan += cycle_time;
remnode->Time_since_send += cycle_time;
if (remnode->Time_since_scan >= remnode->objp->CycleTime)
{
sts = RemTrans_Cyclic(remnode, &remnode_send);
remnode->Time_since_scan = 0.0;
}
remnode = (remnode_item *) remnode->next;
}
/*
* Init a new timer
*/
sts = InitCycleTimer();
if (EVEN(sts)) exit(sts);
}
}
}
include $(pwre_dir_symbols)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(hw_name)/$(type_name)_generic.mk
ifeq ($($(type_name)_generic_mk),)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(type_name)_generic.mk
endif
ifeq ($($(type_name)_generic_mk),)
include $(pwre_kroot)/tools/bld/src/$(type_name)_generic.mk
endif
ifndef link_rule_mk
link_rule_mk := 1
link = $(ldxx) $(elinkflags) $(domap) -o $(export_exe) \
$(export_obj) $(objects) $(rt_msg_eobjs) $(rs_msg_eobjs) \
-lpwr_remote -lpwr_rt -lpwr_co -lpwr_msg_dummy -lpthread -lrt -lm
endif
/*
* Proview $Id: rs_remote_logg.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*************************************************************************
*
* PROGRAM rs_remote_logg
*
* Modifierad
* 950301 Claes Sjfors Skapad
* 010402 Claes Jurstrand Qcom istf DMQ frn v3.0b
* 040630 Claes Jurstrand v4.0.0
*
*
* Funktion:
* Tar emot transar med loggar frn remote och loggar p fil.
*
**************************************************************************/
/*_Include filer_________________________________________________________*/
#ifdef __DECC
#pragma message disable GLOBALEXT
#endif
#ifdef OS_VMS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <float.h>
#include <descrip.h>
#include <libdef.h>
#include <starlet.h>
#include <lib$routines.h>
/*
#include <pams_c_entry_point.h>
#include <pams_c_process.h>
#include <pams_c_type_class.h>
#include <pams_c_return_status.h>
#include <sbs_msg_def.h>
*/
#endif
#ifdef OS_ELN
#include stdio
#include stdlib
#include string
#include math
#include float
#include descrip
#include libdef
#include lib$routines
#include starlet
#endif
#if defined OS_LYNX || defined OS_LINUX
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#endif
#include "pwr.h"
#include "pwr_baseclasses.h"
#include "pwr_remoteclasses.h"
#include "co_time.h"
#include "rt_gdh.h"
#include "rt_errh.h"
#include "rt_gdh_msg.h"
#include "rt_hash_msg.h"
#include "rt_ini_event.h"
#include "rt_qcom.h"
#include "rt_qcom_msg.h"
#include "remote.h"
#include "rs_remote_msg.h"
/*_Globala variabler______________________________________________________*/
qcom_sQid remlogg_qid = {rs_pwr_logg_qix, 0};
qcom_sQattr remlogg_qattr;
qcom_sGet remlogg_get;
/* Global functions________________________________________________________*/
#define ODD(a) (((int)(a) & 1) != 0)
#define EVEN(a) (((int)(a) & 1) == 0)
#define max(Dragon,Eagle) ((Dragon) > (Eagle) ? (Dragon) : (Eagle))
#define min(Dragon,Eagle) ((Dragon) < (Eagle) ? (Dragon) : (Eagle))
#ifndef __ALPHA
#define abs(Dragon) ((Dragon) >= 0 ? (Dragon) : (-(Dragon)))
#endif
#define LogAndExit( status) \
{\
errh_CErrLog(REM__LOGGEXIT, errh_ErrArgMsg(status), NULL);\
exit( status);\
}
#define LogAndReturn( status1, status2) \
{\
errh_CErrLog(status1, errh_ErrArgMsg(status2), NULL);\
return status2;\
}
#define Log( status1, status2) \
{\
errh_CErrLog(status1, errh_ErrArgMsg(status2), NULL);\
}
#define LOGG_FILE_EXT ".log"
#define LOGG_MAX_SIZE 32000
typedef struct {
pwr_tObjid objid;
pwr_sClass_LoggConfig *loggconf;
gdh_tDlid subid;
FILE *outfile;
int file_open;
int wait_count;
} logg_t_loggconf_list;
typedef struct {
logg_t_loggconf_list *loggconflist;
int loggconf_count;
} *logg_ctx;
/*_Local functions________________________________________________________*/
static pwr_tStatus logg_loggconflist_add(
logg_ctx loggctx,
pwr_tObjid objid,
logg_t_loggconf_list **loggconflist,
int *loggconflist_count);
static int logg_get_filename(
char *inname,
char *outname,
char *ext);
static pwr_tStatus logg_open_file( logg_t_loggconf_list *conflist_ptr,
int first_time);
static pwr_tStatus logg_print( logg_ctx loggctx,
pwr_tUInt32 ident,
char *msg);
static pwr_tStatus logg_get_message( logg_ctx loggctx,
pwr_tUInt32 *ident,
char **msg);
static pwr_tStatus logg_init( logg_ctx loggctx);
/****************************************************************************
* Name: exit_hdlr()
*
* Type void
*
* Type Parameter IOGF Description
*
* Description:
* Called at exit
*
**************************************************************************/
void exit_hdlr()
{
gdh_DLUnrefObjectInfoAll();
errh_Info("Exiting\n");
return;
}
/****************************************************************************
* Name: interrupt_hdlr()
*
* Type void
*
* Type Parameter IOGF Description
*
* Description:
* Called at interrupt
*
**************************************************************************/
void interrupt_hdlr()
{
exit(0);
return;
}
/****************************************************************************
* Name: logg_loggconflist_add()
*
* Type pwr_tStatus
*
* Type Parameter IOGF Description
*
* Description:
* Add a conversion config object to the list.
*
**************************************************************************/
static pwr_tStatus logg_loggconflist_add(
logg_ctx loggctx,
pwr_tObjid objid,
logg_t_loggconf_list **loggconflist,
int *loggconflist_count)
{
logg_t_loggconf_list *loggconflist_ptr;
logg_t_loggconf_list *new_loggconflist;
pwr_sAttrRef attrref;
int i;
pwr_tStatus sts;
pwr_sClass_LoggConfig *loggconf;
/* Syntax check */
sts = gdh_ObjidToPointer ( objid, (pwr_tAddress *) &loggconf);
if ( EVEN(sts)) return sts;
/* Check that there is some filename */
if ( !strcmp( loggconf->LoggFile, ""))
return REM__LOGGFILE;
/* Check that identity is unique */
loggconflist_ptr = *loggconflist;
for ( i = 0; i < *loggconflist_count; i++)
{
if ( loggconflist_ptr->loggconf->Identity == loggconf->Identity)
return REM__DUPLIDENT;
loggconflist_ptr++;
}
if ( *loggconflist_count == 0)
{
*loggconflist = calloc( 1 , sizeof(logg_t_loggconf_list));
if ( *loggconflist == 0)
return REM__NOMEMORY;
}
else
{
new_loggconflist = calloc( *loggconflist_count + 1,
sizeof(logg_t_loggconf_list));
if ( new_loggconflist == 0)
return REM__NOMEMORY;
memcpy( new_loggconflist, *loggconflist,
*loggconflist_count * sizeof(logg_t_loggconf_list));
free( *loggconflist);
*loggconflist = new_loggconflist;
}
loggconflist_ptr = *loggconflist + *loggconflist_count;
loggconflist_ptr->objid = objid;
/* Direct link to the cell */
memset( &attrref, 0, sizeof(attrref));
attrref.Objid = objid;
sts = gdh_DLRefObjectInfoAttrref ( &attrref,
(pwr_tAddress *) &loggconflist_ptr->loggconf,
&loggconflist_ptr->subid);
if ( EVEN(sts)) return sts;
(*loggconflist_count)++;
return REM__SUCCESS;
}
/*************************************************************************
*
* Name: logg_get_filename
*
* Typ int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning:
* Adderar extention till filname om det saknas.
*
**************************************************************************/
static int logg_get_filename(
char *inname,
char *outname,
char *ext)
{
char *s;
char *s2;
char timestr[80];
char comp_timestr[80];
pwr_tTime time;
strcpy( outname, inname);
/* Look for extention in filename */
if ( ext != NULL)
{
s = strrchr( outname, ':');
if ( s == 0)
s = outname;
s2 = strrchr( s, '>');
if ( s2 == 0)
{
s2 = strrchr( s, ']');
if ( s2 == 0)
s2 = s;
}
s = strrchr( s2, '.');
if ( s != 0)
*s = 0;
strcat( outname, ext);
}
#if defined OS_LYNX || defined OS_LINUX
/* Get current time to use as "version number" */
clock_gettime( CLOCK_REALTIME, &time);
time_AtoAscii( &time, time_eFormat_ComprDateAndTime, timestr,
sizeof(timestr));
comp_timestr[0] = '.';
memcpy(&comp_timestr[1], &timestr[0], 2);
memcpy(&comp_timestr[3], &timestr[3], 2);
memcpy(&comp_timestr[5], &timestr[6], 2);
memcpy(&comp_timestr[7], &timestr[9], 2);
memcpy(&comp_timestr[9], &timestr[12], 2);
memcpy(&comp_timestr[11], &timestr[15], 2);
comp_timestr[13] = 0;
// strcat(outname, comp_timestr);
#endif
return REM__SUCCESS;
}
/*************************************************************************
*
* Name: logg_open_file
*
* Typ int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning:
* Open current logg file and write a file header.
*
**************************************************************************/
static pwr_tStatus logg_open_file( logg_t_loggconf_list *conflist_ptr,
int first_time)
{
int csts;
char filename[80];
pwr_tTime time;
char timestr[80];
if ( !first_time)
{
/* Check if it's time for a new try to open the file */
conflist_ptr->wait_count++;
if (conflist_ptr->wait_count < 10)
return REM__SUCCESS;
conflist_ptr->wait_count = 0;
}
/* Open file */
logg_get_filename( conflist_ptr->loggconf->LoggFile,
filename, LOGG_FILE_EXT);
#if defined OS_LYNX || defined OS_LINUX
conflist_ptr->outfile = fopen( filename, "a+");
#else
conflist_ptr->outfile = fopen( filename, "w+", "shr=get");
#endif
if (conflist_ptr->outfile != NULL)
{
/* Write a file header */
clock_gettime( CLOCK_REALTIME, &time);
time_AtoAscii( &time, time_eFormat_DateAndTime, timestr,
sizeof(timestr));
csts = fprintf( conflist_ptr->outfile,
"RemLogg file opened at %s\n\n", timestr);
if (csts >= 0)
{
conflist_ptr->loggconf->FileOpenCount++;
#if defined OS_ELN || defined OS_VMS
fgetname( conflist_ptr->outfile, filename);
#endif
errh_CErrLog( REM__LOGGFILEOPEN, errh_ErrArgAF(filename), NULL);
conflist_ptr->file_open = 1;
return REM__SUCCESS;
}
else
{
fclose( conflist_ptr->outfile);
}
}
errh_CErrLog( REM__LOGGFILE, errh_ErrArgAF(filename), NULL);
return REM__LOGGFILE;
}
/*************************************************************************
*
* Name: logg_print
*
* Typ int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning:
* Skrivning av logg meddelande p fil.
*
**************************************************************************/
static pwr_tStatus logg_print( logg_ctx loggctx,
pwr_tUInt32 ident,
char *msg)
{
int csts;
int found;
int i;
logg_t_loggconf_list *conflist_ptr;
logg_t_loggconf_list *garbage_conflist_ptr;
int garbage_loggconf_found;
if ( loggctx->loggconf_count == 0)
/* Not configured */
return REM__SUCCESS;
/* Identify the identity */
found = 0;
garbage_loggconf_found = 0;
conflist_ptr = loggctx->loggconflist;
for ( i = 0; i < loggctx->loggconf_count; i++)
{
if ( conflist_ptr->loggconf->Identity == 0)
{
/* This is the garbage loggfile */
garbage_conflist_ptr = conflist_ptr;
garbage_loggconf_found = 1;
}
if ( conflist_ptr->loggconf->Identity == ident)
{
found = 1;
break;
}
conflist_ptr++;
}
if ( !found)
{
if ( garbage_loggconf_found)
{
/* Write the logg on the garbage file */
conflist_ptr = garbage_conflist_ptr;
}
else
{
errh_CErrLog( REM__LOGGIDEN, NULL);
return REM__SUCCESS;
}
}
/* csts = fwrite( msg, min( strlen(msg),LOGG_MAX_SIZE), 1,
conflist_ptr->outfile);
if (csts == 0)
*/
csts = fprintf( conflist_ptr->outfile, "%s\n", msg);
if ( csts < 0)
{
/* File error, close file and try to open it later */
errh_CErrLog( REM__LOGGWRITE, NULL);
fclose( conflist_ptr->outfile);
conflist_ptr->file_open = 0;
}
else
{
csts = fflush( conflist_ptr->outfile);
if ( csts != 0)
{
/* File error, close file and try to open it later */
errh_CErrLog( REM__LOGGWRITE, NULL);
fclose( conflist_ptr->outfile);
conflist_ptr->file_open = 0;
}
else
conflist_ptr->loggconf->LoggCount++;
}
return REM__SUCCESS;
}
/*************************************************************************
*
* Name: logg_get_message
*
* Typ int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning:
* Reads message from qcom with timeout
*
**************************************************************************/
static pwr_tStatus logg_get_message( logg_ctx loggctx,
pwr_tUInt32 *ident,
char **msg)
{
pwr_tStatus sts;
unsigned int timeout = 200; /* 200 ms */
memset(&remlogg_get, 0, sizeof(remlogg_get));
remlogg_get.maxSize = LOGG_MAX_SIZE;
qcom_Get(&sts, &remlogg_qid, &remlogg_get, timeout);
if ( sts == QCOM__TMO)
return REM__TIMEOUT;
else if (EVEN(sts) || (sts == QCOM__QEMPTY)) return sts;
else
{
if (remlogg_get.type.b == qcom_eBtype_event) {
qcom_sEvent *ep = (qcom_sEvent*) remlogg_get.data;
ini_mEvent new_event;
if (remlogg_get.type.s == qcom_cIini) {
new_event.m = ep->mask;
if (new_event.b.terminate) {
exit(0);
}
}
}
else {
*ident = * (pwr_tUInt32 *) remlogg_get.data;
*msg = (char *) remlogg_get.data + sizeof(pwr_tUInt32);
}
}
return REM__SUCCESS;
}
/*************************************************************************
*
* Name: logg_free_message
*
* Typ int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning:
* Frees qcom message
*
**************************************************************************/
static pwr_tStatus logg_free_message( void)
{
pwr_tStatus sts;
if (remlogg_get.data != 0) qcom_Free(&sts, remlogg_get.data);
if (EVEN(sts)) return sts;
return REM__SUCCESS;
}
/*************************************************************************
*
* Name: logg_init
*
* Typ int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning:
* Initiering av loggfunktionen.
*
**************************************************************************/
static pwr_tStatus logg_init( logg_ctx loggctx)
{
pwr_tStatus sts;
pwr_tObjid objid;
logg_t_loggconf_list *conflist_ptr;
int i;
/* Get the logg config objects on this node */
sts = gdh_GetClassList ( pwr_cClass_LoggConfig, &objid);
while ( ODD(sts))
{
/* Store and direct link the LoggConfig objects */
sts = logg_loggconflist_add( loggctx, objid,
&loggctx->loggconflist,
&loggctx->loggconf_count);
if (EVEN(sts)) Log( REM__CONFINIT, sts);
sts = gdh_GetNextObject( objid, &objid);
}
/* Open the files */
conflist_ptr = loggctx->loggconflist;
for ( i = 0; i < loggctx->loggconf_count; i++)
{
sts = logg_open_file( conflist_ptr, 1);
conflist_ptr++;
}
return REM__SUCCESS;
}
int main()
{
logg_ctx loggctx;
pwr_tStatus sts;
pwr_tUInt32 ident;
char *msg;
logg_t_loggconf_list *conflist_ptr;
int i;
#if defined OS_LYNX || defined OS_LINUX
/* Exit handler */
atexit(&exit_hdlr);
signal(SIGINT, interrupt_hdlr);
#endif
sts = gdh_Init("rs_remote_logg");
if (EVEN(sts)) LogAndExit(sts);
/* Errh init */
errh_Init("rs_remote_logg", 0);
/* Initialize qcom que attributes */
remlogg_qattr.type = qcom_eQtype_private;
remlogg_qattr.quota = 100;
/* Delete the queue if it exists */
qcom_DeleteQ(&sts, &remlogg_qid);
/* Create the remlogg queue */
if (!qcom_CreateQ(&sts, &remlogg_qid, &remlogg_qattr, "Logg")) {
LogAndExit(sts);
}
/* Bind it to rt_ini event-queue */
if (!qcom_Bind(&sts, &remlogg_qid, &qcom_cQini)) {
errh_Fatal("qcom_Bind, %m", sts);
// errh_SetStatus( PWR__SRVTERM);
exit(-1);
}
loggctx = calloc( 1 , sizeof( *loggctx));
if ( loggctx == 0 ) LogAndExit( REM__NOMEMORY);
sts = logg_init( loggctx);
if ( EVEN(sts)) LogAndExit(sts);
for (;;)
{
/* Get logg message */
sts = logg_get_message( loggctx, &ident, &msg);
if ( EVEN(sts))
{
Log( REM__LOGGRCV, sts);
}
else if ( sts != REM__TIMEOUT)
{
logg_print( loggctx, ident, msg);
sts = logg_free_message();
}
/* Check if its time to open any file... */
conflist_ptr = loggctx->loggconflist;
for ( i = 0; i < loggctx->loggconf_count; i++)
{
if ( conflist_ptr->loggconf->NewVersion)
{
conflist_ptr->loggconf->NewVersion = 0;
if ( conflist_ptr->file_open)
{
fclose( conflist_ptr->outfile);
conflist_ptr->file_open = 0;
sts = logg_open_file( conflist_ptr, 1);
}
}
else if ( !conflist_ptr->file_open)
{
sts = logg_open_file( conflist_ptr, 0);
}
conflist_ptr++;
}
}
}
include $(pwre_dir_symbols)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(hw_name)/$(type_name)_generic.mk
ifeq ($($(type_name)_generic_mk),)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(type_name)_generic.mk
endif
ifeq ($($(type_name)_generic_mk),)
include $(pwre_kroot)/tools/bld/src/$(type_name)_generic.mk
endif
ifndef link_rule_mk
link_rule_mk := 1
link = $(ldxx) $(elinkflags) $(domap) -o $(export_exe) \
$(export_obj) $(objects) $(rt_msg_eobjs) \
-lpwr_remote -lpwr_rt -lpwr_co -lpwr_msg_dummy -lpthread -lrt -lm
endif
/*
* Proview $Id: rs_remote_modbus.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*************************************************************************
*
* M O D B U S
* ===========
**************************************************************************
*
* Filename: remote_modbus.c
*
* Date Pgm. Read. Remark
* Modified 970317 CJu - -
* 030908 UL For Linux
* 040505 UL Fixed timeout for recieve to 34 chartimes
*
* Description: Implements remote transport process for MODBUS
*
**************************************************************************
**************************************************************************/
/*_Include files_________________________________________________________*/
#include <time.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <termios.h>
#include <termio.h>
#include <sgtty.h>
#include <sys/ioctl.h>
#include "remote_mq.h"
#include "pwr_class.h"
#include "pwr_systemclasses.h"
#include "co_cdh.h"
#include "rt_gdh.h"
#include "rt_aproc.h"
#include "rt_pwr_msg.h"
#include "pwr_baseclasses.h"
#include "pwr_remoteclasses.h"
#include "remote.h"
#include "remote_utils.h"
#include "remote_remtrans_utils.h"
#include "pwr.h"
#include "rt_gdh.h"
#include "rt_gdh_msg.h"
#include "rt_plc_utl.h"
#include "rt_errh.h"
/*_functions_______________________________________________________________*/
static unsigned int remnode_send(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buffer_size);
void generate_crc(unsigned char *buf, int size, unsigned char *result);
static unsigned int Receive();
/*_variables_______________________________________________________________*/
remnode_item rn;
pwr_sClass_RemnodeModbus *rn_modbus;
int ser_fd; /* file domininator for serial port */
float time_since_scan;
float time_since_rcv;
void load_timeval(struct timeval *tv, float t)
{
tv->tv_sec = t;
tv->tv_usec = (t-(float)tv->tv_sec) * 1000000;
}
/************************************************************************
**************************************************************************
*
* Namn : generate_crc
*
* Typ : void
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Generates CRC checksum for a buffer of unsigned chars
*
**************************************************************************
**************************************************************************/
void generate_crc(unsigned char *buf, int size, unsigned char *result)
{
unsigned short int crc;
unsigned short int gen_polynomial = 0xA001;
unsigned short int flag_mask = 0x0001;
unsigned short int flag;
short int i, j;
crc = 0xFFFF;
for (i=0; i<size; i++)
{
crc = crc^buf[i];
for (j=0; j<8; j++)
{
flag = crc & flag_mask;
crc = crc >> 1;
if (flag) crc = crc ^ gen_polynomial;
}
}
result[0] = (unsigned char) (crc & 0x00FF);
result[1] = (unsigned char) ((crc >> 8) & 0x00FF);
return;
}
/*************************************************************************
**************************************************************************
*
* Namn : remnode_send
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends a RemTrans message to Remote node
*
**************************************************************************
**************************************************************************/
static unsigned int remnode_send(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buffer_size)
{
int sts;
// int size_of_telegram;
// int nbr_of_bytes_written = 0;
// unsigned char ch;
unsigned char telegram[516];
if (buffer_size > sizeof(telegram)-4)
{
errh_Info("Remote modbus send failed, telegram to big");
return(1);
}
/*************************************************************************/
/** Fill up telegram with contents of message and calculate checksum **/
/*************************************************************************/
telegram[0] = remtrans->Address[0]; /* Slave address */
telegram[1] = remtrans->Address[1]; /* Function code */
memcpy(&telegram[2], buf, buffer_size);
generate_crc(telegram, buffer_size+2, &telegram[buffer_size+2]);
/*************************************************************************/
/** Execute the send procedure **/
/*************************************************************************/
sts=write(ser_fd, telegram, buffer_size+4);
/*************************************************************************/
/** Check final status. **/
/*************************************************************************/
if (sts > 0)
{
/* Send OK, receive answer */
sts = Receive();
}
else
{
/* The send procedure has failed */
errh_Info("Remote modbus send failed, write() failed");
}
return(sts);
}
/*************************************************************************
**************************************************************************
*
* Namn : Receive
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Waits for message on serial line
*
**************************************************************************
**************************************************************************/
static unsigned int Receive()
{
int sts, data_size=0;
// int nbr_of_bytes_read = 0;
unsigned char telegram[512];
// unsigned char ch;
unsigned char crc[2];
// DDA$_EXTENDED_STATUS_INFO stsblk;
// int error_logged = 0;
char search_remtrans = FALSE;
remtrans_item *remtrans;
fd_set read_fd;
struct timeval tv;
/**** set up timeout ****/
load_timeval(&tv, rn_modbus->ReadTimeout);
/* old
tv.tv_sec = 0;
//tv.tv_usec = 10000; //(4 char timeout recieve vid 9600)
tv.tv_usec = (1/portspeed)*10*34 //10000 (4 char timeout recieve vid 9600)
*/
/**routine**/
FD_ZERO(&read_fd);
FD_SET(ser_fd, &read_fd);
sts=select(ser_fd+1, &read_fd, NULL, NULL, &tv);
sts=read(ser_fd, telegram, 1);
if(sts>0)
{
while(sts>0)
{
data_size++;
load_timeval(&tv, rn_modbus->ReadTimeout);
/* old
tv.tv_sec = 0;
tv.tv_usec = (1/portspeed)*10*34 //10000 (4 char timeout recieve vid 9600)
*/
FD_ZERO(&read_fd);
FD_SET(ser_fd, &read_fd);
sts=select(ser_fd+1, &read_fd, NULL, NULL, &tv);
sts=read(ser_fd, telegram+data_size, 1);
}
generate_crc(telegram, data_size-2, crc);
if( crc[0]!=telegram[data_size-2] || crc[1]!=telegram[data_size-1])
{
rn_modbus->ErrCount++;
errh_Info("Modbus remote CRC error, calc CRC:%02x%02x telegram CRC:%02x%02x",crc[0], crc[1],telegram[data_size-1],telegram[data_size]);
return (FALSE);
}
else
{
search_remtrans = true;
remtrans = rn.remtrans;
while(remtrans && search_remtrans)
{
if ( remtrans->objp->Address[0] == telegram[0] &&
remtrans->objp->Address[1] == telegram[1] &&
remtrans->objp->Direction == REMTRANS_IN )
search_remtrans = false;
if ( search_remtrans ) remtrans = (remtrans_item *) remtrans->next;
} /* endwhile */
if ( !search_remtrans )
{
sts = RemTrans_Receive(remtrans, &telegram[2], data_size-4);
if ( EVEN(sts) )
{
remtrans->objp->ErrCount++;
return (FALSE);
}
}
if (search_remtrans)
{
/* No corresponding RemTrans object found */
rn_modbus->ErrCount++;
errh_Info("Modbus remote error, no corresponding RemTrans address object found");
return (FALSE);
}
}
}
return(sts);
}
/***************************************************
****** Main routine *****************
***************************************************/
int main(int argc, char *argv[])
{
unsigned int sts; /* Status from function calls etc. */
unsigned char id[32];
unsigned char pname[32];
remtrans_item *remtrans;
int i;
/* Read arg number 2, should be id for this instance */
if (argc >= 2)
strcpy(id, argv[1]);
else
strcpy(id, "0");
/* Build process name with id */
sprintf((char *) pname, "rs_remmodbus_%s", id);
/* Init of errh */
errh_Init((char *) pname, errh_eAnix_remote);
errh_SetStatus(PWR__SRVSTARTUP);
/* Init of gdh */
sts = gdh_Init((char *) pname);
if ( EVEN(sts)) {
errh_Error("gdh_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Arg number 3 should be my remnodes objid in string representation,
read it, convert to real objid and store in remnode_item */
sts = 0;
if (argc >= 3) sts = cdh_StringToObjid(argv[2], &rn.objid);
if ( EVEN(sts)) {
errh_Error("cdh_StringToObjid, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Get pointer to RemnodeModbus object and store locally */
sts = gdh_ObjidToPointer(rn.objid, (pwr_tAddress *) &rn_modbus);
if ( EVEN(sts)) {
errh_Error("cdh_ObjidToPointer, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Initialize some internal data and make standard remtrans init */
rn.next = NULL;
rn.local = NULL; // We dont use local structure since we only have one remnode
rn.retransmit_time = 10.0; // Not used, but initialize anyway
rn_modbus->ErrCount = 0;
sts = RemTrans_Init(&rn);
if ( EVEN(sts)) {
errh_Error("RemTrans_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
time_since_scan = 0;
time_since_rcv = 0;
/* Store remtrans objects objid in remnode_modbus object */
remtrans = rn.remtrans;
i = 0;
while(remtrans) {
rn_modbus->RemTransObjects[i++] = remtrans->objid;
if ( i >= (int)(sizeof(rn_modbus->RemTransObjects)/sizeof(rn_modbus->RemTransObjects[0])))
break;
remtrans = (remtrans_item *) remtrans->next;
}
/* Initialize device */
ser_fd = RemUtils_InitSerialDev(rn_modbus->DevName,
rn_modbus->Speed,
rn_modbus->DataBits,
rn_modbus->StopBits,
rn_modbus->Parity);
if (!ser_fd) {
errh_Error("InitDev, %d", ser_fd);
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
/* Loop forever */
while (!doomsday)
{
if (rn_modbus->Disable == 1) {
errh_Fatal("Disabled, exiting");
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
sts = Receive();
sts = RemTrans_Cyclic(&rn, &remnode_send);
}
}
/*
* Proview $Id: rs_remote_pams.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*************************************************************************
*
* Filename: remote_pams.c
*
* Date Pgm. Read. Remark
* Modified 950307 CJu
*
* Description: Implements remote transport process PAMS
*
**************************************************************************/
#ifdef __DECC
#pragma message disable GLOBALEXT
#endif
/*_Include files_________________________________________________________*/
#ifdef OS_ELN
#include $vaxelnc
#include $exit_utility
#include $function_descriptor
#include ssdef
#include stdio
#include stdlib
#include string
#include math
#include iodef
#include descrip
#include psldef
#include libdtdef
#include lib$routines
/***
#include pams_c_process
#include pams_c_group
#include pams_c_type_class
#include pams_c_return_status_def
#include pams_c_symbol_def
#include pams_c_entry_point
#include sbs_msg_def
***/
#endif
#ifdef OS_VMS
#include <ssdef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <iodef.h>
#include <descrip.h>
#include <psldef.h>
#include <libdtdef.h>
#include <lib$routines.h>
#include <pams_c_process.h>
#include <pams_c_type_class.h>
#include <pams_c_return_status.h>
#include <sbs_msg_def.h>
#endif
#include "pwr_class.h"
#include "pwrs_c_node.h"
#include "rs_remote_mq.h"
#include "rt_gdh.h"
#include "rt_errh.h"
#include "pwr_baseclasses.h"
#include "pwr_ssabclasses.h"
#include "rs_remote_msg.h"
#include "rs_remote.h"
#include "rs_remtrans_utils.h"
#define CLASS_APL_RESP 101
#define CLASS_RESP 102
#ifdef OS_ELN
PROCESS my_proc;
PORT job_port;
#endif
mq_uAddress my_pams_process; /* Pams processnumber for this job */
char receive_buffer[32767]; /* Pointer to received message */
int receive_prio = 0; /* Prio for messages */
mq_uAddress receive_src; /* group, process received message */
short int receive_class; /* Class of received message */
short int receive_type; /* Type of received message */
int receive_size; /* Size of received message */
remnode_item *remnode_list = NULL; /* List of remnodes (internal structure) */
float cycle_time = 1.0; /* Cycle time in seconds */
float min_cycle_time = 0.01; /* Shortest scan time */
unsigned int timer_id = 1;
/*************************************************************************
**************************************************************************
*
* Namn : exith
*
* Typ : void
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Exit handler that is called before process termination
*
**************************************************************************
**************************************************************************/
void exith(void)
{
unsigned int sts;
sts = pams_cancel_timer(&timer_id);
sts = pams_exit(&my_pams_process);
return;
}
/*************************************************************************
**************************************************************************
*
* Namn : DeclareExitHandler
*
* Typ : void
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Declares an exit handler that is called before
* process termination
*
**************************************************************************
**************************************************************************/
void DeclareExitHandler(void)
{
#ifdef OS_ELN
FUNCTION_DESCRIPTOR fn_descriptor;
eln$declare_exit_handler(ELN$PASS_FUNCTION_DESCRIPTOR(fn_descriptor, exith),
NULL);
#else
atexit(exith);
#endif
}
/*************************************************************************
**************************************************************************
*
* Namn : InitCycleTimer
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sets PAMS scan timer
*
**************************************************************************
**************************************************************************/
unsigned int InitCycleTimer()
{
unsigned int sts;
unsigned int sts2;
unsigned int time_function_code = LIB$K_DELTA_SECONDS_F;
char format = 'S';
unsigned short delta_time[4];
/* Konvertera cykeltiden till intern deltatid */
sts = lib$cvtf_to_internal_time(&time_function_code,
&cycle_time,
&delta_time);
if (EVEN(sts)) exit(sts);
sts = pams_set_timer(&timer_id, &format, &0, &delta_time);
return(sts);
}
/*************************************************************************
**************************************************************************
*
* Namn : WaitEvent
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Waits for Net receive or timer expiration.
*
**************************************************************************
**************************************************************************/
unsigned int WaitEvent(void)
{
unsigned int sts;
unsigned int receive_timeout = 0;
short buffer_size;
buffer_size = sizeof(receive_buffer);
sts = pams_get_msgw(&receive_buffer, &receive_prio, &receive_src,
&receive_class, &receive_type, &buffer_size,
&receive_size, &receive_timeout);
if (sts == SS$_NORMAL)
{
if (receive_type == MSG_TYPE_TIMER_EXPIRED)
return(RT_TIMEREXP);
else
return(RT_RECEIVE);
}
else
return(RT_ERROR);
}
/*************************************************************************
**************************************************************************
*
* Namn : send_pollbuff
*
* Typ : void
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends a poll or IO update message to Remote node
*
**************************************************************************
**************************************************************************/
void send_pollbuff( remnode_item *remnode,
pssupd_buffer *buf)
{
return;
}
/*************************************************************************
**************************************************************************
*
* Namn : remnode_send
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends a message to Remote node
*
**************************************************************************
**************************************************************************/
unsigned int remnode_send(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buf_size)
{
unsigned int sts;
char *send_buffer; /* Pointer to message */
int send_prio = 0; /* Prio for messages */
mq_uAddress dest; /* group, process for message */
sts = pams_alloc_msg(&buf_size, &send_buffer);
if (EVEN(sts)) exit(sts);
memcpy(send_buffer, buf, buf_size);
dest.au.Group = remnode->objp->Address[0];
dest.au.Queue = remtrans->Address[2];
sts = pams_send_msg(&send_buffer,
&send_prio,
&dest,
&remtrans->Address[0],
&remtrans->Address[1],
&0);
if (ODD(sts) && (remtrans->Address[0] == CLASS_APL_RESP))
return(STATUS_BUFACK);
else
return(sts);
}
/*************************************************************************
**************************************************************************
*
* Namn : ReceiveComplete
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Invoked when a message is received on the ethernet.
*
**************************************************************************
**************************************************************************/
unsigned int ReceiveComplete()
{
unsigned int sts;
char search_remnode = TRUE;
char search_remtrans = TRUE;
char send_response = FALSE;
remnode_item *remnode;
remtrans_item *remtrans;
char *response_buffer; /* Pointer to response message */
int response_prio = 0; /* Prio for response */
short int response_class = CLASS_RESP; /* Class of response */
int response_size = 4; /* Size of response = 4 bytes */
search_remnode = TRUE;
remnode = remnode_list;
while (remnode && search_remnode)
{
if (receive_src.au.Group == remnode->objp->Address[0])
search_remnode = FALSE;
else
remnode = (remnode_item *) remnode->next;
}
if (search_remnode)
errh_CErrLog(REM__UNKNOWNSOURCE);
else
{
if (receive_class == CLASS_RESP) /* Response message */
{
rem_t_transbuff *transbuff;
transbuff = remnode->transbuff;
if (transbuff &&
transbuff->remtrans->objp->Address[0] == CLASS_APL_RESP &&
transbuff->remtrans->objp->Address[1] == receive_type &&
(memcmp(&transbuff->data, receive_buffer, response_size ) == 0))
{
remnode->transbuff = (rem_t_transbuff *) transbuff->next;
transbuff->remtrans->objp->Buffers--;
remnode->Time_since_send = remnode->objp->ErrTime;
free(transbuff);
transbuff = remnode->transbuff;
if (transbuff)
{
sts = remnode_send(remnode,
transbuff->remtrans->objp,
&transbuff->data, transbuff->size);
if (ODD(sts))
{
remnode->transbuff = (rem_t_transbuff *) transbuff->next;
transbuff->remtrans->objp->Buffers--;
free(transbuff);
}
}
}
}
else
{
search_remtrans = true;
remtrans = remnode->remtrans;
while(remtrans && search_remtrans)
{
if (remtrans->objp->Address[0] == receive_class &&
remtrans->objp->Address[1] == receive_type &&
remtrans->objp->Direction == REMTRANS_IN)
{
search_remtrans = false;
sts = RemTrans_Receive(remtrans, receive_buffer, receive_size);
if (ODD(sts) && receive_class == CLASS_APL_RESP) send_response = TRUE;
break;
}
remtrans = (remtrans_item *) remtrans->next;
}
if (search_remtrans) remnode->objp->ErrTransCount++;
}
if (send_response)
{
/* Send a response message back to source with class response */
sts = pams_alloc_msg(&response_size, &response_buffer);
if (EVEN(sts)) exit(sts);
memcpy(response_buffer, receive_buffer, response_size);
sts = pams_send_msg(&response_buffer,
&response_prio,
&receive_src,
&response_class,
&receive_type,
&0);
if (EVEN(sts)) exit(sts);
}
} /* if search_remnode ... */
return(1);
}
#ifdef OS_ELN
/*************************************************************************
**************************************************************************
*
* Namn : WaitFor_PLC_Change
*
* Typ : int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Subprocess waits for message from REMOTEHANDLER on job_port,
* that will kill the process at PLC-change.
*
**************************************************************************
**************************************************************************/
int WaitFor_PLC_Change()
{
pwr_tStatus sts;
ker$wait_any(&sts, NULL, NULL, &job_port);
exith();
ker$delete(&sts, my_proc);
}
#endif
/*
* Main routine
*/
main(int argc, char *argv[])
{
remnode_item *remnode = NULL; /* Temporary remnode */
unsigned int sts; /* Status from function calls etc. */
unsigned int sts2; /* Status from function calls etc. */
pwr_tObjid node; /* Loop node */
pwr_sClass_RemNode *nodep;
pwr_tObjid pwr_node; /* Own Pwr node */
pwr_sClass_PlcProcess *pwr_nodep; /* Ref to own Pwr plcprocess */
pwr_tTime OriginDnoChgTime; /* LastDnoChgTime at start */
int mygroup; /* PAMS group no */
mq_uAddress gdhpams_process;
#ifdef OS_ELN
PROCESS id;
static struct dsc$descriptor_s name_desc = {0, DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
NAME name_id;
/* Get process-id to be able to kill myself. Create subprocess to kill. */
ker$job_port(&sts, &job_port);
ker$current_process(&sts, &my_proc);
/* Create a name for my own process (first process in job) */
name_desc.dsc$a_pointer = argv[3];
name_desc.dsc$w_length = strlen(argv[3]);
ker$create_name(&sts, &name_id, &name_desc, my_proc, NULL);
/* Create process that waits for PLC-change (hotswitch) */
ker$create_process( &sts, &id, WaitFor_PLC_Change, NULL);
#endif
DeclareExitHandler();
/* Get our PAMS process number from argument list */
if (argc >= 2)
sscanf(argv[1], "%ld", &my_pams_process.All);
else
my_pams_process.All = 125;
/* Declare us as a PAMS and GDH process. Max 5 retries */
sts = mq_AttachQueue ( &my_pams_process, &gdhpams_process);
if (EVEN(sts)) exit(sts);
sts = gdh_Init("rs_remote_pams");
if (EVEN(sts)) exit(sts);
/* Get pointer to $Node-object */
sts = gdh_GetClassList( pwr_cClass_PlcProcess, &pwr_node);
sts = gdh_ObjidToPointer(pwr_node, (pwr_tAddress *) &pwr_nodep);
memcpy(&OriginDnoChgTime, &pwr_nodep->LastChgTime, sizeof(pwr_tTime));
/* Get first remnode object, only on local node */
sts = gdh_GetClassList(pwr_cClass_RemNode, &node);
if (EVEN(sts)) exit(sts);
while (ODD(sts))
{
sts = gdh_ObjidToPointer(node, (pwr_tAddress *) &nodep);
/* Check if transport type is PAMS and if remnode's process number matches ours */
if (nodep->TransportType == REMNODE_TRANSPORT_PAMS &&
nodep->Address[1] == my_pams_process.All)
{
/* Allocate a new item and link it */
remnode = malloc(sizeof(remnode_item));
if (!remnode) exit(REM__NOMEMORY);
remnode->objp = nodep;
remnode->objid = node;
remnode->next = (struct remnode_item *) remnode_list;
remnode_list = remnode;
remnode->Time_since_scan = 0;
remnode->Time_since_poll = 0;
remnode->Time_since_IO = 0;
remnode->Time_since_send = 0;
/* Initialize remtrans objects */
mygroup = gdhpams_process.au.Group;
sts = RemTrans_Init(remnode, mygroup);
if (EVEN(sts)) exit(sts);
/* Check if any cycle time is the shortest so far */
if (remnode->objp->CycleTime < cycle_time &&
remnode->objp->CycleTime >= min_cycle_time)
cycle_time = remnode->objp->CycleTime;
} /* if transport_type... */
sts = gdh_GetNextObject(node, &node);
} /* while */
/* Init Cycle Timer */
sts = InitCycleTimer();
if (EVEN(sts)) exit(sts);
/* Loop forever and wait for net message or timeout */
while (!doomsday)
{
sts = WaitEvent();
if (EVEN(sts)) exit(sts);
/* Om LastDnoChgTime r ndrad (PLC-programbyte), avsluta */
if (memcmp(&OriginDnoChgTime, &pwr_nodep->LastChgTime,
sizeof(pwr_tTime)) != 0) exit(0);
if (sts == RT_RECEIVE)
{
sts = ReceiveComplete();
if (EVEN(sts)) exit(sts);
}
else if (sts == RT_TIMEREXP)
{
remnode = remnode_list;
while(remnode)
{
remnode->Time_since_scan += cycle_time;
remnode->Time_since_send += cycle_time;
if (remnode->Time_since_scan >= remnode->objp->CycleTime)
{
sts = RemTrans_Cyclic(remnode, &remnode_send);
remnode->Time_since_scan = 0.0;
}
remnode = (remnode_item *) remnode->next;
}
/*
* Init a new timer
*/
sts = InitCycleTimer();
if (EVEN(sts)) exit(sts);
}
}
}
/*
* Proview $Id: rs_remote_rk512.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*************************************************************************
*
* R K 5 1 2
* =========
**************************************************************************
*
* Filename: rs_remote_rk512.c
*
* Date Pgm. Read. Remark
* Modified 951006 CJu
* 951124 TAn
*
* Description: Implements remote transport process RK512
*
**************************************************************************
**************************************************************************/
/*_Include files_________________________________________________________*/
#ifdef OS_ELN
#include $vaxelnc
#include $exit_utility
#include $function_descriptor
#include $dda_utility
#include $elnmsg
#include $kernelmsg
#include ssdef
#include stdio
#include stdlib
#include string
#include math
#include iodef
#include descrip
#include psldef
#include libdtdef
#include starlet
#include lib$routines
#endif
#ifdef OS_VMS
#include <ssdef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <iodef.h>
#include <descrip.h>
#include <psldef.h>
#include <libdtdef.h>
#include <starlet.h>
#include <lib$routines.h>
#include <pams_c_process.h>
#include <pams_c_type_class.h>
#include <pams_c_return_status.h>
#include <sbs_msg_def.h>
#endif
#include "pwr_class.h"
#include "pwr_systemclasses.h"
#include "rt_gdh.h"
#include "pwr_baseclasses.h"
#include "pwr_ssabclasses.h"
#include "rs_remote_msg.h"
#include "rs_remote.h"
#include "rs_remtrans_utils.h"
/*_defines_________________________________________________________________*/
#define HEADER_SIZE 10
#define FOLLOW_ON_HEADER_SIZE 4
#define MAX_SIZE_DATA_BLOCK 128
#define MAX_SIZE_TELEGRAM 141
#define RESP_MESSAGE_SIZE 6
#define NUMBER_OF_STOP_CHAR 3
#define TRUE 1
#define FALSE 0
#define BYTE_MASK 0xFF
#define CPU_NR_MASK 0xF0
#define NUL 0
#define STX 2
#define ETX 3
#define DLE 16
#define NAK 21
#ifdef OS_ELN
/*
* ELN specific variables
*/
PORT virtual_serial_line_port;
PORT job_port;
PROCESS my_proc;
MESSAGE read_message;
char *read_message_buf[1024];
MESSAGE write_message;
char *write_message_buf[1024];
int msgsize = 1024;
#else
/*
* VMS specific variables
*/
unsigned int receive_ef;
unsigned int timer_ef;
unsigned int ef_mask;
#endif
/*
* Variables common for VMS and ELN
*/
remnode_item remnode_struct;
remnode_item *remnode = &remnode_struct;
LARGE_INTEGER timeout_cycle;
float max_acknowledge_delay = 2.0; /* Ack. time out on STX request */
LARGE_INTEGER timeout_ack;
float max_response_delay = 5.0; /* Response time out on send telegr. */
LARGE_INTEGER timeout_resp;
float max_char_delay = 0.5; /* Time out receive of next character */
LARGE_INTEGER timeout_char;
unsigned int telegram_counter = 0; /* For control of follow on telegrams */
/********** Function prototypes **********************************/
static void exith(void);
static void DeclareExitHandler(void);
static unsigned int InitTimers(void);
static unsigned int InitNet(void);
static unsigned int remnode_send(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buf_size);
static unsigned int Receive();
static unsigned int ReceiveHandler();
int SendResponseTelegram(unsigned char CODE);
#ifdef OS_VMS
int WaitFor_PLC_Change();
#endif
/*************************************************************************
**************************************************************************
*
* Namn : exith
*
* Typ : void
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Exit handler that is called before process termination
*
**************************************************************************
**************************************************************************/
static void exith(void)
{
#ifdef OS_ELN
unsigned int sts;
#else
return;
#endif
}
/*************************************************************************
**************************************************************************
*
* Namn : DeclareExitHandler
*
* Typ : void
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Declares an exit handler that is called before
* process termination
*
**************************************************************************
**************************************************************************/
static void DeclareExitHandler(void)
{
#ifdef OS_ELN
FUNCTION_DESCRIPTOR fn_descriptor;
eln$declare_exit_handler(ELN$PASS_FUNCTION_DESCRIPTOR(fn_descriptor, exith),
NULL);
#else
atexit(exith);
#endif
}
/*************************************************************************
**************************************************************************
*
* Namn : InitTimers
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Initiates the timers used in this process.
*
**************************************************************************
**************************************************************************/
static unsigned int InitTimers(void)
{
unsigned int sts;
unsigned int time_function_code = LIB$K_DELTA_SECONDS_F;
/* Konvertera cykeltiden till intern deltatid */
sts = lib$cvtf_to_internal_time(&time_function_code,
&remnode->objp->CycleTime,
&timeout_cycle);
if ( ODD(sts) )
{
/* Set timeout for response character from receiver */
sts = lib$cvtf_to_internal_time(&time_function_code,
&max_acknowledge_delay,
&timeout_ack);
}
if ( ODD(sts) )
{
/* Set timeout for response telegram from receiver */
sts = lib$cvtf_to_internal_time(&time_function_code,
&max_response_delay,
&timeout_resp);
}
if ( ODD(sts) )
{
/* Set timeout for max delay between receive of two characters */
sts = lib$cvtf_to_internal_time(&time_function_code,
&max_char_delay,
&timeout_char);
}
return(sts);
}
/*************************************************************************
**************************************************************************
*
* Namn : InitNet
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Assigns and sets up device
*
**************************************************************************
**************************************************************************/
static unsigned int InitNet(void)
{
unsigned int i, sts;
char ch = '\0';
char namestring[80];
char portname[100];
PORT DDA_destination_port;
struct dsc$descriptor_s dataportname;
for ( i=0 ; ( ch != ':' )&&( i < 80 ) ; i++ )
{
namestring[i] = ch = remnode->objp->NodeName[i];
}
namestring[--i] = '\0';
sprintf(portname, "%s$ACCESS", namestring);
dataportname.dsc$a_pointer = portname;
dataportname.dsc$w_length = strlen(portname);
dataportname.dsc$b_class = DSC$K_CLASS_S;
dataportname.dsc$b_dtype = DSC$K_DTYPE_T;
/* Associate portnamne with serial line port ID */
ker$translate_name(&sts, &DDA_destination_port, &dataportname, NAME$LOCAL);
if ( ODD(sts) )
/* Create a new port object */
ker$create_port(&sts, &virtual_serial_line_port, NULL);
if ( ODD(sts) )
/* Connect the port object to the destination_port */
ker$connect_circuit(&sts,
&virtual_serial_line_port,
&DDA_destination_port,
NULL, NULL, NULL, NULL);
if ( ODD(sts) )
{
/* Create messages for tty_read and tty_write operations */
ker$create_message(&sts, &read_message, &read_message_buf, msgsize+512);
ker$create_message(&sts, &write_message, &write_message_buf, msgsize+512);
}
return(sts);
}
/*************************************************************************
**************************************************************************
*
* Namn : remnode_send
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends a message to Remote node
*
**************************************************************************
**************************************************************************/
static unsigned int remnode_send(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buf_size)
{
unsigned int sts, i;
unsigned int size_of_telegram, datasize;
unsigned int number_of_DLE = 0;
unsigned int nbr_of_bytes_written = 0;
unsigned int nbr_of_bytes_read = 0;
unsigned int delta_pos = 0;
unsigned int pos_counter = 0;
unsigned int follow_on = FALSE;
unsigned int A_telegram = FALSE;
unsigned char ch, cpu_number, CPU;
unsigned char BCC = DLE ^ ETX;
unsigned char datasize_low_byte, datasize_high_byte;
unsigned char received_char = '\0';
unsigned char response_buffer[RESP_MESSAGE_SIZE];
unsigned char *data_packet_ptr;
unsigned char *end_of_message_ptr;
unsigned char *restore_buf_ptr = buf;
static unsigned char sstx[2] = {STX, '\0'};
static unsigned char sdle[2] = {DLE, '\0'};
static unsigned char snak[2] = {NAK, '\0'};
DDA$_BREAK_MASK DLE_mask = DLE;
DDA$_BREAK_MASK STX_mask = STX;
/* Define complete telegrams for sending */
struct{
unsigned char telegram_header[HEADER_SIZE];
unsigned char telegram[MAX_SIZE_DATA_BLOCK*2 + NUMBER_OF_STOP_CHAR];
}sendbuffer;
struct{
unsigned char telegram_header[FOLLOW_ON_HEADER_SIZE];
unsigned char telegram[MAX_SIZE_DATA_BLOCK*2 + NUMBER_OF_STOP_CHAR];
}follow_on_sendbuffer;
do /* Send 128 byte telegrams until message is finished */
{
if ( !follow_on )
{
A_telegram = TRUE;
/*************************************************************************/
/** Send A-telegram. **/
/*************************************************************************/
/** Check if follow on telegrams are needed. **/
/*************************************************************************/
if ( buf_size - pos_counter > MAX_SIZE_DATA_BLOCK )
{
delta_pos = MAX_SIZE_DATA_BLOCK;
follow_on = TRUE;
}
else
{
delta_pos = buf_size - pos_counter;
}
/*************************************************************************/
/** Calculate the size of the A-telegram. **/
/*************************************************************************/
/* Count DLE characters */
for ( i=0 ; i<delta_pos ; i++ )
{
if ( *buf++ == DLE )
number_of_DLE += 1;
}
size_of_telegram = HEADER_SIZE+
delta_pos+number_of_DLE+NUMBER_OF_STOP_CHAR;
/*************************************************************************/
/** Fill in the telegram header and calculate BCC. **/
/*************************************************************************/
/* Size have to be expressed in number of 16 bits words. */
/* If odd number of bytes add one. */
datasize = buf_size/2 + buf_size%2;
datasize_low_byte = (unsigned char)(BYTE_MASK & datasize);
datasize = datasize >> 8;
datasize_high_byte = (unsigned char)(BYTE_MASK & datasize);
cpu_number = (unsigned char)remtrans->Address[2];
CPU = '\xFF';
CPU = CPU_NR_MASK & cpu_number;
sendbuffer.telegram_header[0] = '\0';
sendbuffer.telegram_header[1] = '\0';
sendbuffer.telegram_header[2] = 'A';
sendbuffer.telegram_header[3] = 'D';
sendbuffer.telegram_header[4] = (unsigned char)remtrans->Address[0];
sendbuffer.telegram_header[5] = (unsigned char)remtrans->Address[1];
sendbuffer.telegram_header[6] = datasize_high_byte;
sendbuffer.telegram_header[7] = datasize_low_byte;
sendbuffer.telegram_header[8] = '\xFF';
sendbuffer.telegram_header[9] = CPU;
/* Calculate checksum for the header */
for ( i=0 ; i<HEADER_SIZE ; i++ )
{
BCC ^= sendbuffer.telegram_header[i];
}
/*************************************************************************/
/** Fill up A-telegram with contents of message and calculate BCC **/
/*************************************************************************/
buf = restore_buf_ptr;
for ( i=0 ; i<(delta_pos+number_of_DLE) ; i++ )
{
ch = sendbuffer.telegram[i] = *buf++;
BCC ^= ch;
if ( ch == DLE )
{
sendbuffer.telegram[++i] = DLE;
BCC ^= ch;
}
}
if ( delta_pos%2 )
{
/* Ensure that a even number of bytes is treated */
sendbuffer.telegram[i++] = '\0';
size_of_telegram += 1;
}
sendbuffer.telegram[i++] = DLE;
sendbuffer.telegram[i++] = ETX;
sendbuffer.telegram[i] = BCC;
pos_counter = delta_pos;
}
else /* follow on telegram */
{
/*************************************************************************/
/** Send follow on telegram. **/
/*************************************************************************/
/** Check if more follow on telegrams are needed. **/
/*************************************************************************/
if ( buf_size - pos_counter > MAX_SIZE_DATA_BLOCK )
{
delta_pos = MAX_SIZE_DATA_BLOCK;
follow_on = TRUE;
}
else
{
delta_pos = buf_size - pos_counter;
follow_on = FALSE;
}
/*************************************************************************/
/** Calculate the size of the follow on telegram. **/
/*************************************************************************/
/* Count DLE characters */
restore_buf_ptr = buf;
number_of_DLE = 0;
for ( i=0 ; i<delta_pos ; i++ )
{
if ( *buf++ == DLE )
number_of_DLE += 1;
}
size_of_telegram = FOLLOW_ON_HEADER_SIZE+
delta_pos+number_of_DLE+NUMBER_OF_STOP_CHAR;
/*************************************************************************/
/** Fill in the follow on telegram header and calculate BCC. **/
/*************************************************************************/
follow_on_sendbuffer.telegram_header[0] = '\xFF';
follow_on_sendbuffer.telegram_header[1] = '\0';
follow_on_sendbuffer.telegram_header[2] = 'A';
follow_on_sendbuffer.telegram_header[3] = 'D';
/* Calculate checksum for the header */
BCC = DLE ^ ETX;
for ( i=0 ; i<FOLLOW_ON_HEADER_SIZE ; i++ )
{
BCC ^= follow_on_sendbuffer.telegram_header[i];
}
/*************************************************************************/
/* Fill up follow on telegram with contents of message and calculate BCC */
/*************************************************************************/
buf = restore_buf_ptr;
for ( i = 0 ; i < (delta_pos+number_of_DLE) ; i++ )
{
ch = follow_on_sendbuffer.telegram[i] = *buf++;
BCC ^= ch;
if ( ch == DLE )
{
follow_on_sendbuffer.telegram[++i] = DLE;
BCC ^= ch;
}
}
if ( delta_pos%2 )
{
/* Ensure that a even number of bytes is treated */
follow_on_sendbuffer.telegram[i++] = '\0';
size_of_telegram += 1;
}
follow_on_sendbuffer.telegram[i++] = DLE;
follow_on_sendbuffer.telegram[i++] = ETX;
follow_on_sendbuffer.telegram[i] = BCC;
pos_counter += delta_pos;
}
/*************************************************************************/
/** Execute the send procedure **/
/*************************************************************************/
/* Send STX and wait for answer */
eln$tty_write(&sts, &virtual_serial_line_port, 1, &sstx,
&nbr_of_bytes_written, &write_message, &write_message_buf);
if ( ODD(sts) )
{
/* wait for break character or timeout */
eln$tty_read(&sts, &virtual_serial_line_port, 1, &received_char,
&nbr_of_bytes_read, (2+4), &DLE_mask, &timeout_ack,
NULL, NULL, &read_message, &read_message_buf);
}
if ( ODD(sts) && (sts != ELN$_TIMEOUT) )
{
if ( received_char == STX )
{
/* Both nodes is in sending mode. */
/* Cancel this send operation and wait for next timeout or receive */
eln$tty_write(&sts, &virtual_serial_line_port, 1, &snak,
&nbr_of_bytes_written, &write_message, &write_message_buf);
return(FALSE);
}
if ( received_char == DLE )
{
/* Contact is established. Send telegram */
if ( A_telegram )
{
eln$tty_write(&sts, &virtual_serial_line_port, size_of_telegram,
&sendbuffer,
&nbr_of_bytes_written, &write_message, &write_message_buf);
A_telegram = FALSE;
}
else
{
eln$tty_write(&sts, &virtual_serial_line_port, size_of_telegram,
&follow_on_sendbuffer,
&nbr_of_bytes_written, &write_message, &write_message_buf);
}
if ( ODD(sts) )
{
/* wait for break character or timeout */
eln$tty_read(&sts, &virtual_serial_line_port, 1, &received_char,
&nbr_of_bytes_read, (2+4), &DLE_mask, &timeout_ack,
NULL, NULL, &read_message, &read_message_buf);
if ( ODD(sts)&&(sts != ELN$_TIMEOUT)&&(received_char == DLE) )
{
/*************************************************************************/
/** The sending was a SUCCESS. Take care of the response message **/
/*************************************************************************/
eln$tty_read(&sts, &virtual_serial_line_port, 1,
&received_char, &nbr_of_bytes_read, (2+4),
&STX_mask, &timeout_resp, NULL, NULL,
&read_message, &read_message_buf);
if ( ODD(sts)&&(sts != ELN$_TIMEOUT)&&(received_char == STX) )
{
/* Send DLE acknowledge and wait for response data */
eln$tty_write(&sts, &virtual_serial_line_port, 1, &sdle,
&nbr_of_bytes_written, &write_message, &write_message_buf);
if ( ODD(sts) )
{
BCC = '\0';
for (i=0 ;
i<RESP_MESSAGE_SIZE&&ODD(sts)&&(sts!=ELN$_TIMEOUT);
i++ )
{
eln$tty_read(&sts, &virtual_serial_line_port, 1,
&received_char, &nbr_of_bytes_read, 2,
NULL, &timeout_char,
NULL, NULL, &read_message, &read_message_buf);
response_buffer[i] = received_char;
BCC ^= received_char;
} /* endfor */
if ( ODD(sts) &&
(sts != ELN$_TIMEOUT) &&
(response_buffer[2] == '\0') )
{
/* Compare received BCC with calculated */
eln$tty_read(&sts, &virtual_serial_line_port,
1, &received_char, &nbr_of_bytes_read, 2,
NULL, &timeout_char,
NULL, NULL, &read_message, &read_message_buf);
if ( ODD(sts) &&
(sts != ELN$_TIMEOUT) &&
( BCC == received_char ) )
{
/* Response telegram received OK */
eln$tty_write(&sts, &virtual_serial_line_port, 1, &sdle,
&nbr_of_bytes_written, &write_message, &write_message_buf);
if ( response_buffer[3] != 0 )
{
/* This response contains a error code */
errh_CErrLog(REM__SIEMENSERROR,
errh_ErrArgL(response_buffer[3]) );
}
}
else
{
/* Wrong checksum. */
sts = FALSE;
}
}
else
{
/* This is not a response message as expected */
eln$tty_write(&sts, &virtual_serial_line_port, 1, &snak,
&nbr_of_bytes_written, &write_message, &write_message_buf);
sts = FALSE;
}
} /* ENDIF. DLE acknowledge failed */
}
else
{
/* STX character in response message was expected. */
/* Ensure that error status is returned */
sts = FALSE;
}
}
else
{
/* DLE ack. after sending telegram was expected. */
/* Ensure that error status is returned */
sts = FALSE;
}
} /* ENDIF. Contact established but tty_write failed */
}
else
{
/* Failed in making contact. Wrong response character. */
/* Ensure that error status is returned */
sts = FALSE;
}
} /* ENDIF. tty_write or tty_read failed */
/*************************************************************************/
/** Check final status. **/
/*************************************************************************/
if ( EVEN(sts) || (sts == ELN$_TIMEOUT) )
{
/* The send procedure has failed */
eln$tty_write(&sts, &virtual_serial_line_port, 1, &snak,
&nbr_of_bytes_written, &write_message, &write_message_buf);
follow_on = FALSE;
/* Ensure that error status is returned */
sts = FALSE;
}
}while( follow_on );
return(sts);
}
/*************************************************************************
**************************************************************************
*
* Namn : Receive
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Waits for STX on serial line
*
**************************************************************************
**************************************************************************/
static unsigned int Receive()
{
unsigned int sts, wait_result;
unsigned char received_char = NUL;
DDA$_BREAK_MASK DLE_mask = DLE;
unsigned int nbr_of_bytes_read = 0;
unsigned int nbr_of_bytes_written = 0;
static unsigned char snak[2] = {NAK, NUL};
eln$tty_read(&sts, &virtual_serial_line_port, 1,
&received_char, &nbr_of_bytes_read, (2+4), &DLE_mask,
&timeout_cycle, NULL, NULL, &read_message, &read_message_buf);
if (sts == ELN$_SUCCESS)
{
if (received_char == STX)
{
sts = ReceiveHandler();
while ( ODD(sts) && telegram_counter )
{
/* Follow on telegrams are expected */
received_char = NUL;
eln$tty_read(&sts, &virtual_serial_line_port, 1,
&received_char, &nbr_of_bytes_read, (2+4), &DLE_mask,
&timeout_ack, NULL, NULL, &read_message, &read_message_buf);
if (sts == ELN$_SUCCESS && received_char == STX)
{
sts = ReceiveHandler();
}
else
{
sts = FALSE;
}
} /* endwhile */
}
else
{
/* We don't understand, Send NAK unless NAK is received */
if (received_char != NAK)
eln$tty_write(&sts, &virtual_serial_line_port, 1, &snak,
&nbr_of_bytes_written, &write_message, &write_message_buf);
}
}
if ( EVEN(sts) )
{
remnode->objp->ErrTransCount++;
telegram_counter = 0;
eln$tty_write(&sts, &virtual_serial_line_port, 1, &snak,
&nbr_of_bytes_written, &write_message, &write_message_buf);
}
return(1);
}
/*************************************************************************
**************************************************************************
*
* Namn : ReceiveHandler
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Invoked when a telegram is received.
*
**************************************************************************
**************************************************************************/
static unsigned int ReceiveHandler()
{
unsigned int sts, i;
unsigned int delta_pos = 0;
unsigned int nbr_of_bytes_written = 0;
unsigned int nbr_of_bytes_read = 0;
static unsigned int datasize, pos_counter;
static remtrans_item *remtrans;
char search_remtrans = FALSE;
char send_response = FALSE;
char terminate = FALSE;
unsigned char CODE = '\0';
unsigned char BCC = '\0';
unsigned char char_buffer, BCC_checksum;
unsigned char received_char = '\0';
unsigned char ReceiveBuffer[MAX_SIZE_TELEGRAM];
unsigned char *ReceiveBuffer_ptr;
unsigned char sstx[2] = {STX, '\0'};
unsigned char sdle[2] = {DLE, '\0'};
unsigned char snak[2] = {NAK, '\0'};
static unsigned char *TelegramBuffer;
static unsigned char *TelegramBuffer_ptr;
DDA$_BREAK_MASK DLE_mask = DLE;
DDA$_BREAK_MASK STX_mask = STX;
/*************************************************************************/
/** We have received STX earlier, send DLE to responde **/
/*************************************************************************/
/* Send acknowledge ready to receive message */
eln$tty_write(&sts, &virtual_serial_line_port, 1, &sdle,
&nbr_of_bytes_written, &write_message, &write_message_buf);
if ( EVEN(sts) )
return(FALSE);
/*************************************************************************/
/** Store the received telegram temporary **/
/*************************************************************************/
eln$tty_read(&sts, &virtual_serial_line_port, 1, &received_char,
&nbr_of_bytes_read, 2, NULL, &timeout_char,
NULL, NULL, &read_message, &read_message_buf);
if ( EVEN(sts) || (sts == ELN$_TIMEOUT) )
return(FALSE);
ReceiveBuffer[0] = char_buffer = received_char;
BCC ^= received_char;
for ( i=1 ; (terminate==FALSE)&&(i<MAX_SIZE_TELEGRAM) ; i++ )
{
eln$tty_read(&sts, &virtual_serial_line_port, 1, &received_char,
&nbr_of_bytes_read, 2, NULL, &timeout_char,
NULL, NULL, &read_message, &read_message_buf);
if ( EVEN(sts) || (sts == ELN$_TIMEOUT) )
return(FALSE);
if ( (char_buffer == DLE) && (received_char == ETX) )
{
/* End of message. Read checksum and terminate. */
ReceiveBuffer[i] = received_char;
BCC ^= received_char;
eln$tty_read(&sts, &virtual_serial_line_port, 1, &received_char,
&nbr_of_bytes_read, 2, NULL, &timeout_char,
NULL, NULL, &read_message, &read_message_buf);
if ( EVEN(sts) || (sts == ELN$_TIMEOUT) )
return(FALSE);
BCC_checksum = received_char;
terminate = TRUE;
}
else
{
/* Store one more received character in the buffer */
BCC ^= received_char;
if ( (received_char != DLE) ||
((received_char == DLE) && (char_buffer != DLE)) )
{
ReceiveBuffer[i] = char_buffer = received_char;
}
else
{
/* This is a duplicated DLE character. Throw away. */
i--;
char_buffer = '\0';
}
}
} /* endfor */
/*************************************************************************/
/** A complete message is received. Check BCC. **/
/*************************************************************************/
if ( BCC == BCC_checksum )
{
eln$tty_write(&sts, &virtual_serial_line_port, 1, &sdle,
&nbr_of_bytes_written, &write_message, &write_message_buf);
if ( EVEN(sts) )
return(FALSE);
}
else
{
/* Checksum in this telegram is wrong */
return(FALSE);
}
if ( !telegram_counter && (ReceiveBuffer[0] == 0X00) )
{
/*************************************************************************/
/** This is a ordinary A-telegram. Make some error checks and treat it. */
/*************************************************************************/
/* Find out wich RemTrans object that is the target.*/
search_remtrans = true;
remtrans = remnode->remtrans;
while(remtrans && search_remtrans)
{
if ( (remtrans->objp->Address[0] == ReceiveBuffer[4]) &&
(remtrans->objp->Direction == REMTRANS_IN) )
{
search_remtrans = false;
}
if ( search_remtrans )
{
remtrans = (remtrans_item *) remtrans->next;
}
} /* endwhile */
if (search_remtrans)
{
/* No corresponding RemTrans object found */
remnode->objp->ErrTransCount++;
CODE = '\x0A';
}
if ( !CODE )
{
/* Allowed type of telegram ? */
if ( ReceiveBuffer[2] != 'A' )
CODE = '\x16';
}
if ( !CODE )
{
/* Allowed type of data ? */
if ( ReceiveBuffer[3] != 'D' )
CODE = '\x10';
}
if ( !CODE )
{
/* Check size of received message */
datasize = (unsigned int)ReceiveBuffer[6];
datasize = datasize << 8;
datasize = datasize | (unsigned int)ReceiveBuffer[7];
datasize = datasize * 2; /* Convert from 16 bit words to bytes */
if ( datasize <= remtrans->objp->MaxLength)
{
if (datasize > 128) telegram_counter = (datasize-1)/128;
}
else
{
/* Size of received message is to big */
remtrans->objp->ErrCount++;
CODE = '\x34';
}
}
if ( telegram_counter && !CODE )
{
/* Follow on telegrams are expected, allocate more memory */
TelegramBuffer = malloc(datasize);
TelegramBuffer_ptr = TelegramBuffer;
/* Temporary store this telegram */
for ( i = HEADER_SIZE ;
i < (HEADER_SIZE + MAX_SIZE_DATA_BLOCK) ;
i++ )
{
*TelegramBuffer_ptr++ = ReceiveBuffer[i];
}
pos_counter = MAX_SIZE_DATA_BLOCK;
}
else
if ( !CODE )
{
/* This message contains only one telegram. Treat it! */
ReceiveBuffer_ptr = &ReceiveBuffer[HEADER_SIZE];
sts = RemTrans_Receive(remtrans,
ReceiveBuffer_ptr,
datasize);
if ( EVEN(sts) )
{
remtrans->objp->ErrCount++;
return(1);
}
}
}
else
{
if ( !telegram_counter )
/* Wrong type of telegram received when A-telegram was expected */
{
remnode->objp->ErrTransCount++;
CODE = '\x10';
}
}
if ( telegram_counter && (ReceiveBuffer[0] == 0XFF) && !CODE )
{
/*************************************************************************/
/** This is a follow on telegram. Make some error checks and treat it. **/
/*************************************************************************/
if ( !CODE )
{
/* Allowed type of telegram ? */
if ( ReceiveBuffer[2] != 'A' )
CODE = '\x16';
}
if ( !CODE )
{
/* Allowed type of data ? */
if ( ReceiveBuffer[3] != 'D' )
CODE = '\x10';
}
if ( !CODE )
{
if ( datasize - pos_counter > MAX_SIZE_DATA_BLOCK )
{
delta_pos = MAX_SIZE_DATA_BLOCK;
}
else
{
delta_pos = datasize - pos_counter;
}
for ( i = FOLLOW_ON_HEADER_SIZE ;
i < (FOLLOW_ON_HEADER_SIZE + delta_pos) ;
i++ )
{
*TelegramBuffer_ptr++ = ReceiveBuffer[i];
}
telegram_counter -= 1;
pos_counter += delta_pos;
if ( !telegram_counter )
{
/* This was the last follow on telegram. Treat the message */
if ( pos_counter != datasize )
{
/* Wrong number of characters counted */
free(TelegramBuffer);
remtrans->objp->ErrCount++;
return(1);
}
TelegramBuffer_ptr = TelegramBuffer;
sts = RemTrans_Receive(remtrans,
TelegramBuffer_ptr,
datasize);
free(TelegramBuffer);
if ( EVEN(sts) )
{
remtrans->objp->ErrCount++;
return(1);
}
}
}
}
else
{
if ( telegram_counter && !CODE )
/* Wrong type of telegram received when follow on was expected */
{
free(TelegramBuffer);
telegram_counter = 0;
remtrans->objp->ErrCount++;
CODE = '\x10';
}
}
sts = SendResponseTelegram(CODE);
if ( EVEN(sts) || (sts == ELN$_TIMEOUT) )
{
/* A fail has occured when sending response telegram */
return(FALSE);
}
else
{
return(TRUE);
}
}
/*************************************************************************
**************************************************************************
*
* Namn : SendResponseTelegram
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Invoked when a response telegram is to be sent.
*
**************************************************************************
**************************************************************************/
int SendResponseTelegram(unsigned char CODE)
{
unsigned int sts;
unsigned int nbr_of_bytes_written = 0;
unsigned int nbr_of_bytes_read = 0;
unsigned char received_char = '\0';
unsigned char BCC = '\0';
unsigned char ResponseTelegram[RESP_MESSAGE_SIZE+1];
unsigned char sstx[2] = {STX, '\0'};
unsigned char sdle[2] = {DLE, '\0'};
DDA$_BREAK_MASK DLE_mask = DLE;
DDA$_BREAK_MASK STX_mask = STX;
BCC = DLE ^ ETX;
BCC ^= CODE;
ResponseTelegram[0] = '\0';
ResponseTelegram[1] = '\0';
ResponseTelegram[2] = '\0';
ResponseTelegram[3] = CODE;
ResponseTelegram[4] = DLE;
ResponseTelegram[5] = ETX;
ResponseTelegram[6] = BCC;
/* Send STX and wait for answer */
eln$tty_write(&sts, &virtual_serial_line_port, 1,
&sstx, &nbr_of_bytes_written, &write_message, &write_message_buf);
if ( ODD(sts) )
{
/* wait for break character or timeout */
eln$tty_read(&sts, &virtual_serial_line_port, 1, &received_char,
&nbr_of_bytes_read, (2+4), &DLE_mask, &timeout_ack,
NULL, NULL, &read_message, &read_message_buf);
if ( ODD(sts) && (sts != ELN$_TIMEOUT) && (received_char == DLE) )
{
/* Contact is established. Send response telegram */
eln$tty_write(&sts, &virtual_serial_line_port,
sizeof(ResponseTelegram), &ResponseTelegram,
&nbr_of_bytes_written, &write_message, &write_message_buf);
if ( ODD(sts) )
{
/* wait for break character or timeout */
eln$tty_read(&sts, &virtual_serial_line_port, 1,
&received_char, &nbr_of_bytes_read, (2+4), &DLE_mask,
&timeout_ack, NULL, NULL, &read_message, &read_message_buf);
if ( EVEN(sts) || (sts == ELN$_TIMEOUT) || (received_char != DLE) )
{
/* DLE character in response was expected. */
sts = FALSE;
}
} /* ENDIF. Contact established but tty_write failed */
}
else
{
/* Failed in making contact. DLE in response was expected. */
sts = FALSE;
}
} /* ENDIF. tty_write failed when sending STX */
return(sts);
}
#ifdef OS_ELN
/*************************************************************************
**************************************************************************
*
* Namn : WaitFor_PLC_Change
*
* Typ : int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Subprocess waits for message from REMOTEHANDLER on job_port,
* that will kill transport when switch is done.
*
**************************************************************************
**************************************************************************/
int WaitFor_PLC_Change()
{
pwr_tStatus sts;
MESSAGE msg_id;
char *mess;
int size;
while (TRUE) {
ker$wait_any(&sts, NULL, NULL, &job_port);
ker$receive(&sts, &msg_id, &mess, &size, &job_port, NULL, NULL);
if (*mess == 1){
/* Hot switch init. Do nothing but delete the message */
ker$delete(&sts, msg_id);
}
else if (*mess == 2){
/* Switch is done. Execute harakiri! */
ker$delete(&sts, msg_id); /* Delete message */
exith();
ker$delete(&sts, my_proc);
}
else {
printf("Fel telegram PLC-byte %%x%x\n",*mess);
ker$delete(&sts, msg_id);
}
}
}
#endif
/*
* Main routine
*/
main(int argc, char *argv[])
{
unsigned int sts, i; /* Status from function calls etc. */
pwr_tObjid pwr_node; /* Own Pwr node */
pwr_sClass_PlcProcess *pwr_nodep; /* Ref to own Pwr node */
pwr_tTime OriginChgTime; /* LastChgTime at start */
pwr_tClassId remnode_class; /* Vr remnod's class */
#ifdef OS_ELN
PROCESS id_p;
static struct dsc$descriptor_s name_desc = {0, DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
NAME name_id;
/* Get process-id to be able to kill myself.
Create subprocess to kill or to signal switch. */
ker$job_port(&sts, &job_port);
ker$current_process(&sts, &my_proc);
/* Create a name for my own process (first process in job) */
name_desc.dsc$a_pointer = argv[3];
name_desc.dsc$w_length = strlen(argv[3]);
ker$create_name(&sts, &name_id, &name_desc, my_proc, NULL);
ker$create_process( &sts, &id_p, WaitFor_PLC_Change,NULL);
#endif
DeclareExitHandler();
sts = gdh_Init("rs_remote_rk512");
if (EVEN(sts)) exit(sts);
/* Hmta remnodens objid frn argumentvektorn */
if (argc >= 3)
{
sts = cdh_StringToObjid( argv[2], &remnode->objid);
if (EVEN(sts)) exit(sts);
}
else
remnode->objid = pwr_cNObjid;
/* Kontrollera att objektet verkligen r en remnod */
sts = gdh_GetObjectClass(remnode->objid, &remnode_class);
if (EVEN(sts)) exit(sts);
if (remnode_class != pwr_cClass_RemNode) exit(0);
/* Hmta en pekare till remnoden */
sts = gdh_ObjidToPointer(remnode->objid, (pwr_tAddress *) &remnode->objp);
if (EVEN(sts)) exit(sts);
/* Kontrollera att det r rtt transport */
if (remnode->objp->TransportType != REMNODE_TRANSPORT_RK512) exit(0);
remnode->Time_since_scan = 0;
remnode->Time_since_poll = 0;
remnode->Time_since_IO = 0;
remnode->Time_since_send = 0;
/* Initialize remtrans objects */
sts = RemTrans_Init(remnode, 0);
if (EVEN(sts)) exit(sts);
/* Get pointer to $Node-object */
sts = gdh_GetClassList( pwr_cClass_PlcProcess, &pwr_node);
sts = gdh_ObjidToPointer(pwr_node, (pwr_tAddress *) &pwr_nodep);
/* Initialize device */
sts = InitNet();
if (EVEN(sts)) exit(sts);
/* Initialize timers */
sts = InitTimers();
if (EVEN(sts)) exit(sts);
/* Loop forever */
while (!doomsday)
{
sts = Receive();
if (EVEN(sts)) exit(sts);
remnode->Time_since_send += remnode->objp->CycleTime;
sts = RemTrans_Cyclic(remnode, &remnode_send);
}
}
include $(pwre_dir_symbols)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(hw_name)/$(type_name)_generic.mk
ifeq ($($(type_name)_generic_mk),)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(type_name)_generic.mk
endif
ifeq ($($(type_name)_generic_mk),)
include $(pwre_kroot)/tools/bld/src/$(type_name)_generic.mk
endif
ifndef link_rule_mk
link_rule_mk := 1
link = $(ldxx) $(elinkflags) $(domap) -o $(export_exe) \
$(export_obj) $(objects) $(rt_msg_eobjs) \
-lpwr_remote -lpwr_rt -lpwr_co -lpwr_msg_dummy -lpthread -lm
endif
/*
* Proview $Id: rs_remote_serial.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*************************************************************************
*
* S E R I A L
* ===========
**************************************************************************
*
* Filename: remote_serial.c unified serial driver for lynx/linux
*
* Date Pgm. Read. Remark
* Modified 980610 CJu - -
* Modified 010426 ulflj - for lynx
* 010814 ulflj - fixed for pwr 3.3a
* 020530 ulflj - modified serial parameter read
* in lynx version
* 021219 ulflj - fixed tv_timeout in recive()
* 040528 CJu - v4.0.0
*
* Description: Implements remote transport process for a general
* serial communications able to read and write ASCII
* messages. Termination sequence for read is
* configured in Remnode object.
*
*
**************************************************************************
**************************************************************************/
/*_Include files_________________________________________________________*/
/*LynxOS system includes*/
#include <time.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
//#include <uio.h>
#include <termios.h>
#include <termio.h>
#include <sgtty.h>
#include <sys/ioctl.h>
//#include <ioctl.h>
/*PWR includes*/
#include "pwr_class.h"
#include "pwr_systemclasses.h"
#include "remote_mq.h"
#include "co_cdh.h"
#include "rt_gdh.h"
#include "rt_aproc.h"
#include "rt_pwr_msg.h"
#include "pwr_baseclasses.h"
#include "pwr_remoteclasses.h"
#include "remote.h"
#include "remote_utils.h"
#include "remote_remtrans_utils.h"
#include "pwr.h"
#include "rt_gdh.h"
#include "rt_gdh_msg.h"
#include "rt_plc_utl.h"
#include "rt_errh.h"
#include "co_time.h"
/*_variables_______________________________________________________________*/
remnode_item rn;
pwr_sClass_RemnodeSerial *rn_serial;
int ser_fd; /* file domininator for serial port */
unsigned char debug=0; /* 1 if debug mode activated */
float time_since_scan;
float time_since_rcv;
void load_timeval(struct timeval *tv, float t)
{
tv->tv_sec = t;
tv->tv_usec = (t-(float)tv->tv_sec) * 1000000;
}
/*************************************************************************
**************************************************************************
*
* Namn : remnode_send
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends a RemTrans message to Remote node
*
**************************************************************************
**************************************************************************/
static unsigned int remnode_send(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buffer_size)
{
int sts;
/*************************************************************************/
/** Execute the send procedure **/
/*************************************************************************/
//printf("sending\n");
//printf("telegram:%s,%i\n",buf,buffer_size);
sts=write(ser_fd, buf, buffer_size); //write returnerar antalet skrivna tecken
if(sts != buffer_size)
{
errh_Error("Sndfel, %d", sts);
return(STATUS_FELSEND); //jmna returns vvisar p fel i VMS
}
else
return (STATUS_OK);
}
/*************************************************************************
**************************************************************************
*
* Namn : Receive
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Waits for message on serial line
*
**************************************************************************
**************************************************************************/
static unsigned int Receive()
{
int sts;
int nbr_of_bytes_read = 0;
unsigned char telegram[512];
char search_remtrans = FALSE;
remtrans_item *remtrans;
fd_set read_fd;
struct timeval tv;
load_timeval(&tv, rn_serial->ScanTime);
nbr_of_bytes_read = 0;
telegram[nbr_of_bytes_read] = 0;
sts = 0;
while (nbr_of_bytes_read < sizeof(telegram)-2)
{
// Om vi r under mottagning, vnta tills lstimeout
if (nbr_of_bytes_read > 0) load_timeval(&tv, rn_serial->ReadTimeout);
FD_ZERO(&read_fd);
FD_SET(ser_fd, &read_fd);
sts = select(ser_fd+1, &read_fd, NULL, NULL, &tv);
if (sts > 0) { // Tecken finns att lsa
sts = read(ser_fd, &telegram[nbr_of_bytes_read], 1);
if(sts > 0) {
nbr_of_bytes_read++;
if (telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[0] ||
telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[1] ||
telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[2] ||
telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[3] ||
telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[4] ||
telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[5] ||
telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[6] ||
telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[7] )
break;
}
else { // Lsfel
rn_serial->ErrCount++;
break;
}
}
else { // Timeout
break;
}
}
if (nbr_of_bytes_read > 0) // Vi tog emot ett eller flera tecken
{
telegram[nbr_of_bytes_read] = 0;
if (debug)
{
printf("Vi tog emot en trans med terminering 0x%x\n", telegram[nbr_of_bytes_read-1]);
printf("Telegramet var:%s\n", telegram);
}
search_remtrans = true;
remtrans = rn.remtrans;
while (remtrans && search_remtrans)
{
if (remtrans->objp->Direction == REMTRANS_IN )
search_remtrans = false;
if ( search_remtrans ) remtrans = (remtrans_item *) remtrans->next;
} /* endwhile */
if ( !search_remtrans )
{
sts = RemTrans_Receive(remtrans, telegram, nbr_of_bytes_read);
if ( EVEN(sts) )
{
remtrans->objp->ErrCount++;
return (FALSE);
}
}
if (search_remtrans)
{
/* No corresponding RemTrans object found */
rn_serial->ErrCount++;
return (FALSE);
}
}
return(1);
}
/***************************************************
***************** Main routine ****************
***************************************************/
int main(int argc, char *argv[])
{
unsigned int sts; /* Status from function calls etc. */
unsigned char id[32];
unsigned char pname[32];
remtrans_item *remtrans;
int i;
/* Read arg number 2, should be id for this instance */
if (argc >= 2)
strcpy(id, argv[1]);
else
strcpy(id, "0");
/* Build process name with id */
sprintf((char *) pname, "rs_remser_%s", id);
/* Init of errh */
errh_Init((char *) pname, errh_eAnix_remote);
errh_SetStatus(PWR__SRVSTARTUP);
/* Set debug mode if arg number 4 is "debug" (started manually) */
debug = 0;
if (argc >= 4) {
if (!strncmp(argv[3],"debug",5)) debug = 1;
}
if (debug) printf("debugmode valt\n");
/* Init of gdh */
sts = gdh_Init((char *) pname);
if ( EVEN(sts)) {
errh_Error("gdh_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Arg number 3 should be my remnodes objid in string representation,
read it, convert to real objid and store in remnode_item */
sts = 0;
if (argc >= 3) sts = cdh_StringToObjid(argv[2], &rn.objid);
if ( EVEN(sts)) {
errh_Error("cdh_StringToObjid, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Get pointer to RemnodeSerial object and store locally */
sts = gdh_ObjidToPointer(rn.objid, (pwr_tAddress *) &rn_serial);
if ( EVEN(sts)) {
errh_Error("cdh_ObjidToPointer, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Initialize some internal data and make standard remtrans init */
rn.next = NULL;
rn.local = NULL; // We dont use local structure since we only have one remnode
rn.retransmit_time = 10.0; // Not used, but initialize anyway
rn_serial->ErrCount = 0;
sts = RemTrans_Init(&rn);
if ( EVEN(sts)) {
errh_Error("RemTrans_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
time_since_scan = 0;
time_since_rcv = 0;
/* Store remtrans objects objid in remnode_serial object */
remtrans = rn.remtrans;
i = 0;
while(remtrans) {
rn_serial->RemTransObjects[i++] = remtrans->objid;
if ( i >= (int)(sizeof(rn_serial->RemTransObjects)/sizeof(rn_serial->RemTransObjects[0])))
break;
remtrans = (remtrans_item *) remtrans->next;
}
/* Initialize device */
ser_fd = RemUtils_InitSerialDev(rn_serial->DevName,
rn_serial->Speed,
rn_serial->DataBits,
rn_serial->StopBits,
rn_serial->Parity);
if (!ser_fd) {
errh_Error("InitDev, %d", ser_fd);
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
/* Loop forever */
while (1)
{
if (rn_serial->Disable == 1) {
errh_Fatal("Disabled, exiting");
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
sts = Receive();
sts = RemTrans_Cyclic(&rn, &remnode_send);
}
}
include $(pwre_dir_symbols)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(hw_name)/$(type_name)_generic.mk
ifeq ($($(type_name)_generic_mk),)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(type_name)_generic.mk
endif
ifeq ($($(type_name)_generic_mk),)
include $(pwre_kroot)/tools/bld/src/$(type_name)_generic.mk
endif
ifndef link_rule_mk
link_rule_mk := 1
link = $(ldxx) $(elinkflags) $(domap) -o $(export_exe) \
$(export_obj) $(objects) $(rt_msg_eobjs) \
-lpwr_remote -lpwr_rt -lpwr_co -lpwr_msg_dummy -lpthread -lrt -lm
endif
/*
* Proview $Id: rs_remote_tcpip.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*************************************************************************
* ===============
* P r o v i e w
* ===============
**************************************************************************
*
* Filename: rs_remote_tcpip.c
*
* Date Pgm. Read. Remark
* Modified 040108 CJu
*
* Description: Remote transport process TCP/IP
* Implements transport protocol TCP/IP, connection oriented
* protocol on the IP-stack.
*
**************************************************************************
**************************************************************************/
/*_Include files_________________________________________________________*/
#include <stdio.h>
#include <errno.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include "pwr_class.h"
#include "pwrs_c_node.h"
#include "rt_gdh.h"
#include "co_cdh.h"
#include "rt_errh.h"
#include "pwr_baseclasses.h"
#include "pwr_remoteclasses.h"
#include "rt_pwr_msg.h"
#include "rt_aproc.h"
#include "remote.h"
#include "remote_remtrans_utils.h"
//#define debug 0
#define STX 2
#define ETB 15
#define TCP_MAX_SIZE 32768
#define TIME_INCR 0.02
int debug=0;
fd_set fdr; /* For select call */
fd_set fde; /* For select call */
typedef struct
{
unsigned char protocol_id[2];
short int msg_size;
short int msg_id[2];
} remote_tcp_header;
remnode_item rn;
pwr_sClass_RemnodeTCP *rn_tcp;
float time_since_scan;
float time_since_rcv;
float time_since_keepalive;
char receive_buffer[65536];
unsigned char remote_tcp_id[2] = {STX, ETB};
int l_socket; /* Local socket */
int c_socket; /* The connected socket */
struct sockaddr_in l_addr; /* Local named socket description */
struct sockaddr_in r_addr; /* Remote socket description */
enum cs_modes {TCP_CLIENT, TCP_SERVER} cs_mode;
/*************************************************************************
**************************************************************************
*
* Namn : RemoteSleep
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning :
*
**************************************************************************
**************************************************************************/
void RemoteSleep(float time)
{
#ifdef OS_VMS
int sts;
sts = lib$wait(&time);
#elif OS_ELN
LARGE_INTEGER l_time;
l_time.high = -1;
l_time.low = - time * 10000000;
ker$wait_any(NULL, NULL, &l_time);
#elif defined(OS_LYNX) || defined(OS_LINUX)
struct timespec rqtp, rmtp;
rqtp.tv_sec = 0;
rqtp.tv_nsec = time * 1000000000;
if (time >= 1.0) {
rqtp.tv_sec = time/1;
rqtp.tv_nsec = 0;
}
else {
rqtp.tv_nsec = time * 1000000000;
}
nanosleep(&rqtp, &rmtp);
#endif
return;
}
/*************************************************************************
**************************************************************************
*
* Namn : CreateSocket
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Creates socket and sets remote side addresses
*
*
**************************************************************************
**************************************************************************/
int CreateSocket()
{
int sts;
if (cs_mode == TCP_CLIENT) {
/* Create a socket for TCP */
c_socket = socket(AF_INET, SOCK_STREAM, 0);
if (debug) printf("socket: %d\n", c_socket);
if (debug && (c_socket < 0)) perror("socket");
if (c_socket < 0) return(-1);
/* Bind the created socket */
if (rn_tcp->LocalPort != 0) {
l_addr.sin_family = AF_INET;
l_addr.sin_port = htons(rn_tcp->LocalPort);
sts = bind(c_socket, (struct sockaddr *) &l_addr, sizeof(l_addr));
if (debug) printf("bind: %d\n", sts);
if (debug && (sts < 0)) perror("bind");
if (sts != 0) return(-1);
}
}
else {
/* Create a socket for TCP */
l_socket = socket(AF_INET, SOCK_STREAM, 0);
if (debug) printf("socket: %d\n", l_socket);
if (debug && (l_socket < 0)) perror("socket");
if (l_socket < 0) return(-1);
/* Bind the created socket */
if (rn_tcp->LocalPort != 0) {
l_addr.sin_family = AF_INET;
l_addr.sin_port = htons(rn_tcp->LocalPort);
sts = bind(l_socket, (struct sockaddr *) &l_addr, sizeof(l_addr));
if (debug) printf("bind: %d\n", sts);
if (debug && (sts < 0)) perror("bind");
if (sts != 0) return(-1);
}
/* Create listening queue */
sts = listen(l_socket, 1);
if (debug) printf("listen: %d\n", sts);
}
rn_tcp->LinkUp = 0;
rn_tcp->KeepaliveDiff = 0;
time_since_scan = 0;
time_since_rcv = 0;
time_since_keepalive = 0;
return(0);
}
/*************************************************************************
**************************************************************************
*
* Namn : Connect
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Connects local socket to server
*
*
**************************************************************************
**************************************************************************/
int Connect()
{
int sts, sts2;
struct sockaddr_in l_addr;
int l_addr_len;
sts = -1;
if (cs_mode == TCP_CLIENT) {
/* Initialize remote address structure */
r_addr.sin_family = AF_INET;
r_addr.sin_port = htons(rn_tcp->RemotePort);
r_addr.sin_addr.s_addr = inet_addr(rn_tcp->RemoteAddress);
/* Try to connect */
sts = connect(c_socket, (struct sockaddr *) &r_addr, sizeof(r_addr));
if (debug) printf("connect: %d\n", sts);
if (debug && (sts < 0)) perror("connect");
/* Get local socket description */
if (sts == 0) {
l_addr_len = sizeof(struct sockaddr);
sts2 = getsockname(c_socket, (struct sockaddr *) &l_addr, &l_addr_len);
if (sts2 == 0) rn_tcp->LocalPort = ntohs(l_addr.sin_port);
}
}
time_since_rcv = 0;
if (sts == 0) rn_tcp->LinkUp = 1;
return(sts);
}
/*************************************************************************
**************************************************************************
*
* Namn : Accept
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Accepts a client
*
*
**************************************************************************
**************************************************************************/
int Accept()
{
int l_addr_len;
if (cs_mode == TCP_SERVER) {
/* Wait for client */
c_socket = accept(l_socket, (struct sockaddr *) &r_addr, &l_addr_len);
if (debug) printf("accept: %d\n", c_socket);
if (debug && (c_socket < 0)) perror("accept");
}
time_since_rcv = 0;
rn_tcp->LinkUp = 1;
return(0);
}
/*************************************************************************
**************************************************************************
*
* Namn : Shutdown
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Shuts down connection
*
*
**************************************************************************
**************************************************************************/
void Shutdown()
{
int sts;
sts = shutdown(c_socket, 2);
if (debug) printf("shutdown: %d\n", sts);
if (debug && (sts < 0)) perror("shutdown");
if (cs_mode == TCP_CLIENT) {
sts = close(c_socket);
if (debug) printf("close: %d\n", sts);
if (debug && (sts < 0)) perror("close");
}
return;
}
/*************************************************************************
**************************************************************************
*
* Namn : TreatRemtrans
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning :
*
**************************************************************************
**************************************************************************/
void TreatRemtrans(char *buf)
{
remtrans_item *remtrans;
unsigned char search_remtrans;
remote_tcp_header header;
unsigned int sts;
/* Extract header and convert to host byte order */
memcpy(&header, buf, sizeof(remote_tcp_header));
header.msg_size = ntohs(header.msg_size);
header.msg_id[0] = ntohs(header.msg_id[0]);
header.msg_id[1] = ntohs(header.msg_id[1]);
/* Start searching remtrans */
remtrans = rn.remtrans;
search_remtrans = true;
while(remtrans && search_remtrans)
{
/* Match? */
if (remtrans->objp->Address[0] == header.msg_id[0] &&
remtrans->objp->Address[1] == header.msg_id[1] &&
remtrans->objp->Direction == REMTRANS_IN)
{
search_remtrans = false;
sts = RemTrans_Receive(remtrans, buf + sizeof(remote_tcp_header),
header.msg_size-sizeof(remote_tcp_header));
}
remtrans = (remtrans_item *) remtrans->next;
}
if (search_remtrans) rn_tcp->ErrCount++;
return;
}
/*************************************************************************
**************************************************************************
*
* Namn : Receive
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Receives data
*
*
**************************************************************************
**************************************************************************/
unsigned int Receive()
{
unsigned char more_messages;
int data_size;
int buf_ix; /* Current position in receive buffer */
remote_tcp_header header;
static char saved_buffer[65536];
static int saved_fl = 0;
static int saved_size;
static int expected_rest;
data_size = recv(c_socket, receive_buffer, sizeof(receive_buffer), 0);
if (data_size < 0)
{
/* Error */
return(-1);
}
if (data_size == 0)
{
/* Disconnected */
return(0);
}
if (rn_tcp->Disable) {
saved_fl = false;
return(1);
}
buf_ix = 0;
more_messages = true;
time_since_rcv = 0;
if (saved_fl)
{
if (data_size >= expected_rest)
{
memcpy(&saved_buffer[saved_size], &receive_buffer, expected_rest);
TreatRemtrans(saved_buffer);
/* Set position in data buffer */
buf_ix = expected_rest;
data_size = data_size - expected_rest;
if (data_size < sizeof(header)) more_messages = false;
}
saved_fl = 0;
}
while (more_messages)
{
if (data_size >= sizeof(remote_tcp_header))
{
memcpy(&header, &receive_buffer[buf_ix], sizeof(remote_tcp_header));
/* Convert to host byte order */
header.msg_size = ntohs(header.msg_size);
header.msg_id[0] = ntohs(header.msg_id[0]);
header.msg_id[1] = ntohs(header.msg_id[1]);
if (header.protocol_id[0] == remote_tcp_id[0] &&
header.protocol_id[1] == remote_tcp_id[1])
{
if (data_size >= header.msg_size)
{
if (header.msg_size > sizeof(header)) /* Not keepalive buffer */
{
TreatRemtrans(&receive_buffer[buf_ix]);
}
else if (header.msg_size == sizeof(header)) /* Keepalive buffer */
rn_tcp->KeepaliveDiff--;
else /* Too short */
rn_tcp->ErrCount++;
}
else
{
/* Remote ip-message but not complete, save buffer */
memcpy(&saved_buffer, &receive_buffer[buf_ix], data_size);
saved_fl = 1;
saved_size = data_size;
expected_rest = header.msg_size - data_size;
}
}
else
rn_tcp->ErrCount++;
}
else /* Too short */
rn_tcp->ErrCount++;
if (header.msg_size > 0 && !saved_fl)
{
data_size -= header.msg_size;
buf_ix += header.msg_size;
if (data_size < sizeof(header)) more_messages = false;
}
else more_messages = false;
}
return(1);
}
/*************************************************************************
**************************************************************************
*
* Namn : SendKeepalive
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning :
*
**************************************************************************
**************************************************************************/
unsigned int SendKeepalive(void)
{
int sts;
remote_tcp_header header;
/* Fill in application header and convert to network byte order */
header.protocol_id[0] = STX;
header.protocol_id[1] = ETB;
header.msg_size = htons(sizeof(header));
header.msg_id[0] = 0;
header.msg_id[1] = 0;
sts = send(c_socket, &header, sizeof(header), 0);
if (sts >= 0) rn_tcp->KeepaliveDiff++;
return(sts);
}
/*************************************************************************
**************************************************************************
*
* Namn : RemnodeSend
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends data
*
*
**************************************************************************
**************************************************************************/
unsigned int RemnodeSend(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buf_size)
{
int sts;
static struct message_s {
remote_tcp_header header;
char data[TCP_MAX_SIZE];
}message;
memcpy(&message.data, buf, buf_size);
if (rn_tcp->DisableHeader) {
sts = send(c_socket, &message.data, buf_size, 0);
}
else {
message.header.protocol_id[0] = STX;
message.header.protocol_id[1] = ETB;
message.header.msg_size = htons(buf_size+sizeof(remote_tcp_header));
message.header.msg_id[0] = htons(remtrans->Address[0]);
message.header.msg_id[1] = htons(remtrans->Address[1]);
sts = send(c_socket, &message, buf_size + sizeof(remote_tcp_header), 0);
}
if (debug) printf("send: %d\n", sts);
if (debug && (sts == -1)) perror("send");
return 1;
}
/*************************************************************************
**************************************************************************
*
* Namn : main
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Main
*
*
**************************************************************************
**************************************************************************/
int main(int argc, char *argv[])
{
remtrans_item *remtrans;
unsigned char id[32];
unsigned char pname[32];
pwr_tStatus sts;
struct timeval tv;
int i;
if (argc >= 4) debug=1;
/* Read arg number 2, should be id for this instance */
if (argc >= 2)
strcpy(id, argv[1]);
else
strcpy(id, "0");
/* Build process name with id */
sprintf((char *) pname, "rs_remtcp_%s", id);
/* Init of errh */
errh_Init((char *) pname, errh_eAnix_remote);
errh_SetStatus(PWR__SRVSTARTUP);
/* Init of gdh */
sts = gdh_Init((char *) pname);
if (debug) printf("Gdh init: %d\n", sts);
if ( EVEN(sts)) {
errh_Error("gdh_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Arg number 3 should be my remnodes objid in string representation,
read it, convert to real objid and store in remnode_item */
sts = 0;
if (argc >= 3) sts = cdh_StringToObjid(argv[2], &rn.objid);
if (debug) printf("StringToObjid: %d\n", sts);
if ( EVEN(sts)) {
errh_Error("cdh_StringToObjid, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Get pointer to RemnodeTCP object and store locally */
sts = gdh_ObjidToPointer(rn.objid, (pwr_tAddress *) &rn_tcp);
if (debug) printf("ObjidToPointer: %d\n", sts);
if ( EVEN(sts)) {
errh_Error("cdh_ObjidToPointer, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Initialize some internal data and make standard remtrans init */
rn.next = NULL;
rn.local = NULL; // We dont use local structure since we only have one remnode
rn.retransmit_time = rn_tcp->RetransmitTime;
rn_tcp->ErrCount = 0;
sts = RemTrans_Init(&rn);
if ( EVEN(sts)) {
errh_Error("RemTrans_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Initialize no timeout value (poll) for select call */
tv.tv_sec = 0;
tv.tv_usec = 0;
/* Set mode client or server */
if (rn_tcp->ConnectionMode == 0)
cs_mode = TCP_CLIENT;
else
cs_mode = TCP_SERVER;
/* Create TCP socket and init adress structures */
rn_tcp->LinkUp = 0;
for (i=0; i<10; i++) {
sts = CreateSocket();
if (sts >= 0)
break;
else
RemoteSleep(3);
}
if (sts != 0) {
errh_Error("CreateSocket, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Set (re)start time in remnode object */
clock_gettime(CLOCK_REALTIME, &rn_tcp->RestartTime);
/* Store remtrans objects objid in remnode_tcp object */
remtrans = rn.remtrans;
i = 0;
while(remtrans) {
rn_tcp->RemTransObjects[i++] = remtrans->objid;
if ( i >= (int)(sizeof(rn_tcp->RemTransObjects)/sizeof(rn_tcp->RemTransObjects[0])))
break;
remtrans = (remtrans_item *) remtrans->next;
}
if (cs_mode == TCP_CLIENT) {
/* Connect, make 10 attempts with 3 seconds interval */
for (i=0; i<10; i++) {
sts = Connect();
if (sts >= 0)
break;
else
RemoteSleep(3);
}
}
else {
Accept();
}
/* Connected, Loop forever */
/* Set running status */
errh_SetStatus(PWR__SRUN);
while (!doomsday)
{
if (rn_tcp->Disable == 1) {
errh_Fatal("Disabled, exiting");
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
/* Timestamp */
aproc_TimeStamp();
RemoteSleep(TIME_INCR);
/* Increase time counters in local remnode and prevent big counters */
time_since_scan += TIME_INCR;
time_since_keepalive += TIME_INCR;
time_since_rcv += TIME_INCR;
time_since_scan = min(time_since_scan, rn_tcp->ScanTime + 1.0);
time_since_keepalive = min(time_since_keepalive, rn_tcp->KeepaliveTime + 1.0);
time_since_rcv = min(time_since_rcv, rn_tcp->LinkTimeout + 1.0);
/* Update retransmit time, could have been changed */
rn.retransmit_time = rn_tcp->RetransmitTime;
remtrans = rn.remtrans;
while(remtrans) {
remtrans->time_since_send += TIME_INCR;
/* Prevent big counter */
remtrans->time_since_send = min(remtrans->time_since_send, rn.retransmit_time + 1.0);
remtrans = (remtrans_item *) remtrans->next;
}
if (rn_tcp->LinkUp == 0) {
Shutdown();
if (cs_mode == TCP_CLIENT)
exit(0);
else
Accept();
}
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&fdr);
FD_ZERO(&fde);
FD_SET(c_socket, &fdr);
FD_SET(c_socket, &fde);
sts = select(32, &fdr, NULL, &fde, &tv);
if (sts < 0 && debug) perror("select");
if (sts < 0) exit(sts);
if (sts > 0) {
sts = Receive();
if (sts <= 0 && debug) perror("receive:");
if (sts < 0) exit(sts);
if (sts == 0) rn_tcp->LinkUp = 0;
}
if (rn_tcp->LinkUp == 1) {
if (time_since_scan >= rn_tcp->ScanTime) {
if (!rn_tcp->Disable) RemTrans_Cyclic(&rn, &RemnodeSend);
time_since_scan = 0;
}
if (time_since_keepalive >= rn_tcp->KeepaliveTime) {
if (!rn_tcp->Disable && rn_tcp->UseKeepalive) SendKeepalive();
time_since_keepalive = 0;
}
if (time_since_rcv >= rn_tcp->LinkTimeout) {
if (rn_tcp->LinkUp) {
errh_Info("TCP link down %s", rn_tcp->RemoteHostname);
rn_tcp->LinkUp = 0;
}
}
}
}
}
include $(pwre_dir_symbols)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(hw_name)/$(type_name)_generic.mk
ifeq ($($(type_name)_generic_mk),)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(type_name)_generic.mk
endif
ifeq ($($(type_name)_generic_mk),)
include $(pwre_kroot)/tools/bld/src/$(type_name)_generic.mk
endif
ifndef link_rule_mk
link_rule_mk := 1
link = $(ldxx) $(elinkflags) $(domap) -o $(export_exe) \
$(export_obj) $(objects) $(rt_msg_eobjs) \
-lpwr_remote -lpwr_rt -lpwr_co -lpwr_msg_dummy -lpthread -lrt -lm
endif
/*
* Proview $Id: rs_remote_udpip.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*************************************************************************
* ===============
* P r o v i e w
* ===============
**************************************************************************
*
* Filename: rs_remote_udpip.c
*
* Date Pgm. Read. Remark
* Modified 000301 CJu
* 000330 CJu v3.0
* 040504 CJu v4.0.0
*
* Description: Remote transport process UDP/IP
* Implements transport protocol UDP/IP, connectionless
* datagram protocol on the IP-stack. The major difference
* between TCP and UDP is that TCP uses connected
* sockets while UDP sends datagrams to any unconnected
* socket.
*
**************************************************************************
**************************************************************************/
/*_Include files_________________________________________________________*/
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "pwr_class.h"
#include "pwrs_c_node.h"
#include "rt_gdh.h"
#include "co_cdh.h"
#include "rt_errh.h"
#include "pwr_baseclasses.h"
#include "pwr_remoteclasses.h"
#include "rt_pwr_msg.h"
#include "rt_aproc.h"
#include "remote.h"
#include "remote_remtrans_utils.h"
#define STX 2
#define ETB 15
#define ENQ 5
#define ACK 6
#define UDP_MAX_SIZE 32768
#define TIME_INCR 0.02
fd_set fds; /* For select call */
typedef struct
{
unsigned char protocol_id[2];
short int msg_size;
short int msg_id[2];
} remote_udp_header;
remnode_item rn;
pwr_sClass_RemnodeUDP *rn_udp;
float time_since_scan;
float time_since_rcv;
float time_since_keepalive;
int my_socket; /* My socket */
struct sockaddr_in my_addr; /* My named socket description */
struct sockaddr_in their_addr; /* Remote socket description */
struct sockaddr_in dual_addr; /* Maybe a dual socket description */
/*************************************************************************
**************************************************************************
*
* RemoteSleep
*
**************************************************************************
**************************************************************************/
void RemoteSleep(float time)
{
struct timespec rqtp, rmtp;
rqtp.tv_sec = 0;
rqtp.tv_nsec = (long int) (time * 1000000000);
nanosleep(&rqtp, &rmtp);
return;
}
/*************************************************************************
**************************************************************************
*
* SendAck
*
**************************************************************************
**************************************************************************/
void SendAck(short int id0, short int id1)
{
int status;
remote_udp_header header;
header.protocol_id[0] = STX;
header.protocol_id[1] = ACK;
header.msg_size = htons(sizeof(remote_udp_header));
header.msg_id[0] = htons(id0);
header.msg_id[1] = htons(id1);
status = sendto(my_socket, &header, sizeof(header), 0,
(struct sockaddr *) &their_addr, sizeof(struct sockaddr));
return;
}
/*************************************************************************
**************************************************************************
*
* Receive
*
**************************************************************************
**************************************************************************/
short int Receive()
{
static char buf[UDP_MAX_SIZE];
char unknown[24];
unsigned char badr[24];
char *pos;
struct sockaddr_in from;
unsigned int fromlen;
int size;
unsigned int sts;
remote_udp_header header;
remtrans_item *remtrans;
unsigned char search_remtrans;
rem_t_transbuff *transbuff;
rem_t_transbuff *transbuff_behind;
remtrans_item *transp;
/* We have made a select, so we're pretty sure there is something to take */
fromlen = sizeof(struct sockaddr);
size = recvfrom(my_socket, &buf, sizeof(buf), 0,
(struct sockaddr *) &from, &fromlen);
if (size < 0) { /* Definitly error */
errh_Info("UDP Receive fail %s", rn_udp->RemoteHostname);
rn_udp->ErrCount++;
return(-1);
}
if (rn_udp->Disable) return(1);
if (memcmp(&from.sin_addr,
&their_addr.sin_addr,
sizeof(struct in_addr)) != 0) { /*from.sin_port != their_addr.sin_port*/
memcpy(&badr, &from.sin_addr, 4);
sprintf(unknown, "%d.%d.%d.%d", badr[0], badr[1], badr[2], badr[3]);
errh_Info("UDP Receive from unknown source %s", unknown);
rn_udp->ErrCount++;
return(1);
}
/* Set link up */
time_since_rcv = 0;
if (rn_udp->LinkUp == 0) {
errh_Info("UDP link up %s", rn_udp->RemoteHostname);
rn_udp->LinkUp = 1;
}
if (size > 0 && rn_udp->DisableHeader) {
/* Header disabled, take the first receive remtrans object */
remtrans = rn.remtrans;
search_remtrans = true;
while(remtrans && search_remtrans) {
/* Match? */
if (remtrans->objp->Direction == REMTRANS_IN) {
search_remtrans = false;
sts = RemTrans_Receive(remtrans, buf, size);
}
remtrans = (remtrans_item *) remtrans->next;
}
if (search_remtrans) {
rn_udp->ErrCount++;
errh_Info("UDP Receive no remtrans %s", rn_udp->RemoteHostname);
}
}
else if (size >= 8) {
memcpy(&header, &buf, sizeof(remote_udp_header));
/* Convert the header to host byte order */
header.msg_size = ntohs(header.msg_size);
header.msg_id[0] = ntohs(header.msg_id[0]);
header.msg_id[1] = ntohs(header.msg_id[1]);
if (header.protocol_id[0] == STX && size == header.msg_size) {
/* This is a valid remtrans */
if (header.protocol_id[1] == ETB || header.protocol_id[1] == ENQ) {
if (header.msg_id[0] == 0 && header.msg_id[1] == 0) {
/* Keepalive */
rn_udp->KeepaliveDiff--;
}
else {
/* Data */
remtrans = (remtrans_item *) rn.remtrans;
search_remtrans = true;
while(remtrans && search_remtrans) {
/* Match? */
if (remtrans->objp->Address[0] == header.msg_id[0] &&
remtrans->objp->Address[1] == header.msg_id[1] &&
remtrans->objp->Direction == REMTRANS_IN) {
search_remtrans = false;
pos = ((char *) &buf) + sizeof(remote_udp_header);
sts = RemTrans_Receive(remtrans, pos,
header.msg_size-sizeof(remote_udp_header));
if (header.protocol_id[1] == ENQ) {
SendAck(header.msg_id[0], header.msg_id[1]);
}
}
remtrans = (remtrans_item *) remtrans->next;
}
if (search_remtrans) {
rn_udp->ErrCount++;
errh_Info("UDP Receive no remtrans %s", rn_udp->RemoteHostname);
}
}
}
else if (header.protocol_id[1] == ACK) {
/* Acknowledge message */
transbuff = (rem_t_transbuff *) rn.transbuff;
transbuff_behind = (rem_t_transbuff *) rn.transbuff;
while (transbuff) {
transp = (remtrans_item *) transbuff->remtrans;
if (header.msg_id[0] == transp->objp->Address[0] &&
header.msg_id[1] == transp->objp->Address[1]) {
/* This is it, unlink the transbuff */
if (transbuff == transbuff_behind)
rn.transbuff = (rem_t_transbuff *) transbuff->next;
else
transbuff_behind->next = (rem_t_transbuff *) transbuff->next;
/* Decrement buffer counter */
transp->objp->Buffers--;
/* Free transbuff */
free(transbuff);
/* Break the while loop */
break;
}
transbuff_behind = transbuff;
transbuff = (rem_t_transbuff *) transbuff->next;
}
}
else {
/* Weird header */
rn_udp->ErrCount++;
errh_Info("UDP receive weird header %s, %02x %02x %04x %04x %04x",
rn_udp->RemoteHostname,
header.protocol_id[0],
header.protocol_id[1],
header.msg_size,
header.msg_id[0],
header.msg_id[1]);
}
}
else {
/* Weird header */
rn_udp->ErrCount++;
errh_Info("UDP receive weird header %s, %02x %02x %04x %04x %04x",
rn_udp->RemoteHostname,
header.protocol_id[0],
header.protocol_id[1],
header.msg_size,
header.msg_id[0],
header.msg_id[1]);
}
}
else {
/* Not a remtrans UPD message */
rn_udp->ErrCount++;
errh_Info("UDP receive weird message %s", rn_udp->RemoteHostname);
}
return(1);
}
/*************************************************************************
**************************************************************************
*
* SendKeepalive
*
**************************************************************************
**************************************************************************/
int SendKeepalive(void)
{
int sts;
remote_udp_header header;
/* Fill in application header and convert to network byte order */
header.protocol_id[0] = STX;
header.protocol_id[1] = ETB;
header.msg_size = htons(sizeof(header));
header.msg_id[0] = 0;
header.msg_id[1] = 0;
sts = sendto(my_socket, &header, sizeof(header), 0,
(struct sockaddr *) &their_addr, sizeof(struct sockaddr));
if (sts >= 0) rn_udp->KeepaliveDiff++;
return(sts);
}
/*************************************************************************
**************************************************************************
*
* CreateSocket
*
**************************************************************************
**************************************************************************/
void CreateSocket()
{
int sts;
unsigned char badr[4];
unsigned int iadr[4] = {-1, -1, -1, -1};
struct hostent *he;
struct sockaddr_in address;
socklen_t address_len = sizeof(struct sockaddr_in);
/* Create a socket for UDP */
my_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (my_socket < 0) {
errh_Error("Socket, %d", my_socket);
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
if (rn_udp->LocalPort != 0) {
/* Set local port */
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(rn_udp->LocalPort);
/* Bind the created socket */
sts = bind(my_socket, (struct sockaddr *) &my_addr, sizeof(my_addr));
if (sts != 0) {
errh_Error("Bind, %d", sts);
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
}
else {
getsockname(my_socket, (struct sockaddr *) &address, &address_len);
rn_udp->LocalPort = ntohs(address.sin_port);
}
/*
problem, you have to be root user to do this!!
sts = setsockopt(my_socket, SOL_SOCKET, SO_BINDTODEVICE, rn_udp->DevName, strlen(en_udp->DevName));
printf("Setsockopt, %d\n", sts);
if (sts != 0) errh_Error("Setsockopt bindtodevice, %d", sts);
*/
/* Initialize remote address structure */
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(rn_udp->RemotePort);
sscanf((char *) &(rn_udp->RemoteAddress), "%d.%d.%d.%d",
&iadr[0], &iadr[1], &iadr[2], &iadr[3]);
/* If none or invalid ip-address is given, use hostname to get hostent struct,
otherwise use the given ip address directly */
if ((iadr[0] < 0 || iadr[0] > 255) ||
(iadr[0] < 0 || iadr[0] > 255) ||
(iadr[0] < 0 || iadr[0] > 255) ||
(iadr[0] < 0 || iadr[0] > 255)) {
he = gethostbyname(rn_udp->RemoteHostname);
if (he) {
memcpy(&their_addr.sin_addr, he->h_addr, 4);
sprintf(rn_udp->RemoteAddress, "%s", inet_ntoa(their_addr.sin_addr));
}
else {
errh_Error("Unknown host, %s", rn_udp->RemoteHostname);
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
}
else {
badr[0] = (unsigned char) iadr[0];
badr[1] = (unsigned char) iadr[1];
badr[2] = (unsigned char) iadr[2];
badr[3] = (unsigned char) iadr[3];
memcpy(&their_addr.sin_addr, &badr, 4);
}
/* If there is a multicast address configured, create a socket for a dual remote node */
if (rn.multicast) {
dual_addr.sin_family = AF_INET;
dual_addr.sin_port = htons(rn_udp->RemotePort);
badr[0] = (unsigned char) rn.multicast->Address[0];
badr[1] = (unsigned char) rn.multicast->Address[1];
badr[2] = (unsigned char) rn.multicast->Address[2];
badr[3] = (unsigned char) rn.multicast->Address[3];
memcpy(&dual_addr.sin_addr, &badr, 4);
}
rn_udp->LinkUp = 0;
rn_udp->KeepaliveDiff = 0;
time_since_scan = 0;
time_since_rcv = 0;
time_since_keepalive = 0;
}
/*************************************************************************
**************************************************************************
*
* RemnodeSend
*
**************************************************************************
**************************************************************************/
unsigned int RemnodeSend(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buf_size)
{
int status;
int want_ack;
static struct message_s {
remote_udp_header header;
char data[UDP_MAX_SIZE];
} message;
message.header.protocol_id[0] = STX;
/* Will we have ack? */
want_ack = 0;
if (remtrans->MaxBuffers > 0) {
message.header.protocol_id[1] = ENQ;
want_ack = 1;
}
else
message.header.protocol_id[1] = ETB;
message.header.msg_size = htons(buf_size+sizeof(remote_udp_header));
message.header.msg_id[0] = htons(remtrans->Address[0]);
message.header.msg_id[1] = htons(remtrans->Address[1]);
memcpy(&message.data, buf, buf_size);
if (rn_udp->DisableHeader)
status = sendto(my_socket, &message.data, buf_size, 0,
(struct sockaddr *) &their_addr, sizeof(struct sockaddr));
else
status = sendto(my_socket, &message, buf_size + sizeof(remote_udp_header), 0,
(struct sockaddr *) &their_addr, sizeof(struct sockaddr));
/* Send to dual node aswell if this is configured, we never want ack on this though */
if (rn.multicast && remtrans->Address[3] & 1) {
message.header.protocol_id[1] = ETB;
if (rn_udp->DisableHeader)
status = sendto(my_socket, &message.data, buf_size, 0,
(struct sockaddr *) &dual_addr, sizeof(struct sockaddr));
else
status = sendto(my_socket, &message, buf_size + sizeof(remote_udp_header), 0,
(struct sockaddr *) &dual_addr, sizeof(struct sockaddr));
}
if (want_ack)
return (STATUS_BUFACK);
else
return (STATUS_OK);
}
/*************************************************************************
**************************************************************************
*
* Main
*
**************************************************************************
**************************************************************************/
int main(int argc, char *argv[])
{
remtrans_item *remtrans;
unsigned char id[32];
unsigned char pname[32];
pwr_tStatus sts;
struct timeval tv;
int i;
/* Read arg number 2, should be id for this instance */
if (argc >= 2)
strcpy(id, argv[1]);
else
strcpy(id, "0");
/* Build process name with id */
sprintf((char *) pname, "rs_remudp_%s", id);
/* Init of errh */
errh_Init((char *) pname, errh_eAnix_remote);
errh_SetStatus(PWR__SRVSTARTUP);
/* Init of gdh */
sts = gdh_Init((char *) pname);
if ( EVEN(sts)) {
errh_Error("gdh_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Arg number 3 should be my remnodes objid in string representation,
read it, convert to real objid and store in remnode_item */
sts = 0;
if (argc >= 3) sts = cdh_StringToObjid(argv[2], &rn.objid);
if ( EVEN(sts)) {
errh_Error("cdh_StringToObjid, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Get pointer to RemnodeUDP object and store locally */
sts = gdh_ObjidToPointer(rn.objid, (pwr_tAddress *) &rn_udp);
if ( EVEN(sts)) {
errh_Error("cdh_ObjidToPointer, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Initialize some internal data and make standard remtrans init */
rn.next = NULL;
rn.local = NULL; // We dont use local structure since we only have one remnode
rn.retransmit_time = rn_udp->RetransmitTime;
rn_udp->ErrCount = 0;
sts = RemTrans_Init(&rn);
/* Log that we will multicast */
if (rn.multicast) {
errh_Info("Will send to dual address: %d.%d.%d.%d",
rn.multicast->Address[0],
rn.multicast->Address[1],
rn.multicast->Address[2],
rn.multicast->Address[3]);
}
if ( EVEN(sts)) {
errh_Error("RemTrans_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Store remtrans objects objid in remnode_udp object */
remtrans = rn.remtrans;
i = 0;
while(remtrans) {
rn_udp->RemTransObjects[i++] = remtrans->objid;
if ( i >= (int)(sizeof(rn_udp->RemTransObjects)/sizeof(rn_udp->RemTransObjects[0])))
break;
remtrans = (remtrans_item *) remtrans->next;
}
/* Initialize no timeout value (poll) for select call */
tv.tv_sec = 0;
tv.tv_usec = 0;
/* Create UDP socket and init adress structures */
CreateSocket();
/* Wait for one cycle */
RemoteSleep(rn_udp->ScanTime);
/* Set running status */
errh_SetStatus(PWR__SRUN);
/* Set (re)start time in remnode object */
clock_gettime(CLOCK_REALTIME, &rn_udp->RestartTime);
/* Loop forever */
while (!doomsday)
{
/* Check disable flag */
if (rn_udp->Disable == 1) {
errh_Fatal("Disabled, exiting");
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
/* Timestamp */
aproc_TimeStamp();
RemoteSleep(TIME_INCR);
/* Increase time counters in local remnode and prevent big counters */
time_since_scan += TIME_INCR;
time_since_keepalive += TIME_INCR;
time_since_rcv += TIME_INCR;
time_since_scan = min(time_since_scan, rn_udp->ScanTime + 1.0);
time_since_keepalive = min(time_since_keepalive, rn_udp->KeepaliveTime + 1.0);
time_since_rcv = min(time_since_rcv, rn_udp->LinkTimeout + 1.0);
/* Update retransmit time, could have been changed */
rn.retransmit_time = rn_udp->RetransmitTime;
remtrans = rn.remtrans;
while(remtrans) {
remtrans->time_since_send += TIME_INCR;
/* Prevent big counter */
remtrans->time_since_send = min(remtrans->time_since_send, rn.retransmit_time + 1.0);
remtrans = (remtrans_item *) remtrans->next;
}
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(my_socket, &fds);
sts = select(32, &fds, NULL, NULL, &tv);
if (sts > 0) Receive();
if (sts < 0) {
errh_Error("Select, %d", sts);
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
if (time_since_scan >= rn_udp->ScanTime) {
if (!rn_udp->Disable) RemTrans_Cyclic(&rn, &RemnodeSend);
time_since_scan = 0;
}
if (time_since_keepalive >= rn_udp->KeepaliveTime) {
if (!rn_udp->Disable && rn_udp->UseKeepalive) SendKeepalive();
time_since_keepalive = 0;
}
if (time_since_rcv >= rn_udp->LinkTimeout && rn_udp->LinkTimeout > 0) {
if (rn_udp->LinkUp) {
errh_Info("UDP link down %s", rn_udp->RemoteHostname);
rn_udp->LinkUp = 0;
}
}
}
}
include $(pwre_dir_symbols)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(hw_name)/$(type_name)_generic.mk
ifeq ($($(type_name)_generic_mk),)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(type_name)_generic.mk
endif
ifeq ($($(type_name)_generic_mk),)
include $(pwre_kroot)/tools/bld/src/$(type_name)_generic.mk
endif
ifndef link_rule_mk
link_rule_mk := 1
link = $(ldxx) $(elinkflags) $(domap) -o $(export_exe) \
$(export_obj) $(objects) $(rt_msg_eobjs) \
-lpwr_remote -lpwr_rt -lpwr_co -lpwr_msg_dummy -lpthread -lrt -lm
endif
/*
* Proview $Id: rs_remotehandler.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/************************************************************************
*
* P S S - 9 0 0 0
* =================
*************************************************************************
*
* Filename: remotehandler.c
*
* Date Pgm. Read. Remark
* Modified 950307 Hans Werner ELN
* 950309 C Jurstrand VMS
* 950309 C Jurstrand VMS
* 950915 CS Converted to DECC compiler
* 960215 C Jurstrand 3964R and TCP/IP
* 960927 C Jurstrand 3964R_VNET and name for 1:st process
* 970602 C Jurstrand MODBUS and ADLP10
* 971016 C Jurstrand DMQ
* 980610 C Jurstrand Universal serial prot.
* 980922 C Jurstrand MOMENTUM
* 000330 C Jurstrand 3.0b and LIMAB and UDP/IP
* 000517 C Jurstrand Lynx OS
* 001222 C Jurstrand Varmomstart, QCOM
* 010405 C Jurstrand 3.3a, QCOM p ELN
* 040303 J Nylund ndrat till omgivningsvariabel
* i skvgarna till exe-filerna
* 040422 C Jurstrand 4.0.0
*
* Description:
* Start and control of transportprocesses for remote communication
*
**************************************************************************
**************************************************************************/
/********* Include files *************************************************/
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
#include "co_dcli.h"
#include "pwr.h"
#include "pwr_class.h"
#include "pwrs_c_node.h"
#include "co_cdh.h"
#include "rt_gdh.h"
#include "rt_errh.h"
#include "rt_qcom.h"
#include "rt_qcom_msg.h"
#include "rt_pwr_msg.h"
#include "rt_ini_event.h"
#include "pwr_baseclasses.h"
#include "pwr_remoteclasses.h"
#include "remote.h"
#include "rt_plc_utl.h"
#include "rt_pcm.h"
#include "rt_aproc.h"
typedef struct {
char path[64];
pwr_tObjid objid;
pwr_tAddress objref;
pwr_tClassId classid;
pwr_tBoolean *disable;
pwr_tUInt32 *restart_limit;
pwr_tUInt32 *restarts;
pwr_tBoolean first;
pid_t cpid;
int id;
} Transport;
Transport tp[25];
int tpcount;
int tpmax = 25;
pwr_tObjid remcfg_objid;
pwr_sClass_RemoteConfig *remcfgp;
static void AddTransports();
static int StartTransport(unsigned int idx);
/************************************************************************
*
* AddTransport
*
************************************************************************/
static void AddTransports()
{
pwr_tObjid objid;
pwr_tAddress objref;
pwr_tStatus sts;
/* Init transport (process) counter */
tpcount = 0;
/* Initialize transport vector with 0's */
memset(&tp, 0, sizeof(tp));
/* Get and configure all MQ remnodes, one process for each remnode */
sts = gdh_GetClassList (pwr_cClass_RemnodeMQ, &objid);
while ( ODD(sts))
{
sts = gdh_ObjidToPointer(objid, &objref);
sprintf(tp[tpcount].path, "rs_remote_mq");
tp[tpcount].id = ((pwr_sClass_RemnodeMQ *) objref)->MyQueue;
tp[tpcount].disable = &((pwr_sClass_RemnodeMQ *) objref)->Disable;
tp[tpcount].restart_limit = &((pwr_sClass_RemnodeMQ *) objref)->RestartLimit;
tp[tpcount].restarts = &((pwr_sClass_RemnodeMQ *) objref)->RestartCount;
((pwr_sClass_RemnodeMQ *) objref)->RestartCount = 0;
tp[tpcount].objid = objid;
tp[tpcount].objref = objref;
tp[tpcount].classid = pwr_cClass_RemnodeMQ;
tp[tpcount].cpid = -1;
tp[tpcount].first = true;
remcfgp->RemNodeObjects[tpcount] = objid;
tpcount++;
sts = gdh_GetNextObject (objid, &objid);
}
/* Get and configure all UDP remnodes, one process for each remnode */
sts = gdh_GetClassList (pwr_cClass_RemnodeUDP, &objid);
while ( ODD(sts))
{
sts = gdh_ObjidToPointer(objid, &objref);
sprintf(tp[tpcount].path, "rs_remote_udpip");
tp[tpcount].id = ((pwr_sClass_RemnodeUDP *) objref)->LocalPort;
tp[tpcount].disable = &((pwr_sClass_RemnodeUDP *) objref)->Disable;
tp[tpcount].restart_limit = &((pwr_sClass_RemnodeUDP *) objref)->RestartLimit;
tp[tpcount].restarts = &((pwr_sClass_RemnodeUDP *) objref)->RestartCount;
((pwr_sClass_RemnodeUDP *) objref)->RestartCount = 0;
tp[tpcount].objid = objid;
tp[tpcount].objref = objref;
tp[tpcount].classid = pwr_cClass_RemnodeUDP;
tp[tpcount].cpid = -1;
tp[tpcount].first = true;
remcfgp->RemNodeObjects[tpcount] = objid;
tpcount++;
sts = gdh_GetNextObject (objid, &objid);
}
/* Get and configure all TCP remnodes, one process for each remnode */
sts = gdh_GetClassList (pwr_cClass_RemnodeTCP, &objid);
while ( ODD(sts))
{
sts = gdh_ObjidToPointer(objid, &objref);
sprintf(tp[tpcount].path, "rs_remote_tcpip");
tp[tpcount].id = ((pwr_sClass_RemnodeTCP *) objref)->LocalPort;
tp[tpcount].disable = &((pwr_sClass_RemnodeTCP *) objref)->Disable;
tp[tpcount].restart_limit = &((pwr_sClass_RemnodeTCP *) objref)->RestartLimit;
tp[tpcount].restarts = &((pwr_sClass_RemnodeTCP *) objref)->RestartCount;
((pwr_sClass_RemnodeTCP *) objref)->RestartCount = 0;
tp[tpcount].objid = objid;
tp[tpcount].objref = objref;
tp[tpcount].classid = pwr_cClass_RemnodeTCP;
tp[tpcount].cpid = -1;
tp[tpcount].first = true;
remcfgp->RemNodeObjects[tpcount] = objid;
tpcount++;
sts = gdh_GetNextObject (objid, &objid);
}
/* Check if there is at least one ALCM remnode. If so, make an entry for rs_remote_alcm in
the transport table. rs_remote_alcm handles all instances of remnodes in one process */
sts = gdh_GetClassList (pwr_cClass_RemnodeALCM, &objid);
if ( ODD(sts))
{
sts = gdh_ObjidToPointer(objid, &objref);
sprintf(tp[tpcount].path, "rs_remote_alcm");
tp[tpcount].id = 0;
tp[tpcount].disable = &((pwr_sClass_RemnodeALCM *) objref)->Disable;
tp[tpcount].restart_limit = &((pwr_sClass_RemnodeALCM *) objref)->RestartLimit;
tp[tpcount].restarts = &((pwr_sClass_RemnodeALCM *) objref)->RestartCount;
((pwr_sClass_RemnodeALCM *) objref)->RestartCount = 0;
tp[tpcount].objid = objid;
tp[tpcount].objref = objref;
tp[tpcount].classid = pwr_cClass_RemnodeALCM;
tp[tpcount].cpid = -1;
tp[tpcount].first = true;
remcfgp->RemNodeObjects[tpcount] = objid;
tpcount++;
}
/* Get and configure all Serial remnodes, one process for each remnode */
sts = gdh_GetClassList (pwr_cClass_RemnodeSerial, &objid);
while ( ODD(sts))
{
sts = gdh_ObjidToPointer(objid, &objref);
sprintf(tp[tpcount].path, "rs_remote_serial");
tp[tpcount].id = 0;
tp[tpcount].disable = &((pwr_sClass_RemnodeSerial *) objref)->Disable;
tp[tpcount].restart_limit = &((pwr_sClass_RemnodeSerial *) objref)->RestartLimit;
tp[tpcount].restarts = &((pwr_sClass_RemnodeSerial *) objref)->RestartCount;
((pwr_sClass_RemnodeSerial *) objref)->RestartCount = 0;
tp[tpcount].objid = objid;
tp[tpcount].objref = objref;
tp[tpcount].classid = pwr_cClass_RemnodeSerial;
tp[tpcount].cpid = -1;
tp[tpcount].first = true;
remcfgp->RemNodeObjects[tpcount] = objid;
tpcount++;
sts = gdh_GetNextObject (objid, &objid);
}
/* Get and configure all Modbus remnodes, one process for each remnode */
sts = gdh_GetClassList (pwr_cClass_RemnodeModbus, &objid);
while ( ODD(sts))
{
sts = gdh_ObjidToPointer(objid, &objref);
sprintf(tp[tpcount].path, "rs_remote_modbus");
tp[tpcount].id = 0;
tp[tpcount].disable = &((pwr_sClass_RemnodeModbus *) objref)->Disable;
tp[tpcount].restart_limit = &((pwr_sClass_RemnodeModbus *) objref)->RestartLimit;
tp[tpcount].restarts = &((pwr_sClass_RemnodeModbus *) objref)->RestartCount;
((pwr_sClass_RemnodeModbus *) objref)->RestartCount = 0;
tp[tpcount].objid = objid;
tp[tpcount].objref = objref;
tp[tpcount].classid = pwr_cClass_RemnodeModbus;
tp[tpcount].cpid = -1;
tp[tpcount].first = true;
remcfgp->RemNodeObjects[tpcount] = objid;
tpcount++;
sts = gdh_GetNextObject (objid, &objid);
}
/* Get and configure all 3964R remnodes, one process for each remnode */
sts = gdh_GetClassList (pwr_cClass_Remnode3964R, &objid);
while ( ODD(sts))
{
sts = gdh_ObjidToPointer(objid, &objref);
sprintf(tp[tpcount].path, "rs_remote_3964r");
tp[tpcount].id = 0;
tp[tpcount].disable = &((pwr_sClass_Remnode3964R *) objref)->Disable;
tp[tpcount].restart_limit = &((pwr_sClass_Remnode3964R *) objref)->RestartLimit;
tp[tpcount].restarts = &((pwr_sClass_Remnode3964R *) objref)->RestartCount;
((pwr_sClass_Remnode3964R *) objref)->RestartCount = 0;
tp[tpcount].objid = objid;
tp[tpcount].objref = objref;
tp[tpcount].classid = pwr_cClass_Remnode3964R;
tp[tpcount].cpid = -1;
tp[tpcount].first = true;
remcfgp->RemNodeObjects[tpcount] = objid;
tpcount++;
sts = gdh_GetNextObject (objid, &objid);
}
return;
}
/************************************************************************
*
* StartTransport
*
************************************************************************/
static int StartTransport(unsigned int idx)
{
char arg1[40];
char arg2[40];
char arg3[40];
int res;
/* Check index */
if (idx >= tpcount || idx < 0) return -1;
if (*tp[idx].disable || (*tp[idx].restarts >= *tp[idx].restart_limit)) {
tp[idx].cpid = -1;
return -1;
}
if (!tp[idx].first) (*tp[idx].restarts)++;
tp[idx].first = false;
memset(arg1, 0, sizeof(arg1));
memset(arg2, 0, sizeof(arg2));
memset(arg3, 0, sizeof(arg3));
sprintf(arg1,"%s", tp[idx].path);
sprintf(arg2,"%d", tp[idx].id);
sprintf(arg3,"%s", cdh_ObjidToString(NULL, tp[idx].objid, 0));
if (((tp[idx].cpid) = fork())) {
}
else {
if (execlp(tp[idx].path, arg1, arg2, arg3, (char *) 0) < 0) {
errh_Warning("Can't start transport %s", tp[idx].path);
res = -1;
_exit(0);
}
else {
res = 1;
}
}
return(res);
}
/************************************************************************
*
* main
*
************************************************************************/
int main()
{
int i;
pwr_tStatus sts;
pid_t cpid;
int stat_loc;
pwr_tStatus status;
qcom_sQattr qattr;
qcom_sQid qini;
qcom_sQid qid = qcom_cNQid;
qcom_sGet get;
char mp[2000];
char hotswap;
char new_plc;
errh_Init("rs_remhdl", errh_eAnix_remote);
errh_SetStatus(PWR__SRVSTARTUP);
/* Qcom init */
if (!qcom_Init(&status, 0, "rs_remhdl")) {
errh_Error("qcom_Init, %m", status);
errh_SetStatus(PWR__SRVTERM);
exit(status);
}
qattr.type = qcom_eQtype_private;
qattr.quota = 100;
if (!qcom_CreateQ(&status, &qid, &qattr, "Restart")) {
errh_Error("qcom_CreateQ, %m", status);
errh_SetStatus(PWR__SRVTERM);
exit(status);
}
qini = qcom_cQini;
if (!qcom_Bind(&status, &qid, &qini)) {
errh_Error("qcom_CreateQ, %m", status);
errh_SetStatus(PWR__SRVTERM);
exit(-1);
}
/* GDH init */
sts = gdh_Init("rs_remhdl");
if ( EVEN(sts)) {
errh_Error("gdh_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
hotswap = 0;
while (true)
{
/* Get RemoteConfig object */
sts = gdh_GetClassList(pwr_cClass_RemoteConfig, &remcfg_objid);
if (ODD(sts)) {
sts = gdh_ObjidToPointer(remcfg_objid, (pwr_tAddress *) &remcfgp);
if ( EVEN(sts)) {
errh_Error("gdh_ObjidToPointer, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
aproc_RegisterObject( remcfg_objid);
if (remcfgp->Disable) {
errh_Info("Remote server disabled in RemoteConfig, rs_remotehandler will not run");
errh_SetStatus(0);
exit(1);
}
for (i=0; i<tpmax; i++) remcfgp->RemNodeObjects[i] = pwr_cNObjid;
}
else {
errh_Info("No RemoteConfig object found, rs_remotehandler will not run");
errh_SetStatus(0);
exit(1);
}
// Add all remote transports
AddTransports();
/*
sumsts = 1;
for (i=0; i<tpcount; i++)
{
sts = StartTransport(i);
if (sts < 0) sumsts = sts;
errh_Info("Transport %s started by remotehandler", tp[i].path);
}
if (sumsts < 0)
errh_Warning("All transports started, at least one failed");
else
errh_Info("All transports started");
*/
new_plc = 0;
do {
if (!hotswap) errh_SetStatus(PWR__SRUN);
aproc_TimeStamp();
get.maxSize = sizeof(mp);
get.data = mp;
qcom_Get(&status, &qid, &get, 100); // TMO == 100 ms
if (status == QCOM__TMO || status == QCOM__QEMPTY) {
if (!hotswap) {
cpid = waitpid(-1, &stat_loc, WNOHANG);
for (i=0; i<tpcount; i++) {
if (tp[i].cpid == -1 || cpid == tp[i].cpid) {
sts = StartTransport(i);
// errh_Warning("Transport %s terminated, restarted by remotehandler", tp[i].path);
}
}
}
}
else {
ini_mEvent new_event;
qcom_sEvent *ep = (qcom_sEvent *) get.data;
new_event.m = ep->mask;
if (new_event.b.swapInit && !hotswap) {
hotswap = 1;
errh_SetStatus(PWR__SRVRESTART);
for (i=0; i<tpcount; i++) {
if (tp[i].cpid > 0) {
kill(tp[i].cpid, 9);
cpid = waitpid(tp[i].cpid, &stat_loc, 0);
if (cpid != tp[i].cpid) {
errh_Error("Error in waitpid, exiting");
errh_SetStatus(PWR__SRVTERM);
exit(1);
}
tp[i].cpid = -1;
}
}
}
if (new_event.b.swapDone && hotswap) {
hotswap = 0;
new_plc = 1;
}
if (new_event.b.terminate) {
for (i=0; i<tpcount; i++) {
if (tp[i].cpid > 0) {
kill(tp[i].cpid, 9);
cpid = waitpid(tp[i].cpid, &stat_loc, 0);
if (cpid != tp[i].cpid) {
errh_Error("Error in waitpid, exiting");
errh_SetStatus(PWR__SRVTERM);
exit(1);
}
tp[i].cpid = -1;
}
}
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
qcom_Free(&sts, get.data);
}
} while (!new_plc);
}
}
include $(pwre_dir_symbols)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(hw_name)/$(type_name)_generic.mk
ifeq ($($(type_name)_generic_mk),)
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(type_name)_generic.mk
endif
ifeq ($($(type_name)_generic_mk),)
include $(pwre_kroot)/tools/bld/src/$(type_name)_generic.mk
endif
/*
* Proview $Id: remote.h,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define even(x) (((int)(x) & 1) == 0)
#define max(Dragon,Eagle) ((Dragon) > (Eagle) ? (Dragon) : (Eagle))
#define min(Dragon,Eagle) ((Dragon) < (Eagle) ? (Dragon) : (Eagle))
#ifndef __ALPHA
#define abs(Dragon) ((Dragon) >= 0 ? (Dragon) : (-(Dragon)))
#endif
#define true 1
#define false 0
#define TRUE 1
#define FALSE 0
#define doomsday false
#define REMTRANS_UNDEF 0
#define REMTRANS_IO 1
#define REMTRANS_APPL 2
#define REMTRANS_IN 1
#define REMTRANS_OUT 2
#define RT_TIMEREXP 1
#define RT_ERROR 2
#define RT_RECEIVE 3
#define RS_PWR_LOGG_Procno 90 /* RemTransLogg Processnumber */
#define RS_PWR_LOGG_Type 90 /* RemTransLogg message Type */
#define RS_PWR_LOGG_Class 90 /* RemTransLogg message Class */
#define RS_PWR_LOGG_RemTransId 90 /* RemTransLogg RemTrans Identifier */
#define rs_pwr_logg_qix (1<<31 | 1000)
#define STATUS_FELSEND 0 /* Send was not successfull */
#define STATUS_OK 1 /* All is well */
#define STATUS_LENGTH 2 /* Too big data receive or send */
#define STATUS_BUFF 3 /* Receive data has been buffered */
#define STATUS_LOST 4 /* Receive data has been lost */
#define STATUS_BUFACK 6 /* Sent, wait for ack */
#define PSS_UPD_DV 1 /* Order new value Rem Dv */
#define PSS_UPD_DO 2 /* Order new value Rem Do */
#define PSS_UPD_AO 3 /* Order new value Rem Ao */
#define PSS_Switch_Init 5 /* PLC Switch is coming. Keep stall */
#define PSS_Switch_Done 6 /* Restart. Reinstate ordinary stall */
#define PSS_Follow_On 7 /* To much data. Next telegram is follow on */
#define MAX_ORDER_BUFFERSIZE 108 /* 124 bytes including header */
#define MAX_IO_BUFFERSIZE 1422 /* 1440 bytes including header */
#define MAX_ORDERS_DATASIZE 72 /* More than enough for orders */
#define MAX_ORDER_BUFFERSIZE_VNET 116 /* 128 bytes including header */
#define MAX_RECEIVE_BUFFERSIZE_VNET 256 /* For update of IO and common */
typedef struct {
short int trans_code;
short int common_name[2];
short int di_offset; /* Byte offset from here to number of di */
short int do_offset; /* Byte offset from here to number of do */
short int dv_offset; /* Byte offset from here to number of dv */
short int ai_offset; /* Byte offset from here to number of ai */
short int ao_offset; /* Byte offset from here to number of ao */
short int co_offset; /* Byte offset from here to number of co */
unsigned char data[MAX_IO_BUFFERSIZE]; /* Data :
short int Number of bytes for di-area
unsigned char Di-area Number of di / 8 bytes
short int Number of bytes for do-area
unsigned char Do-area Number of do / 8 bytes
short int Number of bytes for dv-area
unsigned char Dv-area Number of dv / 8 bytes
short int Number of ai
short int Ai-area not used
short int Ai-area Raw-value
short int Number of ao
short int Ao-area Raw-value
short int Number of co
int Co-area not used
int Co-area Raw-value */
} bsp_buffer;
typedef struct {
unsigned char type; /* DV = 1, DO = 2, AO = 3 , Switch = 5*/
unsigned char size; /* DV,DO = 0 (puls) AO = 2 (size) */
short int signal; /* Channel number */
} pssupd_order_header;
typedef struct {
short int transcode;
short int future_use;
short int length; /* Number of bytes in buffer */
short int receive_task[2];/* Task to receive orders */
short int common_name[2]; /* Task to receive orders */
short int no_of_updates; /* Number of orders */
unsigned char data[MAX_ORDER_BUFFERSIZE];
} pssupd_buffer;
typedef struct {
short int length; /* Number of words in buffer */
short int receive_task[2];/* Task to receive orders */
short int common_name[2]; /* Task to receive orders */
short int no_of_updates; /* Number of orders */
unsigned char data[MAX_ORDER_BUFFERSIZE_VNET];
} pssupd_buffer_vnet;
typedef struct {
short int length;
short int common_name[2];
short int offset;
unsigned char data[MAX_RECEIVE_BUFFERSIZE_VNET];
} common_buffer_vnet;
typedef struct {
short int length;
short int io_name[2];
unsigned char data[MAX_RECEIVE_BUFFERSIZE_VNET];
} io_buffer_vnet;
typedef struct {
pwr_sClass_RemChan_Di *objp; /* Pointer to RemChanDi-object */
pwr_tBoolean *actval; /* Pointer to DI_VALUE_BASE */
void *next; /* Pointer to next remdi_item */
} remdi_item;
typedef struct {
pwr_sClass_RemChan_Do *objp; /* Pointer to RemChanDo-object */
pwr_tBoolean *actval; /* Pointer to DO_VALUE_BASE */
void *next; /* Pointer to next remdo_item */
} remdo_item;
typedef struct {
pwr_sClass_RemChan_Dv *objp; /* Pointer to RemChanDv-object */
pwr_tBoolean *actval; /* Pointer to DV_VALUE_BASE */
void *next; /* Pointer to next remdv_item */
} remdv_item;
typedef struct {
pwr_sClass_RemChan_Ai *objp; /* Pointer to RemChanAi-object */
pwr_tFloat32 *actval; /* Pointer to AI_VALUE_BASE */
short int *rawval; /* Pointer to rawvalue in Ai-object */
void *next; /* Pointer to next remai_item */
} remai_item;
typedef struct {
pwr_sClass_RemChan_Ao *objp; /* Pointer to RemChanAo-object */
pwr_tFloat32 *actval; /* Pointer to AO_VALUE_BASE */
short int *rawval; /* Pointer to rawvalue in Ao-object */
void *next; /* Pointer to next remao_item */
} remao_item;
typedef struct {
pwr_sClass_RemChan_Co *objp; /* Pointer to RemChanCo-object */
pwr_tInt32 *actval; /* Pointer to CA_VALUE_BASE */
pwr_tInt32 *extval; /* Pointer to CO_VALUE_BASE */
void *next; /* Pointer to next remco_item */
} remco_item;
typedef struct {
pwr_sClass_RemTrans *objp; /* Pointer to RemTrans-object */
pwr_tObjid objid; /* RemTrans Objid */
char *datap; /* Pointer to Data-object */
void *next; /* Pointer to next remtrans_item */
void *buffp; /* Pointer to first buffered trans */
/* typecast to struct rem_t_transbuff */
pwr_tFloat32 time_since_send; /* Time since last send */
} remtrans_item;
typedef struct {
void *next; /* Pointer to next buffer */
void *remtrans; /* Pointer to remtrans _item */
/* typecast to struct remtrans_item */
int size; /* Number of bytes in data below */
int ackbuf; /* Buffered because of wait for ack */
char data; /* Dataarea */
} rem_t_transbuff;
typedef struct {
void *next; /* Pointer to next remnode */
void *local; /* Pointer to optional local data structure */
pwr_tObjid objid; /* ObjId of RemNode */
pwr_sClass_MultiCast *multicast; /* Pointer to (first) MultiCast-object under RemNode */
/* Elements for remtrans use */
remtrans_item *remtrans; /* Pointer to first remtrans_item */
rem_t_transbuff *transbuff; /* Pointer to first buffered trans */
pwr_tFloat32 retransmit_time; /* Time to wait until retransmitting */
pwr_tStatus laststs; /* Last send status */
/* Elements for remio use */
char *remio_data; /* Pointer to remio primary data */
int remio_size; /* Size of primary data bufferobject */
pwr_tStatus remio_err; /* Error message has been sent */
remdi_item *remdi; /* Pointer to first remdi_item */
remdo_item *remdo; /* Pointer to first remdo_item */
remdv_item *remdv; /* Pointer to first remdv_item */
remai_item *remai; /* Pointer to first remai_item */
remao_item *remao; /* Pointer to first remao_item */
remco_item *remco; /* Pointer to first remdco_item */
int maxremdi; /* Number of Di in subsystem */
int maxremdo; /* Number of Do in subsystem */
int maxremdv; /* Number of Me in subsystem */
int maxremai; /* Number of Ai in subsystem */
int maxremao; /* Number of Ao in subsystem */
int maxremco; /* Number of Pi in subsystem */
} remnode_item;
/*
* Proview $Id: remote_mq.h,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef remote_mq_h
#define remote_mq_h
/* remote_mq.h -- Runtime environment - Message Queue
*/
/* Define types used by PAMS */
#if defined(OS_VMS) || defined(OS_ELN)
#ifndef __INTS_LOADED
#ifdef __DECC
#include <ints.h>
#else
#define __INTS_LOADED 1
typedef char int8;
typedef unsigned char uint8;
typedef short int16;
typedef unsigned short uint16;
#if defined(__alpha) && defined(__osf__)
typedef signed int int32;
typedef unsigned int uint32;
#else
typedef long int32;
typedef unsigned long uint32;
#endif /* __alpha && __osf__ */
#endif /* __DECC */
#endif /* __INTS_LOADED */
/* In PAMS 'queue' is named 'process', so do a fix */
#ifdef OS_ELN
typedef union {
unsigned long all;
struct {
unsigned short queue;
unsigned short group;
} au;
} PAMS_ADDRESS;
#define PAMS_ADDRESS_DEFINED
#else
/* Include p_entry.h otherwise we won't get any prototypes */
#include "p_entry.h"
#endif
#include pams_c_process
#include pams_c_group
#include pams_c_type_class
#include pams_c_return_status_def
#include pams_c_symbol_def
#include pams_c_entry_point
#include avail_msg_def
#include sbs_msg_def
typedef union {
unsigned long All;
struct {
unsigned short Queue;
unsigned short Group;
} au;
} mq_uAddress;
pwr_tStatus mq_AttachQueue (
mq_uAddress *RequestedAddress,
mq_uAddress *Address
);
#endif
#endif
/*
* Proview $Id: remote_remio_utils.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*************************************************************************
*
* Filename: remio_utils.c
*
* Date Pgm. Read. Remark
* Modified
*
* Description: Remote I/O utilities
*
**************************************************************************/
/*_Include files_________________________________________________________*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "pwr_class.h"
#include "pwrs_c_node.h"
#include "rt_gdh.h"
#include "co_cdh.h"
#include "pwr_baseclasses.h"
#include "pwr_remoteclasses.h"
#include "rs_remote_msg.h"
#include "remote.h"
#include "remote_remio_utils.h"
/*************************************************************************
**************************************************************************
*
* Name : Functions that converts raw values for AI and AO to actual values
* and vice versa.
*
***************************************************************************
**************************************************************************/
pwr_tFloat32 ConvAItoAct(pwr_tInt16 raw, pwr_sClass_RemChan_Ai *body)
{
pwr_tFloat32 fraw;
pwr_tFloat32 actval;
double dval;
fraw = raw;
if (body->SensorPolyType == 1)
actval = body->SensorPolyCoef0 + body->SensorPolyCoef1*fraw;
else if (body->SensorPolyType == 2)
actval = body->SensorPolyCoef0 +
fraw * (body->SensorPolyCoef1 + body->SensorPolyCoef2 * fraw);
else if (body->SensorPolyType == 3) {
dval = body->SensorPolyCoef0 + body->SensorPolyCoef1*fraw;
if (dval >= 0) actval = body->SensorPolyCoef2 * sqrt(dval);
else actval = 0;
}
else if (body->SensorPolyType == 4) {
dval = body->SensorPolyCoef0 + body->SensorPolyCoef1*fraw;
if (dval >= 0) actval = body->SensorPolyCoef2 * sqrt(dval);
else actval = -body->SensorPolyCoef2 * sqrt(-dval);
}
else actval = fraw;
return actval;
}
/************************************************************/
pwr_tFloat32 ConvAOtoAct(pwr_tInt16 raw, pwr_sClass_RemChan_Ao *body)
{
pwr_tFloat32 fraw;
pwr_tFloat32 actval;
fraw = raw;
if (body->OutPolyCoef1 != 0.0)
actval = (fraw - body->OutPolyCoef0)/body->OutPolyCoef1;
else actval = body->OutMinLimit;
return actval;
}
/************************************************************/
pwr_tInt16 ConvAOtoRaw(pwr_tFloat32 act, pwr_sClass_RemChan_Ao *body)
{
pwr_tInt16 raw;
pwr_tFloat32 actval;
if (act > body->OutMaxLimit) actval = body->OutMaxLimit;
else if (act < body->OutMinLimit) actval = body->OutMinLimit;
else actval = act;
raw = body->OutPolyCoef0 + body->OutPolyCoef1 * actval;
return raw;
}
/*************************************************************************
**************************************************************************
*
* Name : RemIO_Init_ALCM
*
* Typ : pwr_tStatus
*
* Input : Pointer to struct remnode_item with objid and objp
*
* Description : Search for all RemChan_xx under rem_node
*
**************************************************************************
**************************************************************************/
pwr_tStatus RemIO_Init_ALCM(remnode_item *remnode)
{
pwr_tObjid childobjid, chanobjid, sigobjid;
pwr_tClassId class;
pwr_sClass_Di *dip;
pwr_sClass_Do *dop;
pwr_sClass_Dv *dvp;
pwr_sClass_Ai *aip;
pwr_sClass_Ao *aop;
pwr_sClass_Co *cop;
pwr_sClass_RemChan_Di *chandip;
pwr_sClass_RemChan_Dv *chandvp;
pwr_sClass_RemChan_Do *chandop;
pwr_sClass_RemChan_Ai *chanaip;
pwr_sClass_RemChan_Ao *chanaop;
pwr_sClass_RemChan_Co *chancop;
remdi_item *remdi;
remdo_item *remdo;
remdv_item *remdv;
remai_item *remai;
remao_item *remao;
remco_item *remco;
pwr_tStatus sts;
pwr_sClass_RemnodeALCM *objp;
/* Get pointer to remnodeALCM-object */
sts = gdh_ObjidToPointer(remnode->objid, (pwr_tAddress *) &objp);
/* Initialize remnode_item and RemNode-object*/
remnode->remdi = remdi = NULL;
remnode->remdo = remdo = NULL;
remnode->remdv = remdv = NULL;
remnode->remai = remai = NULL;
remnode->remao = remao = NULL;
remnode->remco = remco = NULL;
remnode->remio_data = NULL;
remnode->maxremdi = objp->NumberOfDI = 0;
remnode->maxremdo = objp->NumberOfDO = 0;
remnode->maxremdv = objp->NumberOfDV = 0;
remnode->maxremai = objp->NumberOfAI = 0;
remnode->maxremao = objp->NumberOfAO = 0;
remnode->maxremco = objp->NumberOfCo = 0;
objp->IOPollDiff = 0;
objp->IOStallFlag = FALSE;
remnode->remio_err = FALSE;
/* Get I/O dataarea for RemIO */
chanobjid = objp->IODataArea;
sts = gdh_ObjidToPointer(chanobjid, (pwr_tAddress *) &remnode->remio_data);
if (ODD(sts)) sts = gdh_GetObjectSize(chanobjid,
(unsigned int *) &remnode->remio_size);
else remnode->remio_size = 0;
/* Get first child to RemNode */
sts = gdh_GetChild(remnode->objid, &childobjid);
while (ODD(sts)) {
/* Test type of object */
sts = gdh_GetObjectClass(childobjid, &class);
switch (class) {
/* Search for RemChanDi with Di-connection */
case pwr_cClass_RemDi: {
sts = gdh_GetChild(childobjid, &chanobjid);
while (ODD(sts)) {
sts = gdh_GetObjectClass(chanobjid, &class);
if (class == pwr_cClass_RemChan_Di) {
sts = gdh_ObjidToPointer(chanobjid, (pwr_tAddress *) &chandip);
if (ODD(sts)) {
sigobjid = chandip->SigChanCon;
sts = gdh_GetObjectClass(sigobjid, &class);
if (class == pwr_cClass_Di) {
sts = gdh_ObjidToPointer(sigobjid, (pwr_tAddress *) &dip);
/* Create new item and link it */
remdi = malloc(sizeof(remdi_item));
if (remdi == 0) exit(REM__NOMEMORY);
remdi->next = (struct remdi_item *) remnode->remdi;
remnode->remdi = remdi;
/* Initialize remdi_item */
objp->NumberOfDI++;
remdi->objp = chandip;
remdi->actval = (pwr_tBoolean *) gdh_TranslateRtdbPointer(
(pwr_tUInt32) dip->ActualValue);
if (class == pwr_cClass_Di)
chandip->ActualValue = dip->ActualValue;
remdi->objp->BuffOff = remdi->objp->ConvOff / 8;
remdi->objp->ConvMask = 1 << (remdi->objp->ConvOff % 8);
} /* END ClassDi */
} /* END Object Di */
} /* END Class RemChanDi */
sts = gdh_GetNextSibling(chanobjid, &chanobjid);
} /* END while RemChanDi under RemDi */
break;
} /* END case RemDi */
/* Search for RemChanD0 with Do-connection */
case pwr_cClass_RemDo: {
sts = gdh_GetChild(childobjid, &chanobjid);
while (ODD(sts)) {
sts = gdh_GetObjectClass(chanobjid, &class);
if (class == pwr_cClass_RemChan_Do) {
sts = gdh_ObjidToPointer(chanobjid, (pwr_tAddress *) &chandop);
if (ODD(sts)) {
sigobjid = chandop->SigChanCon;
sts = gdh_GetObjectClass(sigobjid, &class);
if (class == pwr_cClass_Do) {
sts = gdh_ObjidToPointer(sigobjid, (pwr_tAddress *) &dop);
/* Create new item and link it */
remdo = malloc(sizeof(remdo_item));
if (remdo == 0) exit(REM__NOMEMORY);
remdo->next = (struct remdo_item *) remnode->remdo;
remnode->remdo = remdo;
/* Initialize remdo_item */
objp->NumberOfDO++;
remdo->objp = chandop;
remdo->actval = gdh_TranslateRtdbPointer(
(pwr_tUInt32) dop->ActualValue);
if (class == pwr_cClass_Do)
chandop->ActualValue = dop->ActualValue;
remdo->objp->BuffOff = remdo->objp->ConvOff / 8;
remdo->objp->ConvMask = 1 << (remdo->objp->ConvOff % 8);
remdo->objp->OldValue = *remdo->actval;
} /* END Class Do */
} /* END Object Do */
} /* END Class RemChanDo */
sts = gdh_GetNextSibling(chanobjid, &chanobjid);
} /* END while RemChanDo under RemDo */
break;
} /* END case RemDo */
/* Search for RemChanDv with Dv-connection */
case pwr_cClass_RemDv: {
sts = gdh_GetChild(childobjid, &chanobjid);
while (ODD(sts)) {
sts = gdh_GetObjectClass(chanobjid, &class);
if (class == pwr_cClass_RemChan_Dv) {
sts = gdh_ObjidToPointer(chanobjid, (pwr_tAddress *) &chandvp);
if (ODD(sts)) {
sigobjid = chandvp->SigChanCon;
sts = gdh_GetObjectClass(sigobjid, &class);
if (class == pwr_cClass_Dv) {
sts = gdh_ObjidToPointer(sigobjid, (pwr_tAddress *) &dvp);
/* Create new item and link it */
remdv = malloc(sizeof(remdv_item));
if (remdv == 0) exit(REM__NOMEMORY);
remdv->next = (struct remdv_item *) remnode->remdv;
remnode->remdv = remdv;
/* Initialize Dv, RemChanDv and remdv_item */
objp->NumberOfDV++;
remdv->objp = chandvp;
remdv->actval = gdh_TranslateRtdbPointer(
(pwr_tUInt32) dvp->ActualValue);
chandvp->ActualValue = dvp->ActualValue;
remdv->objp->OldValue = *remdv->actval;
remdv->objp->BuffOff = remdv->objp->ConvOff / 8;
remdv->objp->ConvMask = 1 << (remdv->objp->ConvOff % 8);
} /* END Class Dv */
} /* END Object Dv */
} /* END Class RemChanDv */
sts = gdh_GetNextSibling(chanobjid, &chanobjid);
} /* END while RemChanDv under RemDv */
break;
} /* END case RemDv */
/* Search for RemChanAi with Ai-connection */
case pwr_cClass_RemAi: {
sts = gdh_GetChild(childobjid, &chanobjid);
while (ODD(sts)) {
sts = gdh_GetObjectClass(chanobjid, &class);
if (class == pwr_cClass_RemChan_Ai) {
sts = gdh_ObjidToPointer(chanobjid, (pwr_tAddress *) &chanaip);
if (ODD(sts)) {
sigobjid = chanaip->SigChanCon;
sts = gdh_GetObjectClass(sigobjid, &class);
if (class == pwr_cClass_Ai) {
sts = gdh_ObjidToPointer(sigobjid, (pwr_tAddress *) &aip);
/* Create new item and link it */
remai = malloc(sizeof(remai_item));
if (remai == 0) exit(REM__NOMEMORY);
remai->next = (struct remai_item *) remnode->remai;
remnode->remai = remai;
/* Initialize Ai, RemChanAi and remai_item */
objp->NumberOfAI++;
remai->objp = chanaip;
remai->actval = (pwr_tFloat32 *) gdh_TranslateRtdbPointer(
(pwr_tUInt32) aip->ActualValue);
chanaip->ActualValue = aip->ActualValue;
remai->rawval = (short int *) &aip->RawValue;
} /* END Class Ai */
} /* END Object Ai */
} /* END Class RemChanAi */
sts = gdh_GetNextSibling(chanobjid, &chanobjid);
} /* END while RemChanAi under RemAi */
break;
} /* END case RemAi */
/* Search for RemChanAo with Ao-connection */
case pwr_cClass_RemAo: {
sts = gdh_GetChild(childobjid, &chanobjid);
while (ODD(sts)) {
sts = gdh_GetObjectClass(chanobjid, &class);
if (class == pwr_cClass_RemChan_Ao) {
sts = gdh_ObjidToPointer(chanobjid, (pwr_tAddress *) &chanaop);
if (ODD(sts)) {
sigobjid = chanaop->SigChanCon;
sts = gdh_GetObjectClass(sigobjid, &class);
if (class == pwr_cClass_Ao) {
sts = gdh_ObjidToPointer(sigobjid, (pwr_tAddress *) &aop);
/* Create new item and link it */
remao = malloc(sizeof(remao_item));
if (remao == 0) exit(REM__NOMEMORY);
remao->next = (struct remao_item *) remnode->remao;
remnode->remao = remao;
/* Initialize Ao, RemChanAo and remao_item */
objp->NumberOfAO++;
remao->objp = chanaop;
remao->actval = (pwr_tFloat32 *) gdh_TranslateRtdbPointer(
(pwr_tUInt32) aop->ActualValue);
chanaop->ActualValue = aop->ActualValue;
remao->rawval = (short int *)&aop->RawValue;
remao->objp->OldValue = aop->RawValue;
} /* END Class Ao */
} /* END Object Ao */
} /* END Class RemChanAo */
sts = gdh_GetNextSibling(chanobjid, &chanobjid);
} /* END while RemChanAo under RemAo */
break;
} /* END case RemAo */
/* Search for RemChanCo with Co-connection */
case pwr_cClass_RemCo: {
sts = gdh_GetChild(childobjid, &chanobjid);
while (ODD(sts)) {
sts = gdh_GetObjectClass(chanobjid, &class);
if (class == pwr_cClass_RemChan_Co) {
sts = gdh_ObjidToPointer(chanobjid, (pwr_tAddress *) &chancop);
if (ODD(sts)) {
sigobjid = chancop->SigChanCon;
sts = gdh_GetObjectClass(sigobjid, &class);
if (class == pwr_cClass_Co) {
sts = gdh_ObjidToPointer(sigobjid, (pwr_tAddress *) &cop);
/* Create new item and link it */
remco = malloc(sizeof(remco_item));
if (remco == 0) exit(REM__NOMEMORY);
remco->next = (struct remco_item *) remnode->remco;
remnode->remco = remco;
/* Initialize Co, RemChanCo and remco_item */
objp->NumberOfCo++;
remco->objp = chancop;
remco->extval = (pwr_tInt32 *) gdh_TranslateRtdbPointer(
(pwr_tUInt32) cop->AbsValue);
chancop->ExtendedValue = cop->AbsValue;
remco->actval = (pwr_tInt32 *) gdh_TranslateRtdbPointer(
(pwr_tUInt32) cop->RawValue);
chancop->ActualValue = cop->RawValue;
} /* END Class Co */
} /* END Object Co */
} /* END Class RemChanCo */
sts = gdh_GetNextSibling(chanobjid, &chanobjid);
} /* END while RemChanCo under RemCo */
break;
} /* END case RemCo */
} /* END switch */
/* Get next child under RemNode */
sts = gdh_GetNextSibling(childobjid, &childobjid);
} /* END while */
return(1);
}
/*************************************************************************
**************************************************************************
*
* Name : RemIO_Stall_ALCM
*
* Typ : pwr_tStatus
*
* Input : Pointer to struct remnode_item with objid and objp
*
* Description : Action made when remote IO stalls
*
**************************************************************************
**************************************************************************/
pwr_tStatus RemIO_Stall_ALCM(remnode_item *remnode)
{
remdi_item *remdi;
remdo_item *remdo;
remdv_item *remdv;
remai_item *remai;
remao_item *remao;
pwr_sClass_RemnodeALCM *objp;
pwr_tStatus sts;
/* Get pointer to remnodeALCM-object */
sts = gdh_ObjidToPointer(remnode->objid, (pwr_tAddress *) &objp);
/* Set StallFlag */
if ( !objp->IOStallFlag) {
objp->IOStallFlag = TRUE;
/* Clear Remote signals according to IOStallAction */
if (objp->IOStallAction >= 2) {
remdi = remnode->remdi;
while (remdi != 0) {
*remdi->actval = FALSE;
remdi = (remdi_item *) remdi->next;
} /* END while */
remdo = remnode->remdo;
while (remdo != 0) {
if (!remdo->objp->PwrIsMaster) *remdo->actval = FALSE;
remdo = (remdo_item *) remdo->next;
} /* END while */
remdv = remnode->remdv;
while (remdv != 0) {
if (!remdv->objp->PwrIsMaster) *remdv->actval = FALSE;
remdv = (remdv_item *) remdv->next;
} /* END while */
remai = remnode->remai;
while(remai) {
*remai->rawval = 0;
*remai->actval = ConvAItoAct(*remai->rawval, remai->objp);
remai = (remai_item *) remai->next;
} /* END while */
remao = remnode->remao;
while(remao) {
if (!remao->objp->PwrIsMaster) {
*remao->rawval = 0;
*remao->actval = ConvAOtoAct(*remao->rawval, remao->objp);
}
remao = (remao_item *) remao->next;
} /* END while */
} /* END if (IOStallAction... */
} /* END if new IOStallFlag */
return(1);
}
/*************************************************************************
**************************************************************************
*
* Name : RemIO_Receive_ALCM
*
* Typ : pwr_tStatus
*
* Input : Pointer to struct remnode_item
* Pointer to data buffer
* Size of databuffer
*
* Description : Invoked when I/O-data is received from subsystem.
* Packs up di-, do-, etc channels and store actual values
* in rtdb.
* Transport ALCM
*
**************************************************************************
**************************************************************************/
pwr_tStatus RemIO_Receive_ALCM( remnode_item *remnode,
bsp_buffer *buffer,
int size)
#define MAX16 32767
#define MIN16 -32767
#define MAXCO16 65536
#define MAX24 8388607
#define MIN24 -8388607
#define MAXCO24 16777216
{
char *bytep;
short int *wordp;
int *longp;
remdi_item *remdi;
remdo_item *remdo;
remdv_item *remdv;
remai_item *remai;
remao_item *remao;
remco_item *remco;
int nochan;
pwr_tInt32 longval;
pwr_tInt32 diff;
pwr_tStatus err;
pwr_sClass_RemnodeALCM *objp;
pwr_tStatus sts;
/* Get pointer to remnodeALCM-object */
sts = gdh_ObjidToPointer(remnode->objid, (pwr_tAddress *) &objp);
/* Update IOPollDiff */
objp->IOPollDiff--;
objp->IOStallFlag = FALSE;
err = false;
/* Store data in data-object */
if (remnode->remio_size >= size) memcpy(remnode->remio_data, buffer, size);
/* Pack up di-bits, set actval */
bytep = (char *) &buffer->di_offset + buffer->di_offset;
wordp = (short int *) bytep;
nochan = *wordp;
remnode->maxremdi = nochan * 8;
bytep += 2;
remdi = remnode->remdi;
while (remdi != 0) {
if (remdi->objp->BuffOff < nochan) *remdi->actval =
(remdi->objp->ConvMask & *(bytep+remdi->objp->BuffOff)) ? TRUE : FALSE;
else {
err = TRUE;
if (!remnode->remio_err) {
remnode->remio_err = TRUE;
printf(" REMIO fel Di offset %d\n",remdi->objp->ConvOff);
}
}
remdi = (remdi_item *) remdi->next;
} /* END while */
/* Pack up do-bits, set actval if not PwrIsMaster */
bytep = (char *) &buffer->do_offset + buffer->do_offset;
wordp = (short int *) bytep;
nochan = *wordp;
remnode->maxremdo = nochan * 8;
bytep += 2;
remdo = remnode->remdo;
while (remdo != 0) {
if (remdo->objp->BuffOff < nochan) {
remdo->objp->OldValue =
(remdo->objp->ConvMask & *(bytep+remdo->objp->BuffOff)) ? TRUE : FALSE;
if (!remdo->objp->PwrIsMaster) *remdo->actval = remdo->objp->OldValue;
}
else {
err = TRUE;
if (!remnode->remio_err) {
remnode->remio_err = TRUE;
printf(" REMIO fel Do offset %d\n",remdo->objp->ConvOff);
}
}
remdo = (remdo_item *) remdo->next;
} /* END while */
/* Pack up dv-bits, set actval if not PwrIsMaster */
bytep = (char *) &buffer->dv_offset + buffer->dv_offset;
wordp = (short int *) bytep;
nochan = *wordp;
remnode->maxremdv = nochan * 8;
bytep += 2;
remdv = remnode->remdv;
while (remdv != 0) {
if (remdv->objp->BuffOff < nochan) {
remdv->objp->OldValue =
(remdv->objp->ConvMask & *(bytep+remdv->objp->BuffOff)) ? TRUE : FALSE;
if (!remdv->objp->PwrIsMaster) *remdv->actval = remdv->objp->OldValue;
}
else {
err = TRUE;
if (!remnode->remio_err) {
remnode->remio_err = TRUE;
printf(" REMIO fel Dv offset %d\n",remdv->objp->ConvOff);
}
}
remdv = (remdv_item *) remdv->next;
} /* END while */
/*Convert raw AI values to actual values */
bytep = (char *) &buffer->ai_offset + buffer->ai_offset;
wordp = (short int *) bytep;
remnode->maxremai = nochan = *wordp;
/* Stega frbi den oanvnda arean som r lika stor som antalet AI (se dekl av bsp_buffer) */
wordp += nochan+1;
remai = remnode->remai;
while(remai) {
if (remai->objp->ConvOff < nochan) {
*remai->rawval = *(wordp+remai->objp->ConvOff);
*remai->actval = ConvAItoAct(*remai->rawval, remai->objp);
}
else {
err = TRUE;
if (!remnode->remio_err) {
remnode->remio_err = TRUE;
printf(" REMIO fel Ai offset %d\n",remai->objp->ConvOff);
}
}
remai = (remai_item *) remai->next;
} /* END while */
/* Convert raw AO values to actual values, set oldvalue,
set actval if not PwrIsMaster */
bytep = (char *) &buffer->ao_offset + buffer->ao_offset;
wordp = (short int *) bytep;
remnode->maxremao = nochan = *wordp;
wordp++;
remao = remnode->remao;
while(remao) {
if (remao->objp->ConvOff < nochan) {
remao->objp->OldValue = *(wordp+remao->objp->ConvOff);
if (!remao->objp->PwrIsMaster) {
*remao->rawval = remao->objp->OldValue;
*remao->actval = ConvAOtoAct(*remao->rawval, remao->objp);
}
}
else {
err = TRUE;
if (!remnode->remio_err) {
remnode->remio_err = TRUE;
printf(" REMIO fel Ao offset %d\n",remao->objp->ConvOff);
}
}
remao = (remao_item *) remao->next;
} /* END while */
/* Store Co values in COVALUEBASE and CAVALUEBASE */
bytep = (char *) &buffer->co_offset + buffer->co_offset;
wordp = (short int *) bytep;
remnode->maxremco = nochan = *wordp;
wordp++;
longp = (int *) wordp;
longp += nochan;
remco = remnode->remco;
while(remco) {
if (remco->objp->ConvOff < nochan) {
longval = *(longp+remco->objp->ConvOff);
diff = longval - *remco->actval;
/* 16-bit counter ??? */
if (remco->objp->NoOfBits == 16) {
if (diff < MIN16) diff += MAXCO16;
else if (diff > MAX16) diff -= MAXCO16;
}
/* 24-bit counter */
else {
if (diff < MIN24) diff += MAXCO24;
else if (diff > MAX24) diff -= MAXCO24;
}
/* Add differens and save value */
*remco->extval += diff;
*remco->actval = longval;
}
else {
err = TRUE;
if (!remnode->remio_err) {
err = remnode->remio_err = TRUE;
printf(" REMIO fel Co offset %d\n",remco->objp->ConvOff);
}
}
remco = (remco_item *) remco->next;
} /* END while */
/* Was all remote I/O inside buffer ? */
if (!err && remnode->remio_err) {
printf("Remote I/O node is OK again !\n");
}
remnode->remio_err = err;
return(1);
}
/*************************************************************************
**************************************************************************
*
* Name : RemIO_Cyclic_ALCM
*
* Typ : pwr_tStatus
*
* Input : Pointer to remnode_item
*
* Description : Invoked when the cycle timer expires for any remNode.
* Transport ALCM
*
**************************************************************************
**************************************************************************/
pwr_tStatus RemIO_Cyclic_ALCM( remnode_item *remnode,
void (* send_pollbuff)
(remnode_item *remnode,
pssupd_buffer *buf))
{
remdo_item *remdo;
remdv_item *remdv;
remao_item *remao;
pssupd_buffer askbuff;
pssupd_order_header *buffhead;
unsigned char buffdata[MAX_ORDERS_DATASIZE];
unsigned char *datap;
unsigned int buffsize, datasize;
pwr_sClass_RemnodeALCM *objp;
pwr_tStatus sts;
/* Get pointer to remnodeALCM-object */
sts = gdh_ObjidToPointer(remnode->objid, (pwr_tAddress *) &objp);
/* Step through do, dv and ao to see if they should be
updated remote */
buffhead = (pssupd_order_header *) &askbuff.data;
askbuff.no_of_updates = 0;
datap = buffdata;
datasize = buffsize = 0;
remdo = remnode->remdo;
while(remdo) {
if (remdo->objp->PwrIsMaster && (remdo->objp->ConvOff < remnode->maxremdo)
&& (remdo->objp->OldValue != *remdo->actval)){
if ((buffsize + sizeof(pssupd_order_header) + 1) >
MAX_ORDER_BUFFERSIZE ) {
/* Send buffer and re-initiate it! */
askbuff.length = buffsize + sizeof(pssupd_buffer) -
MAX_ORDER_BUFFERSIZE;
memcpy(buffhead, &buffdata, datasize);
(send_pollbuff) (remnode, &askbuff);
objp->IOPollDiff++;
buffhead = (pssupd_order_header *) &askbuff.data;
askbuff.no_of_updates = 0;
datap = buffdata;
datasize = buffsize = 0;
}
askbuff.no_of_updates++;
buffhead->type = PSS_UPD_DO;
buffhead->size = 0;
buffhead->signal = remdo->objp->ConvOff;
buffhead++;
*datap = *remdo->actval;
datap++;
datasize++;
buffsize += sizeof(pssupd_order_header) + 1;
}
remdo = (remdo_item *) remdo->next;
}
remdv = remnode->remdv;
while(remdv) {
if (remdv->objp->PwrIsMaster && (remdv->objp->ConvOff < remnode->maxremdv)
&& remdv->objp->OldValue != *remdv->actval){
if ((buffsize + sizeof(pssupd_order_header) + 1) >
MAX_ORDER_BUFFERSIZE ) {
/* Send buffer and re-initiate it! */
askbuff.length = buffsize + sizeof(pssupd_buffer) -
MAX_ORDER_BUFFERSIZE;
memcpy(buffhead, &buffdata, datasize);
(send_pollbuff) (remnode, &askbuff);
objp->IOPollDiff++;
buffhead = (pssupd_order_header *) &askbuff.data;
askbuff.no_of_updates = 0;
datap = buffdata;
datasize = buffsize = 0;
}
askbuff.no_of_updates++;
buffhead->type = PSS_UPD_DV;
buffhead->size = 0;
buffhead->signal = remdv->objp->ConvOff;
buffhead++;
*datap = *remdv->actval;
datap++;
datasize++;
buffsize += sizeof(pssupd_order_header) + 1;
}
remdv = (remdv_item *) remdv->next;
}
remao = remnode->remao;
while(remao) {
if (remao->objp->PwrIsMaster && remao->objp->ConvOff < remnode->maxremao) {
*remao->rawval = ConvAOtoRaw( *remao->actval, remao->objp);
if (remao->objp->OldValue != *remao->rawval) {
if ((buffsize + sizeof(pssupd_order_header) + 2) >
MAX_ORDER_BUFFERSIZE ) {
/* Send buffer and re-initiate it! */
askbuff.length = buffsize + sizeof(pssupd_buffer) -
MAX_ORDER_BUFFERSIZE;
memcpy(buffhead, &buffdata, datasize);
(send_pollbuff) (remnode, &askbuff);
objp->IOPollDiff++;
buffhead = (pssupd_order_header *) &askbuff.data;
askbuff.no_of_updates = 0;
datap = buffdata;
datasize = buffsize = 0;
}
askbuff.no_of_updates++;
buffhead->type = PSS_UPD_AO;
buffhead->size = 2;
buffhead->signal = remao->objp->ConvOff;
buffhead++;
*(short int *)datap = *remao->rawval;
datap += 2;
datasize += 2;
buffsize += sizeof(pssupd_order_header) + 2;
}
}
remao = (remao_item *) remao->next;
}
/* Sendbuffer if updates or poll */
if ((askbuff.no_of_updates > 0) || objp->IOPoll) {
askbuff.length = buffsize + sizeof(pssupd_buffer) - MAX_ORDER_BUFFERSIZE;
memcpy(buffhead, &buffdata, datasize); /* Copy data after headers */
(send_pollbuff) (remnode, &askbuff); /* Send orders */
objp->IOPollDiff++;
}
return STATUS_OK;
}
/*************************************************************************
**************************************************************************
*
* Name : RemIO_Init_3964R
*
* Typ : pwr_tStatus
*
* Input : Pointer to struct remnode_item with objid and objp
*
* Description : Search for all RemChan_xx under rem_node
*
**************************************************************************
**************************************************************************/
pwr_tStatus RemIO_Init_3964R(remnode_item *remnode)
{
pwr_tObjid childobjid, chanobjid, sigobjid;
pwr_tClassId class;
pwr_sClass_Di *dip;
pwr_sClass_Do *dop;
pwr_sClass_Dv *dvp;
pwr_sClass_Ai *aip;
pwr_sClass_Ao *aop;
pwr_sClass_Co *cop;
pwr_sClass_RemChan_Di *chandip;
pwr_sClass_RemChan_Dv *chandvp;
pwr_sClass_RemChan_Do *chandop;
pwr_sClass_RemChan_Ai *chanaip;
pwr_sClass_RemChan_Ao *chanaop;
pwr_sClass_RemChan_Co *chancop;
remdi_item *remdi;
remdo_item *remdo;
remdv_item *remdv;
remai_item *remai;
remao_item *remao;
remco_item *remco;
pwr_tStatus sts;
pwr_sClass_Remnode3964R *objp;
char name[80];
/* Get pointer to remnode3964R-object */
sts = gdh_ObjidToPointer(remnode->objid, (pwr_tAddress *) &objp);
/* Initialize remnode_item and RemNode-object*/
remnode->remdi = remdi = NULL;
remnode->remdo = remdo = NULL;
remnode->remdv = remdv = NULL;
remnode->remai = remai = NULL;
remnode->remao = remao = NULL;
remnode->remco = remco = NULL;
remnode->remio_data = NULL;
remnode->maxremdi = 0;
remnode->maxremdo = 0;
remnode->maxremdv = 0;
remnode->maxremai = 0;
remnode->maxremao = 0;
remnode->maxremco = 0;
remnode->remio_err = FALSE;
remnode->remio_size = 0;
objp->LinkUp = 1;
/* Get I/O dataarea */
sts = gdh_GetChild(remnode->objid, &childobjid);
while (ODD(sts)) {
sts = gdh_ObjidToName(childobjid, name, sizeof(name), cdh_mName_object);
if (strstr(name, "IO_AREA")) {
sts = gdh_ObjidToPointer(childobjid, (pwr_tAddress *) &remnode->remio_data);
if (ODD(sts)) sts = gdh_GetObjectSize(childobjid,(unsigned int *) &remnode->remio_size);
break;
}
sts = gdh_GetNextSibling(childobjid, &childobjid);
}
/* Get first child to RemNode */
sts = gdh_GetChild(remnode->objid, &childobjid);
while (ODD(sts)) {
/* Test type of object */
sts = gdh_GetObjectClass(childobjid, &class);
switch (class) {
/* Search for RemChanDi with Di-connection */
case pwr_cClass_RemDi: {
sts = gdh_GetChild(childobjid, &chanobjid);
while (ODD(sts)) {
sts = gdh_GetObjectClass(chanobjid, &class);
if (class == pwr_cClass_RemChan_Di) {
sts = gdh_ObjidToPointer(chanobjid, (pwr_tAddress *) &chandip);
if (ODD(sts)) {
sigobjid = chandip->SigChanCon;
sts = gdh_GetObjectClass(sigobjid, &class);
if (class == pwr_cClass_Di) {
sts = gdh_ObjidToPointer(sigobjid, (pwr_tAddress *) &dip);
/* Create new item and link it */
remdi = malloc(sizeof(remdi_item));
if (remdi == 0) exit(REM__NOMEMORY);
remdi->next = (struct remdi_item *) remnode->remdi;
remnode->remdi = remdi;
/* Initialize remdi_item */
// objp->NumberOfDI++;
remdi->objp = chandip;
remdi->actval = (pwr_tBoolean *) gdh_TranslateRtdbPointer(
(pwr_tUInt32) dip->ActualValue);
if (class == pwr_cClass_Di)
chandip->ActualValue = dip->ActualValue;
remdi->objp->BuffOff = remdi->objp->ConvOff / 8;
remdi->objp->ConvMask = 1 << (remdi->objp->ConvOff % 8);
} /* END ClassDi */
} /* END Object Di */
} /* END Class RemChanDi */
sts = gdh_GetNextSibling(chanobjid, &chanobjid);
} /* END while RemChanDi under RemDi */
break;
} /* END case RemDi */
/* Search for RemChanD0 with Do-connection */
case pwr_cClass_RemDo: {
sts = gdh_GetChild(childobjid, &chanobjid);
while (ODD(sts)) {
sts = gdh_GetObjectClass(chanobjid, &class);
if (class == pwr_cClass_RemChan_Do) {
sts = gdh_ObjidToPointer(chanobjid, (pwr_tAddress *) &chandop);
if (ODD(sts)) {
sigobjid = chandop->SigChanCon;
sts = gdh_GetObjectClass(sigobjid, &class);
if (class == pwr_cClass_Do) {
sts = gdh_ObjidToPointer(sigobjid, (pwr_tAddress *) &dop);
/* Create new item and link it */
remdo = malloc(sizeof(remdo_item));
if (remdo == 0) exit(REM__NOMEMORY);
remdo->next = (struct remdo_item *) remnode->remdo;
remnode->remdo = remdo;
/* Initialize remdo_item */
// objp->NumberOfDO++;
remdo->objp = chandop;
remdo->actval = gdh_TranslateRtdbPointer(
(pwr_tUInt32) dop->ActualValue);
if (class == pwr_cClass_Do)
chandop->ActualValue = dop->ActualValue;
remdo->objp->BuffOff = remdo->objp->ConvOff / 8;
remdo->objp->ConvMask = 1 << (remdo->objp->ConvOff % 8);
remdo->objp->OldValue = *remdo->actval;
} /* END Class Do */
} /* END Object Do */
} /* END Class RemChanDo */
sts = gdh_GetNextSibling(chanobjid, &chanobjid);
} /* END while RemChanDo under RemDo */
break;
} /* END case RemDo */
/* Search for RemChanDv with Dv-connection */
case pwr_cClass_RemDv: {
sts = gdh_GetChild(childobjid, &chanobjid);
while (ODD(sts)) {
sts = gdh_GetObjectClass(chanobjid, &class);
if (class == pwr_cClass_RemChan_Dv) {
sts = gdh_ObjidToPointer(chanobjid, (pwr_tAddress *) &chandvp);
if (ODD(sts)) {
sigobjid = chandvp->SigChanCon;
sts = gdh_GetObjectClass(sigobjid, &class);
if (class == pwr_cClass_Dv) {
sts = gdh_ObjidToPointer(sigobjid, (pwr_tAddress *) &dvp);
/* Create new item and link it */
remdv = malloc(sizeof(remdv_item));
if (remdv == 0) exit(REM__NOMEMORY);
remdv->next = (struct remdv_item *) remnode->remdv;
remnode->remdv = remdv;
/* Initialize Dv, RemChanDv and remdv_item */
// objp->NumberOfDV++;
remdv->objp = chandvp;
remdv->actval = gdh_TranslateRtdbPointer(
(pwr_tUInt32) dvp->ActualValue);
chandvp->ActualValue = dvp->ActualValue;
remdv->objp->OldValue = *remdv->actval;
remdv->objp->BuffOff = remdv->objp->ConvOff / 8;
remdv->objp->ConvMask = 1 << (remdv->objp->ConvOff % 8);
} /* END Class Dv */
} /* END Object Dv */
} /* END Class RemChanDv */
sts = gdh_GetNextSibling(chanobjid, &chanobjid);
} /* END while RemChanDv under RemDv */
break;
} /* END case RemDv */
/* Search for RemChanAi with Ai-connection */
case pwr_cClass_RemAi: {
sts = gdh_GetChild(childobjid, &chanobjid);
while (ODD(sts)) {
sts = gdh_GetObjectClass(chanobjid, &class);
if (class == pwr_cClass_RemChan_Ai) {
sts = gdh_ObjidToPointer(chanobjid, (pwr_tAddress *) &chanaip);
if (ODD(sts)) {
sigobjid = chanaip->SigChanCon;
sts = gdh_GetObjectClass(sigobjid, &class);
if (class == pwr_cClass_Ai) {
sts = gdh_ObjidToPointer(sigobjid, (pwr_tAddress *) &aip);
/* Create new item and link it */
remai = malloc(sizeof(remai_item));
if (remai == 0) exit(REM__NOMEMORY);
remai->next = (struct remai_item *) remnode->remai;
remnode->remai = remai;
/* Initialize Ai, RemChanAi and remai_item */
// objp->NumberOfAI++;
remai->objp = chanaip;
remai->actval = (pwr_tFloat32 *) gdh_TranslateRtdbPointer(
(pwr_tUInt32) aip->ActualValue);
chanaip->ActualValue = aip->ActualValue;
remai->rawval = (short int *) &aip->RawValue;
} /* END Class Ai */
} /* END Object Ai */
} /* END Class RemChanAi */
sts = gdh_GetNextSibling(chanobjid, &chanobjid);
} /* END while RemChanAi under RemAi */
break;
} /* END case RemAi */
/* Search for RemChanAo with Ao-connection */
case pwr_cClass_RemAo: {
sts = gdh_GetChild(childobjid, &chanobjid);
while (ODD(sts)) {
sts = gdh_GetObjectClass(chanobjid, &class);
if (class == pwr_cClass_RemChan_Ao) {
sts = gdh_ObjidToPointer(chanobjid, (pwr_tAddress *) &chanaop);
if (ODD(sts)) {
sigobjid = chanaop->SigChanCon;
sts = gdh_GetObjectClass(sigobjid, &class);
if (class == pwr_cClass_Ao) {
sts = gdh_ObjidToPointer(sigobjid, (pwr_tAddress *) &aop);
/* Create new item and link it */
remao = malloc(sizeof(remao_item));
if (remao == 0) exit(REM__NOMEMORY);
remao->next = (struct remao_item *) remnode->remao;
remnode->remao = remao;
/* Initialize Ao, RemChanAo and remao_item */
// objp->NumberOfAO++;
remao->objp = chanaop;
remao->actval = (pwr_tFloat32 *) gdh_TranslateRtdbPointer(
(pwr_tUInt32) aop->ActualValue);
chanaop->ActualValue = aop->ActualValue;
remao->rawval = (short int *)&aop->RawValue;
remao->objp->OldValue = aop->RawValue;
} /* END Class Ao */
} /* END Object Ao */
} /* END Class RemChanAo */
sts = gdh_GetNextSibling(chanobjid, &chanobjid);
} /* END while RemChanAo under RemAo */
break;
} /* END case RemAo */
/* Search for RemChanCo with Co-connection */
case pwr_cClass_RemCo: {
sts = gdh_GetChild(childobjid, &chanobjid);
while (ODD(sts)) {
sts = gdh_GetObjectClass(chanobjid, &class);
if (class == pwr_cClass_RemChan_Co) {
sts = gdh_ObjidToPointer(chanobjid, (pwr_tAddress *) &chancop);
if (ODD(sts)) {
sigobjid = chancop->SigChanCon;
sts = gdh_GetObjectClass(sigobjid, &class);
if (class == pwr_cClass_Co) {
sts = gdh_ObjidToPointer(sigobjid, (pwr_tAddress *) &cop);
/* Create new item and link it */
remco = malloc(sizeof(remco_item));
if (remco == 0) exit(REM__NOMEMORY);
remco->next = (struct remco_item *) remnode->remco;
remnode->remco = remco;
/* Initialize Co, RemChanCo and remco_item */
// objp->NumberOfCo++;
remco->objp = chancop;
remco->extval = (pwr_tInt32 *) gdh_TranslateRtdbPointer(
(pwr_tUInt32) cop->AbsValue);
chancop->ExtendedValue = cop->AbsValue;
remco->actval = (pwr_tInt32 *) gdh_TranslateRtdbPointer(
(pwr_tUInt32) cop->RawValue);
chancop->ActualValue = cop->RawValue;
} /* END Class Co */
} /* END Object Co */
} /* END Class RemChanCo */
sts = gdh_GetNextSibling(chanobjid, &chanobjid);
} /* END while RemChanCo under RemCo */
break;
} /* END case RemCo */
} /* END switch */
/* Get next child under RemNode */
sts = gdh_GetNextSibling(childobjid, &childobjid);
} /* END while */
return(1);
}
/*************************************************************************
**************************************************************************
*
* Name : RemIO_Stall_3964R
*
* Typ : pwr_tStatus
*
* Input : Pointer to struct remnode_item with objid and objp
*
* Description : Action made when remote IO stalls
*
**************************************************************************
**************************************************************************/
pwr_tStatus RemIO_Stall_3964R(remnode_item *remnode, int stall_action)
{
remdi_item *remdi;
remdo_item *remdo;
remdv_item *remdv;
remai_item *remai;
remao_item *remao;
pwr_sClass_Remnode3964R *objp;
pwr_tStatus sts;
/* Get pointer to remnode-object */
sts = gdh_ObjidToPointer(remnode->objid, (pwr_tAddress *) &objp);
/* Set StallFlag */
if (objp->LinkUp != 0) {
objp->LinkUp = 0;
/* Clear Remote signals according to IOStallAction */
if (stall_action >= 2) {
remdi = remnode->remdi;
while (remdi != 0) {
*remdi->actval = FALSE;
remdi = (remdi_item *) remdi->next;
} /* END while */
remdo = remnode->remdo;
while (remdo != 0) {
if (!remdo->objp->PwrIsMaster) *remdo->actval = FALSE;
remdo = (remdo_item *) remdo->next;
} /* END while */
remdv = remnode->remdv;
while (remdv != 0) {
if (!remdv->objp->PwrIsMaster) *remdv->actval = FALSE;
remdv = (remdv_item *) remdv->next;
} /* END while */
remai = remnode->remai;
while(remai) {
*remai->rawval = 0;
*remai->actval = ConvAItoAct(*remai->rawval, remai->objp);
remai = (remai_item *) remai->next;
} /* END while */
remao = remnode->remao;
while(remao) {
if (!remao->objp->PwrIsMaster) {
*remao->rawval = 0;
*remao->actval = ConvAOtoAct(*remao->rawval, remao->objp);
}
remao = (remao_item *) remao->next;
} /* END while */
} /* END if (IOStallAction... */
} /* END if new IOStallFlag */
return(1);
}
/*************************************************************************
**************************************************************************
*
* Name : RemIO_Receive_3964R
*
* Typ : pwr_tStatus
*
* Input : Pointer to struct remnode_item
* Pointer to data buffer
* Size of databuffer
*
* Description : Invoked when I/O-data is received from subsystem.
* Packs up di-, do-, etc channels and store actual values
* in rtdb.
* Transport 3964R VNET
*
**************************************************************************
**************************************************************************/
pwr_tStatus RemIO_Receive_3964R(remnode_item *remnode,
unsigned char *buffer,
int size)
#define MAX16 32767
#define MIN16 -32767
#define MAXCO16 65536
#define MAX24 8388607
#define MIN24 -8388607
#define MAXCO24 16777216
{
unsigned char *bytep;
short int *wordp;
int *longp;
remdi_item *remdi;
remdo_item *remdo;
remdv_item *remdv;
remai_item *remai;
remao_item *remao;
remco_item *remco;
int nochan;
pwr_tInt32 longval;
pwr_tInt32 diff;
pwr_tStatus err;
/* Update PollDiff etc */
// remnode->objp->PollDiff--;
// remnode->objp->LinkUp = 1;
// remnode->Time_since_IO = 0;
err = false;
/* Store data in data-object */
if (remnode->remio_size >= size) memcpy(remnode->remio_data, buffer, size);
/* Pack up di-bits, set actval */
bytep = buffer;
wordp = (short int *) bytep;
nochan = *wordp * 2; /* Convert to bytes */
remnode->maxremdi = nochan * 8;
bytep += 2;
remdi = remnode->remdi;
while (remdi != 0) {
if (remdi->objp->BuffOff < nochan) *remdi->actval =
(remdi->objp->ConvMask & *(bytep+remdi->objp->BuffOff)) ? TRUE : FALSE;
else {
err = TRUE;
if (!remnode->remio_err) {
remnode->remio_err = TRUE;
printf(" REMIO fel Di offset %d\n",remdi->objp->ConvOff);
}
}
remdi = (remdi_item *) remdi->next;
} /* END while */
/* Pack up do-bits, set actval if not PwrIsMaster */
bytep += nochan;
wordp = (short int *) bytep;
nochan = *wordp * 2; /* Convert to bytes */
remnode->maxremdo = nochan * 8;
bytep += 2;
remdo = remnode->remdo;
while (remdo != 0) {
if (remdo->objp->BuffOff < nochan) {
remdo->objp->OldValue =
(remdo->objp->ConvMask & *(bytep+remdo->objp->BuffOff)) ? TRUE : FALSE;
if (!remdo->objp->PwrIsMaster) *remdo->actval = remdo->objp->OldValue;
}
else {
err = TRUE;
if (!remnode->remio_err) {
remnode->remio_err = TRUE;
printf(" REMIO fel Do offset %d\n",remdo->objp->ConvOff);
}
}
remdo = (remdo_item *) remdo->next;
} /* END while */
/* Pack up dv-bits, set actval if not PwrIsMaster */
bytep += nochan;
wordp = (short int *) bytep;
nochan = *wordp * 2; /* Convert to bytes */
remnode->maxremdv = nochan * 8;
bytep += 2;
remdv = remnode->remdv;
while (remdv != 0) {
if (remdv->objp->BuffOff < nochan) {
remdv->objp->OldValue =
(remdv->objp->ConvMask & *(bytep+remdv->objp->BuffOff)) ? TRUE : FALSE;
if (!remdv->objp->PwrIsMaster) *remdv->actval = remdv->objp->OldValue;
}
else {
err = TRUE;
if (!remnode->remio_err) {
remnode->remio_err = TRUE;
printf(" REMIO fel Dv offset %d\n",remdv->objp->ConvOff);
}
}
remdv = (remdv_item *) remdv->next;
} /* END while */
/*Convert raw AI values to actual values */
bytep += nochan;
wordp = (short int *) bytep;
remnode->maxremai = nochan = *wordp;
bytep += 2;
wordp += 1;
remai = remnode->remai;
while(remai) {
if (remai->objp->ConvOff < nochan) {
*remai->rawval = *(wordp+remai->objp->ConvOff);
*remai->actval = ConvAItoAct(*remai->rawval, remai->objp);
}
else {
err = TRUE;
if (!remnode->remio_err) {
remnode->remio_err = TRUE;
printf(" REMIO fel Ai offset %d\n",remai->objp->ConvOff);
}
}
remai = (remai_item *) remai->next;
} /* END while */
/* Convert raw AO values to actual values, set oldvalue,
set actval if not PwrIsMaster */
bytep += nochan * 2; /* Convert to bytes */
wordp = (short int *) bytep;
remnode->maxremao = nochan = *wordp;
bytep += 2;
wordp += 1;
remao = remnode->remao;
while(remao) {
if (remao->objp->ConvOff < nochan) {
remao->objp->OldValue = *(wordp+remao->objp->ConvOff);
if (!remao->objp->PwrIsMaster) {
*remao->rawval = remao->objp->OldValue;
*remao->actval = ConvAOtoAct(*remao->rawval, remao->objp);
}
}
else {
err = TRUE;
if (!remnode->remio_err) {
remnode->remio_err = TRUE;
printf(" REMIO fel Ao offset %d\n",remao->objp->ConvOff);
}
}
remao = (remao_item *) remao->next;
} /* END while */
/* Store Co values in COVALUEBASE and CAVALUEBASE */
bytep += nochan * 2; /* Convert to bytes */
wordp = (short int *) bytep;
remnode->maxremco = nochan = *wordp;
wordp += 1;
longp = (int *) wordp;
remco = remnode->remco;
while(remco) {
if (remco->objp->ConvOff < nochan) {
longval = *(longp+remco->objp->ConvOff);
diff = longval - *remco->actval;
/* 16-bit counter ??? */
if (remco->objp->NoOfBits == 16) {
if (diff < MIN16) diff += MAXCO16;
else if (diff > MAX16) diff -= MAXCO16;
}
/* 24-bit counter */
else {
if (diff < MIN24) diff += MAXCO24;
else if (diff > MAX24) diff -= MAXCO24;
}
/* Add difference and save value */
*remco->extval += diff;
*remco->actval = longval;
}
else {
err = TRUE;
if (!remnode->remio_err) {
err = remnode->remio_err = TRUE;
printf(" REMIO fel Co offset %d\n",remco->objp->ConvOff);
}
}
remco = (remco_item *) remco->next;
} /* END while */
/* Was all remote I/O inside buffer ? */
if (!err && remnode->remio_err) {
printf("Remote I/O node is OK again !\n");
}
remnode->remio_err = err;
return(1);
}
/*************************************************************************
**************************************************************************
*
* Name : RemIO_Cyclic_3964R
*
* Typ : pwr_tStatus
*
* Input : Pointer to remnode_item
*
* Description : Invoked when the cycle timer expires for the remNode.
* Transport 3964R VNET
*
**************************************************************************
**************************************************************************/
pwr_tStatus RemIO_Cyclic_3964R(remnode_item *remnode,
void (* send_pollbuff)
(remnode_item *remnode,
pssupd_buffer_vnet *buf))
{
remdo_item *remdo;
remdv_item *remdv;
remao_item *remao;
pssupd_buffer_vnet askbuff;
pssupd_order_header *buffhead;
unsigned char buffdata[MAX_ORDERS_DATASIZE];
unsigned char *datap;
unsigned int buffsize, datasize;
/* Step through do, dv and ao to see if they should be
updated remote */
buffhead = (pssupd_order_header *) &askbuff.data;
askbuff.no_of_updates = 0;
datap = buffdata;
datasize = buffsize = 0;
remdo = remnode->remdo;
while(remdo) {
if (remdo->objp->PwrIsMaster && (remdo->objp->ConvOff < remnode->maxremdo)
&& (remdo->objp->OldValue != *remdo->actval)){
if ((buffsize + 2 * (sizeof(pssupd_order_header) + 1) ) >
MAX_ORDER_BUFFERSIZE_VNET ) {
/* Add a follow on telegram header. */
askbuff.no_of_updates++;
buffhead->type = PSS_Follow_On;
buffhead->size = buffhead->signal = 0;
*datap = 0;
buffsize += sizeof(pssupd_order_header) + 1;
/* Send buffer and re-initiate it! */
askbuff.length = (buffsize + sizeof(pssupd_buffer_vnet) -
MAX_ORDER_BUFFERSIZE_VNET + 1) / 2;
buffhead++;
memcpy(buffhead, &buffdata, datasize);
(send_pollbuff) (remnode, &askbuff);
// remnode->objp->PollDiff++;
buffhead = (pssupd_order_header *) &askbuff.data;
askbuff.no_of_updates = 0;
datap = buffdata;
datasize = buffsize = 0;
}
askbuff.no_of_updates++;
buffhead->type = PSS_UPD_DO;
buffhead->size = 0;
buffhead->signal = remdo->objp->ConvOff;
buffhead++;
*datap = *remdo->actval;
datap++;
datasize++;
buffsize += sizeof(pssupd_order_header) + 1;
}
remdo = (remdo_item *) remdo->next;
}
remdv = remnode->remdv;
while(remdv) {
if (remdv->objp->PwrIsMaster && (remdv->objp->ConvOff < remnode->maxremdv)
&& remdv->objp->OldValue != *remdv->actval){
if ((buffsize + 2 * (sizeof(pssupd_order_header) + 1) ) >
MAX_ORDER_BUFFERSIZE_VNET ) {
/* Add a follow on telegram header. */
askbuff.no_of_updates++;
buffhead->type = PSS_Follow_On;
buffhead->size = buffhead->signal = 0;
*datap = 0;
buffsize += sizeof(pssupd_order_header) + 1;
/* Send buffer and re-initiate it! */
askbuff.length = (buffsize + sizeof(pssupd_buffer_vnet) -
MAX_ORDER_BUFFERSIZE_VNET + 1) / 2;
buffhead++;
memcpy(buffhead, &buffdata, datasize);
(send_pollbuff) (remnode, &askbuff);
// remnode->objp->PollDiff++;
buffhead = (pssupd_order_header *) &askbuff.data;
askbuff.no_of_updates = 0;
datap = buffdata;
datasize = buffsize = 0;
}
askbuff.no_of_updates++;
buffhead->type = PSS_UPD_DV;
buffhead->size = 0;
buffhead->signal = remdv->objp->ConvOff;
buffhead++;
*datap = *remdv->actval;
datap++;
datasize++;
buffsize += sizeof(pssupd_order_header) + 1;
}
remdv = (remdv_item *) remdv->next;
}
remao = remnode->remao;
while(remao) {
if (remao->objp->PwrIsMaster && remao->objp->ConvOff < remnode->maxremao) {
*remao->rawval = ConvAOtoRaw( *remao->actval, remao->objp);
if (remao->objp->OldValue != *remao->rawval) {
if ((buffsize + 2 * (sizeof(pssupd_order_header) + 2) ) >
MAX_ORDER_BUFFERSIZE_VNET ) {
/* Add a follow on telegram header. */
askbuff.no_of_updates++;
buffhead->type = PSS_Follow_On;
buffhead->size = buffhead->signal = 0;
*(short int *)datap = 0;
buffsize += sizeof(pssupd_order_header) + 2;
/* Send buffer and re-initiate it! */
askbuff.length = (buffsize + sizeof(pssupd_buffer_vnet) -
MAX_ORDER_BUFFERSIZE_VNET + 1) / 2;
buffhead++;
memcpy(buffhead, &buffdata, datasize);
(send_pollbuff) (remnode, &askbuff);
// remnode->objp->PollDiff++;
buffhead = (pssupd_order_header *) &askbuff.data;
askbuff.no_of_updates = 0;
datap = buffdata;
datasize = buffsize = 0;
}
askbuff.no_of_updates++;
buffhead->type = PSS_UPD_AO;
buffhead->size = 2;
buffhead->signal = remao->objp->ConvOff;
buffhead++;
*(short int *)datap = *remao->rawval;
datap += 2;
datasize += 2;
buffsize += sizeof(pssupd_order_header) + 2;
}
}
remao = (remao_item *) remao->next;
}
/* Always send */
// if ((askbuff.no_of_updates > 0) /* || remnode->objp->Poll */) {
askbuff.length = (buffsize + sizeof(pssupd_buffer_vnet) -
MAX_ORDER_BUFFERSIZE_VNET + 1) / 2;
memcpy(buffhead, &buffdata, datasize); /* Add data after headers */
(send_pollbuff) (remnode, &askbuff); /* Send orders */
// remnode->objp->PollDiff++;
// }
return STATUS_OK;
}
/*
* Proview $Id: remote_remio_utils.h,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*************************************************************************
*
* Filename: remio_utils.h
*
* Date Pgm. Read. Remark
* Modified
*
* Description: Remote I/O utilities
*
*************************************************************************/
#if defined __cplusplus
extern "C" {
#endif
/*_function prototypes__________________________________________________*/
pwr_tFloat32 ConvAItoAct(pwr_tInt16 raw, pwr_sClass_RemChan_Ai *body);
pwr_tFloat32 ConvAOtoAct(pwr_tInt16 raw, pwr_sClass_RemChan_Ao *body);
pwr_tInt16 ConvAOtoRaw(pwr_tFloat32 act, pwr_sClass_RemChan_Ao *body);
pwr_tStatus RemIO_Init_ALCM (remnode_item *remnode);
pwr_tStatus RemIO_Stall_ALCM (remnode_item *remnode);
pwr_tStatus RemIO_Receive_ALCM (remnode_item *remnode,
bsp_buffer *buffer,
int size);
pwr_tStatus RemIO_Cyclic_ALCM (remnode_item *remnode,
void (* send_pollbuff)
(remnode_item *remnode,
pssupd_buffer *buf));
pwr_tStatus RemIO_Init_3964R (remnode_item *remnode);
pwr_tStatus RemIO_Stall_3964R (remnode_item *remnode,
int stall_action);
pwr_tStatus RemIO_Receive_3964R(remnode_item *remnode,
unsigned char *buffer,
int size);
pwr_tStatus RemIO_Cyclic_3964R(remnode_item *remnode,
void (* send_pollbuff)
(remnode_item *remnode,
pssupd_buffer_vnet *buf));
#if defined __cplusplus
}
#endif
/*
* Proview $Id: remote_remtrans_utils.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*********************************************************************
**********************************************************************
*
* Filename : remtrans_utils.c
*
* Modified : Date Pgm Remark
* 950208 Hans Werner First version
* 950208 CS Converted from h to c file
* 960222 Hans Werner Added RemTrans_Logg
* 010330 CJu RemTrans_Logg to qcom
* 040506 CJu Changes to V4.0.0
*
* Description : Remote trans utilities used by all remote transports
*
**********************************************************************
*********************************************************************/
#include "pwr.h"
#include "pwr_class.h"
#include "co_time.h"
#include "co_cdh.h"
#include "rt_errh.h"
#include "rt_gdh.h"
#include "rt_qcom.h"
#include "rt_qcom_msg.h"
#include "rt_qdb_msg.h"
#include "pwr_remoteclasses.h"
#include "remote.h"
#include "remote_remtrans_utils.h"
#include "rs_remote_msg.h"
/* Declare common variables */
qcom_sQid logg_qid;
/*********************************************************************
**********************************************************************
*
* Name : RemTrans_Logg
*
* Type : void
*
* Input : Pointer to struct remtrans_item with objid and pointer
*
* Output : QCOM logg-message to RS_REMOTE_LOGG.
* Description : Check if logging is to be done. Put log message together
* and send to queue RS_PWR_LOGG
*
**********************************************************************
*********************************************************************/
void RemTrans_Logg(remtrans_item *remtrans)
{
pwr_sClass_RemTrans *RemTransP;
pwr_tStatus sts;
pwr_tString80 rad1; /* Object name */
pwr_tString80 rad2; /* Time, status, length */
char *buffp; /* Pointer inside send buffer */
char *datap; /* Pointer to transdata buffer */
unsigned int i; /* Loop index */
unsigned int sizrad1; /* Buffer size row 1 */
unsigned int sizrad2; /* Buffer size row 2 */
unsigned int AntByt; /* Number of databytes to logg */
unsigned int AntRad; /* Number of lines data in logg */
unsigned int sign12;
unsigned int sign1;
unsigned int sign2;
unsigned int maxrad; /* Number of databytes in line */
unsigned int size; /* Total size of send buffer */
static unsigned short qcom_initialized = 0;
char* dynp; /* Allocated dynamic data area */
qcom_sPut put;
/* Shall we make a logg-entry ? */
RemTransP = remtrans->objp;
if ((RemTransP->LoggLevel > 1) || ((RemTransP->LoggLevel == 1) &&
EVEN(RemTransP->LastSts)))
{
/* FIRST ROW: Get Object name */
sts = gdh_ObjidToName(remtrans->objid, (char *) &rad1, sizeof(rad1), cdh_mNName);
if (EVEN(sts)) return;
sizrad1 = strlen((char *) &rad1);
/* SECOND ROW: Get Date and Time */
time_AtoAscii( NULL, time_eFormat_ComprDateAndTime, rad2, sizeof(rad2));
sizrad2 = strlen(rad2);
datap = (char *) &rad2 + sizrad2;
/* Status and Buffer Length */
sizrad2 += sprintf(datap," Status %d Length %d",
RemTransP->LastSts, RemTransP->DataLength);
/* Get size of data message to be logged */
if (RemTransP->LoggLevel == 4) AntByt = RemTransP->DataLength;
else if (RemTransP->LoggLevel == 3) AntByt =
(RemTransP->DataLength > 48) ? 48 : RemTransP->DataLength;
else AntByt = 0;
AntByt = min(AntByt, 10000);
AntRad = (AntByt + 23) / 24;
size = sizrad1 + sizrad2 + 9 + 3 * AntByt + AntRad;
if (qcom_initialized == 0)
{
/* Try to initiate qcom (it's probably already done) */
logg_qid = qcom_cNQid;
logg_qid.qix = rs_pwr_logg_qix;
qcom_Init(&sts, 0, "Logg");
if (EVEN(sts) && sts != QDB__ALRMAP) {
errh_Info("Qcom init failed, status: %d\n", sts);
return;
}
qcom_initialized = 1;
}
/* Malloc dynamic data area */
dynp = 0;
dynp = malloc(size+1);
if (!dynp) return;
buffp = dynp;
/* Get rad1 and rad2 into sendbuffer */
*buffp++ = RS_PWR_LOGG_RemTransId;
*buffp++ = 0;
*buffp++ = 0;
*buffp++ = 0;
memcpy(buffp, &rad1, sizrad1);
buffp += sizrad1;
*buffp = 13; /* CR */
buffp++;
*buffp = 10; /* LF */
buffp++;
memcpy(buffp, &rad2, sizrad2);
buffp += sizrad2;
*buffp = 13; /* CR */
buffp++;
*buffp = 10; /* LF */
buffp++;
/* Logg of Trans Data */
datap = remtrans->datap;
while (AntByt > 0)
{
maxrad = AntByt;
if (AntByt > 24) maxrad = 24;
for (i = 0; i < maxrad; i++)
{
sign12 = *datap;
sign1 = (sign12 & 240) / 16; /* Most sign 4 bits */
sign2 = sign12 & 15; /* Least sign 4 bits */
datap++;
if (sign1 < 10) *buffp = sign1 + 48; /* 0 - 9 */
else *buffp = sign1 + 55; /* A - F */
buffp++;
if (sign2 < 10) *buffp = sign2 + 48; /* 0 - 9 */
else *buffp = sign2 + 55; /* A - F */
buffp++;
*buffp = 32; /* Space */
buffp++;
} /* EndLoop bytes in row */
buffp--;
*buffp = 13; /* CR */
buffp++;
*buffp = 10; /* LF */
buffp++;
AntByt -= maxrad;
} /* Endloop lines */
*buffp = 0; /* NULL as end sign */
/* Send to Logg-job */
put.data = dynp;
put.size = size;
put.type.b = qcom_eBtype__;
put.type.s = qcom_eStype__;
put.reply.qix = 0;
put.reply.nid = 0;
qcom_Put(&sts, &logg_qid, &put);
free(dynp);
} /* END Logging */
return;
}
/*********************************************************************
**********************************************************************
*
* Name : RemTrans_Init
*
* Type : pwr_tInt32
*
* Input : Pointer to struct remnode_item.
*
* Output : Linked list of remtrans_items
* Description : Initialize RemTrans-object
*
**********************************************************************
*********************************************************************/
pwr_tInt32 RemTrans_Init(remnode_item *remnode)
{
remtrans_item *remtrans;
pwr_tStatus sts;
pwr_tObjid child_objid,data_objid;
pwr_tClassId class;
int mc_found;
/****** Initialize data in RemNode ******/
remnode->remtrans = NULL;
remnode->transbuff = NULL;
remnode->multicast = NULL;
mc_found = 0;
/****** Get first child under RemNode ******/
sts = gdh_GetChild(remnode->objid, &child_objid);
while ( ODD(sts)) {
/****** Test if type remtrans ******/
sts = gdh_GetObjectClass(child_objid, &class);
if (class == pwr_cClass_RemTrans) {
/****** Create remtrans_item and link it ******/
remtrans = malloc(sizeof(remtrans_item));
if (remtrans == 0) exit(REM__NOMEMORY); /* Error exit */
remtrans->next = (struct remtrans_item *) remnode->remtrans;
remnode->remtrans = remtrans;
remtrans->objid = child_objid;
sts = gdh_ObjidToPointer(child_objid, (pwr_tAddress *) &remtrans->objp);
remtrans->buffp = NULL;
/****** Clear data i RemTrans ******/
remtrans->objp->Buffers = 0;
remtrans->objp->LastSts = 1;
remtrans->objp->TransCount = 0;
remtrans->objp->BuffCount = 0;
remtrans->objp->LostCount = 0;
remtrans->objp->ErrCount = 0;
remtrans->time_since_send = 0;
/****** Check data object under RemTrans ******/
sts = gdh_GetChild(child_objid, &data_objid);
if ( EVEN(sts)) {
remtrans->objp->MaxLength = 0;
remtrans->datap = 0;
} /* END No Data */
else {
sts = gdh_ObjidToPointer(data_objid, (pwr_tAddress *) &remtrans->datap);
sts = gdh_GetObjectSize(data_objid,
(unsigned int *)&remtrans->objp->MaxLength);
} /* END Data found */
} /* END Class RemTrans */
/* If child is (first) MultiCast object, store pointer to this object in remnode_item */
if (class == pwr_cClass_MultiCast && mc_found == 0) {
mc_found = 1;
sts = gdh_ObjidToPointer(child_objid, (pwr_tAddress *) &remnode->multicast);
}
/****** Get next child under RemNode ******/
sts = gdh_GetNextSibling(child_objid, &child_objid);
} /* END while */
return STATUS_OK;
} /* END RemTrans_Init */
/*********************************************************************
**********************************************************************
*
* Name : RemTrans_Cyclic
*
* Type : pwr_tInt32
*
* Input : Pointer to struct remnode_item
*
* Description : Check if there are any free buffers to treat or
* any transes to send.
*
**********************************************************************
*********************************************************************/
pwr_tInt32 RemTrans_Cyclic( remnode_item *remnode,
unsigned int (* remnode_send)
(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buf_size)
)
{
pwr_tStatus sts;
remtrans_item *remtrans;
pwr_sClass_RemTrans *RemTransP;
rem_t_transbuff *buffp,*nextp;
remtrans_item *transp;
pwr_tInt32 buffsize;
pwr_tStatus SendSts;
/* Test if there is a buffered trans */
if (remnode->transbuff) {
buffp = (rem_t_transbuff *) remnode->transbuff;
transp = (remtrans_item *) buffp->remtrans;
/* Trans is not to be sent before time-out if buffered in wait for ack */
if ((transp->time_since_send >= remnode->retransmit_time) ||
(buffp->ackbuf == 0)) {
sts = (remnode_send) (remnode, transp->objp, &buffp->data, buffp->size);
transp->time_since_send = 0;
if (ODD(sts)) {
remnode->transbuff = (rem_t_transbuff *) buffp->next;
transp->objp->Buffers--;
free(buffp);
}
}
}
/* Loop all remtrans under remnode */
remtrans = remnode->remtrans;
while (remtrans) {
RemTransP = remtrans->objp;
/* Check if buffered receive */
if (RemTransP->Direction == REMTRANS_IN && RemTransP->Buffers > 0 &&
!RemTransP->DataValid) {
buffp = (rem_t_transbuff *) remtrans->buffp;
buffsize = buffp->size; /* buffersize */
remtrans->buffp = buffp->next; /* next buffer */
memcpy(remtrans->datap,&buffp->data,buffsize); /* copy transdata */
RemTransP->Buffers--;
RemTransP->DataLength = buffp->size;
RemTransP->LastSts = STATUS_BUFF;
RemTrans_Logg(remtrans); /* Logg */
RemTransP->DataValid = TRUE;
free(buffp); /* Dispose of buffer */
} /* END buffered receive */
/* Treat send trans */
else if (RemTransP->Direction == REMTRANS_OUT) {
/* Is there new data to send ? */
if (RemTransP->DataValid) {
if (RemTransP->DataLength > RemTransP->MaxLength ){
RemTransP->ErrCount++;
RemTransP->LastSts = STATUS_LENGTH;
} /* END too long data */
else {
SendSts = 0; /* Assume that we could not send */
if ((RemTransP->MaxBuffers == 0) ||
!remnode->transbuff) { /* Try to send if no buffers */
SendSts = (remnode_send) (remnode,RemTransP,
remtrans->datap,RemTransP->DataLength);
remtrans->time_since_send = 0;
if (ODD(SendSts)) {
RemTransP->TransCount++;
clock_gettime( CLOCK_REALTIME, &RemTransP->TransTime);
RemTransP->LastSts = STATUS_OK;
} /* END Send OK */
} /* END Try to send */
if (EVEN(SendSts)) { /* Trans should be buffered */
if ((RemTransP->MaxBuffers > 0) &&
(RemTransP->Buffers < RemTransP->MaxBuffers)) {
buffp = malloc(RemTransP->DataLength +
sizeof(rem_t_transbuff) - 1);
if (buffp) {
RemTransP->Buffers++; /* Buffer counter */
RemTransP->BuffCount++; /* Buffered trans counter */
buffp->next = 0;
buffp->remtrans = remtrans;
buffp->size = RemTransP->DataLength;
buffp->ackbuf = (SendSts == STATUS_BUFACK) ? 1 : 0;
memcpy(&buffp->data, remtrans->datap, RemTransP->DataLength);
if (remnode->transbuff == 0) remnode->transbuff = buffp;
else { /* Put buffer last in queue */
nextp = (rem_t_transbuff *) remnode->transbuff;
while (nextp->next) nextp = (rem_t_transbuff *) nextp->next;
nextp->next = (struct rem_t_transbuff *) buffp;
} /* END New buffer last in queue */
RemTransP->TransCount++;
clock_gettime( CLOCK_REALTIME, &RemTransP->TransTime);
RemTransP->LastSts = STATUS_BUFF;
} /* END Create new bufer */
else {
RemTransP->ErrCount++;
if (EVEN(sts)) RemTransP->LastSts = sts;
else RemTransP->LastSts = STATUS_FELSEND;
} /* END No memory for buffer */
} /* END Buffering wanted */
else {
RemTransP->ErrCount++;
RemTransP->LastSts = STATUS_FELSEND;
} /* END No more buffers */
} /* END trans is not sent */
} /* END Send request for valid trans */
RemTrans_Logg(remtrans); /* Logg */
RemTransP->DataValid = FALSE; /* Trans is treated */
} /* END Data valid was set */
} /* END Send direction */
remtrans = (remtrans_item *) remtrans->next;
} /* END while */
return STATUS_OK;
}
/*********************************************************************
**********************************************************************
*
* Name : RemTrans_Receive
*
* Type : pwr_tInt32
*
* Input : Pointer to struct remtrans_item,
* Pointer to buffer and size of buffer
*
* Description : Treat received trans that belongs to this remtrans_item.
*
**********************************************************************
*********************************************************************/
pwr_tInt32 RemTrans_Receive( remtrans_item *remtrans,
char *buffer,
int size)
{
pwr_sClass_RemTrans *RemTransP;
rem_t_transbuff *buffp,*nextp;
RemTransP = remtrans->objp; /* Get remtrans object */
RemTransP->TransCount++;
clock_gettime( CLOCK_REALTIME, &RemTransP->TransTime);
if ((unsigned int) size > RemTransP->MaxLength) { /* Too big trans */
RemTransP->ErrCount++;
RemTransP->LastSts = STATUS_LENGTH;
RemTrans_Logg(remtrans); /* Logg */
return STATUS_LENGTH;
} /* END Too big trans */
else {
/* First dispose of buffer if last trans is treated */
if (!RemTransP->DataValid && (RemTransP->Buffers > 0)) {
buffp = (rem_t_transbuff *) remtrans->buffp;
remtrans->buffp = buffp->next;
memcpy(remtrans->datap,&buffp->data,buffp->size); /* copy transdata */
RemTransP->Buffers--;
RemTransP->DataLength = buffp->size;
RemTransP->LastSts = STATUS_BUFF;
RemTransP->DataValid = TRUE;
free(buffp); /* Dispose of buffer */
} /* END buffered receive */
if (!RemTransP->DataValid && RemTransP->Buffers == 0) { /* Store directly */
memcpy(remtrans->datap,buffer,size);
RemTransP->DataLength = size;
RemTransP->LastSts = STATUS_OK;
RemTrans_Logg(remtrans); /* Logg */
RemTransP->DataValid = TRUE;
return STATUS_OK;
} /* END Store trans directly */
else if ((RemTransP->MaxBuffers > 0) &&
(RemTransP->Buffers < RemTransP->MaxBuffers)) {
buffp = malloc(size + sizeof(rem_t_transbuff) - 1);
if (buffp) {
RemTransP->Buffers++; /* Buffer counter */
RemTransP->BuffCount++; /* Buffered trans counter */
buffp->next = 0;
buffp->size = size;
memcpy(&buffp->data,buffer,size);
if (remtrans->buffp == 0) remtrans->buffp =
(struct rem_t_transbuff *) buffp;
else {
nextp = (rem_t_transbuff *) remtrans->buffp;
while (nextp->next) nextp = (rem_t_transbuff *) nextp->next;
nextp->next = (struct rem_t_transbuff *)buffp;
} /* END New buffer last in queue */
return STATUS_BUFF;
} /* END Create new bufer */
else {
RemTransP->LostCount++;
RemTransP->LastSts = STATUS_LOST;
RemTrans_Logg(remtrans); /* Logg */
return STATUS_LOST;
} /* END No memory for buffer*/
} /* END Try to buffer */
else {
RemTransP->LostCount++;
RemTransP->LastSts = STATUS_LOST;
RemTrans_Logg(remtrans); /* Logg */
return STATUS_LOST;
} /* END Buffering not allowed */
} /* END Treat OK trans */
}
/*
* Proview $Id: remote_remtrans_utils.h,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if defined __cplusplus
extern "C" {
#endif
void RemTrans_Logg(remtrans_item *remtrans);
pwr_tInt32 RemTrans_Init(remnode_item *remnode);
pwr_tInt32 RemTrans_Cyclic(remnode_item *remnode,
unsigned int (* remnode_send)
(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buf_size));
pwr_tInt32 RemTrans_Receive(remtrans_item *remtrans,
char *buffer,
int size);
#if defined __cplusplus
}
#endif
/*
* Proview $Id: remote_utils.c,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelsund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <time.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <termios.h>
#include <termio.h>
#include <sgtty.h>
#include <sys/ioctl.h>
#include "remote_utils.h"
#define TRUE 1
/************************************************************************
**************************************************************************
*
* Namn : RemUtils_InitSerialDev
*
* Typ : int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Assigns and sets up serial device
*
**************************************************************************
**************************************************************************/
int RemUtils_InitSerialDev(char *device, int speed, int databits, int stopbits, int parity)
{
#define SER_NONE 0
#define SER_ODD 1
#define SER_EVEN 2
struct termios tty_attributes;
int fd;
int sts;
int l_parity = SER_NONE;
fd=open(device, O_RDWR | O_NDELAY | O_NOCTTY); /*ppna seriedevicet*/
if(fd==-1) return 0;
tcgetattr(fd, &tty_attributes); //hmta serieportsvrdena
tty_attributes.c_cc[VMIN] = 1;
tty_attributes.c_cc[VTIME] = 0;
tty_attributes.c_lflag &= ~(ICANON | ISIG | ECHO | IEXTEN);
tty_attributes.c_cflag |= (CLOCAL | CREAD);
tty_attributes.c_oflag &= ~(OPOST);
tty_attributes.c_oflag &= ~(ONLCR);
tty_attributes.c_iflag &= ~(INLCR | ICRNL);
/*
speed = rn_serial->Speed;
bits = rn_serial->DataBits;
stopbit = rn_serial->StopBits;
*/
if (parity == 1) l_parity = SER_ODD;
if (parity == 2) l_parity = SER_EVEN;
/* hastighetsval */
tty_attributes.c_cflag &= ~CBAUD; //maska bort all hastighet
switch(speed)
{
case 300:
tty_attributes.c_cflag |= B300;
break;
case 1200:
tty_attributes.c_cflag |= B1200;
break;
case 2400:
tty_attributes.c_cflag |= B2400;
break;
case 4800:
tty_attributes.c_cflag |= B4800;
break;
case 9600:
tty_attributes.c_cflag |= B9600;
break;
case 19200:
tty_attributes.c_cflag |= B19200;
break;
default:
tty_attributes.c_cflag |= B9600;
break;
}
/* stt bitlngd p porten, 5, 6, 7 eller 8 bitar */
tty_attributes.c_cflag &= ~CSIZE; //bytesize maska bort alla bitlngdsval
if (databits == 5)
tty_attributes.c_cflag |= CS5; //5bit
else if (databits == 6)
tty_attributes.c_cflag |= CS6; //6bit
else if (databits == 7)
tty_attributes.c_cflag |= CS7; //7bit
else
tty_attributes.c_cflag |= CS8; //8bit
//tty_attributes.c_iflag |=ISTRIP;
/* paritetsval */
if (parity == SER_ODD || parity == SER_EVEN)
{
tty_attributes.c_cflag |= PARENB; //sl p paritet
tty_attributes.c_iflag |= IGNPAR; //vi vill bara skicka paritet inte kolla inkommande
if (parity == SER_EVEN)
tty_attributes.c_cflag &= ~PARODD; //even om inte odd
if (parity == SER_ODD)
tty_attributes.c_cflag |= PARODD; //odd
}
else
tty_attributes.c_cflag &= ~PARENB; //sl av paritet
/* stopbitsval */
if(stopbits == 2)
tty_attributes.c_cflag |=CSTOPB; //2 stopbitar
else
tty_attributes.c_cflag &=~CSTOPB; //1 stopbit
/* fldeskontroll */
tty_attributes.c_iflag &= ~IXON; //ingen XON/XOFF in
//tty_attributes.c_iflag &= (V_IGNCR);
//tty_attributes.c_iflag &= (IGNPAR | V_IGNCR);
//tty_attributes.c_iflag &= ~(BRKINT | IXON | V_INLCR | V_ICRNL);
//tty_attributes.c_cflag &= ~(CSIZE | CSTOPB | PARENB); //fippla om vrden lite granna
sts=tcsetattr(fd, TCSANOW, &tty_attributes);
if (sts<0) return(0);
tcflush(fd,TCIOFLUSH); //spola porten innan vi brjar
return fd;
}
/************************************************************************
**************************************************************************
*
* Namn : RemUtils_ConvertR50ToAscii
*
* Typ : int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Help routine for conversion from Radix50 to Ascii
*
**************************************************************************
**************************************************************************/
char RemUtils_ConvertR50ToAscii(int i)
{
char asc;
if (i == 0)
{
asc = ' ';
return asc;
}
if (i >= 1 && i <= 26)
{
asc = i + 64;
return asc;
}
if (i == 27)
{
asc = '$';
return asc;
}
if (i == 28)
{
asc = '.';
return asc;
}
if (i >= 30 && i <= 39)
{
asc = i + 18;
return asc;
}
asc = 0;
return asc;
}
/************************************************************************
**************************************************************************
*
* Namn : RemUtils_R50ToAscii
*
* Typ : int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Conversion from Radix50 to Ascii
*
**************************************************************************
**************************************************************************/
int RemUtils_R50ToAscii(unsigned short R50[], char asc[])
{
int i,j,k,index,ascindex=0;
unsigned short radix[2];
for (index = 0 ; index < 2 ; index++)
{
k = R50[index] % 40;
radix[index] = R50[index] - k;
radix[index] = radix[index] / 40;
j = radix[index] % 40;
radix[index] = radix[index] - j;
i = radix[index] / 40;
asc[ascindex++] = RemUtils_ConvertR50ToAscii(i);
asc[ascindex++] = RemUtils_ConvertR50ToAscii(j);
asc[ascindex++] = RemUtils_ConvertR50ToAscii(k);
}
return TRUE;
}
/************************************************************************
**************************************************************************
*
* Namn : RemUtils_AsciiToR50
*
* Typ : int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Conversion from Ascii to Radix50
*
**************************************************************************
**************************************************************************/
int RemUtils_AsciiToR50(char asc[], short R50[])
{
int i;
short dig_vec[6];
for (i = 0 ; i < 6 ; i++)
{
if (asc[i] >= '0' && asc[i] <= '9')
dig_vec[i] = asc[i] - 18;
else
{
if (asc[i] >= 'A' && asc[i] <= 'Z')
dig_vec[i] = asc[i] - 64;
else
{
if (asc[i] >= 'a' && asc[i] <= 'z')
dig_vec[i] = asc[i] - 96;
else
{
if (asc[i] == '$')
dig_vec[i] = 27;
else
{
if (asc[i] == '.')
dig_vec[i] = 28;
else
{
if (asc[i] == ' ')
dig_vec[i] = 0;
else
dig_vec[i] = 35;
}
}
}
}
}
}
R50[0] = ((dig_vec[0]*40 + dig_vec[1])*40 + dig_vec[2]);
R50[1] = ((dig_vec[3]*40 + dig_vec[4])*40 + dig_vec[5]);
return TRUE;
}
/*
* Proview $Id: remote_utils.h,v 1.1 2006-01-12 06:39:33 claes Exp $
* Copyright (C) 2005 SSAB Oxelösund AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the program, if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if defined __cplusplus
extern "C" {
#endif
/* Functions for serial lines */
int RemUtils_InitSerialDev(char *device, int speed, int databits, int stopbits, int parity);
/* Functions for radix 50 */
char RemUtils_ConvertR50ToAscii(int i);
int RemUtils_R50ToAscii(unsigned short R50[], char asc[]);
int RemUtils_AsciiToR50(char asc[], short R50[]);
#if defined __cplusplus
}
#endif
# makefile -- <short description>
#
# PROVIEW/R
# Copyright (C) 1996 by Comator Process AB.
#
# <Description>.
#
include $(pwre_dir_symbols)
ifndef variables_mk
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(hw_name)/variables.mk
endif
ifndef variables_mk
include $(pwre_kroot)/tools/bld/src/$(os_name)/variables.mk
endif
ifndef rules_mk
-include $(pwre_kroot)/tools/bld/src/$(os_name)/$(hw_name)/rules.mk
endif
ifndef rules_mk
include $(pwre_kroot)/tools/bld/src/$(os_name)/rules.mk
endif
.PHONY : all init copy lib exe clean realclean\
$(clean_wbl)
all : init copy exe
init :
copy : $(inc_dir)/pwr_remoteclasses.h \
$(inc_dir)/pwr_remoteclasses.hpp
lib : $(load_dir)/remote.dbs
exe : $(doc_dir)/en_us/orm/remote_allclasses.html \
$(exe_dir)/remote_xtthelp.dat
clean :
realclean : clean $(clean_wbl)
$(load_dir)/remote.dbs :
@ echo "Generating loadfile for remote"
@ export pwr_load=$(pwr_eload);\
wb_cmd -q -i create snapshot /file=\"$(pwre_sroot)/wbl/remote/src/\"/out=\"$(target)\"
@ chmod a+w $(target)
$(inc_dir)/pwr_remoteclasses.h :
@ echo "Generating struct files for remote classes..."
@ co_convert -s -d $(inc_dir) "$(pwre_sroot)/wbl/remote/src/remote_*.wb_load"
$(inc_dir)/pwr_remoteclasses.hpp :
@ echo "Generating hpp files for remote classes..."
@ co_convert -po -d $(inc_dir) "$(pwre_sroot)/wbl/remote/src/remote_*.wb_load"
$(doc_dir)/en_us/orm/remote_allclasses.html :
@ echo "Generating html files for remote classes en_us..."
@ co_convert -w -d $(doc_dir)/en_us/orm -g $(pwre_sroot)/wbl/remote/src/cnv_setup.dat "$(pwre_sroot)/wbl/remote/src/remote_*.wb_load"
@ echo "Generating html files for remote structs en_us..."
@ co_convert -c -d $(doc_dir)/en_us/orm $(inc_dir)/pwr_remoteclasses.h
@ echo "Generating html files for remote code en_us..."
@ co_convert -c -d $(doc_dir)/en_us/orm "$(pwre_sroot)/lib/rs/src/rs_plc_macro_remote.h"
@ co_convert -c -d $(doc_dir)/en_us/orm "$(pwre_sroot)/lib/rs/src/rs_plc_*.c"
@ echo "Generating html files for remote classes sv_se..."
@ co_convert -w -l sv_se -d $(doc_dir)/sv_se/orm -g $(pwre_sroot)/wbl/remote/src/cnv_setup.dat "$(pwre_sroot)/wbl/remote/src/remote_*.wb_load"
@ echo "Generating html files for remote structs sv_se..."
@ co_convert -c -d $(doc_dir)/sv_se/orm $(inc_dir)/pwr_remoteclasses.h
@ echo "Generating html files for remote code sv_se..."
@ co_convert -c -d $(doc_dir)/sv_se/orm "$(pwre_sroot)/lib/rs/src/rs_plc_macro_remote.h"
@ co_convert -c -d $(doc_dir)/sv_se/orm "$(pwre_sroot)/lib/rs/src/rs_plc_*.c"
@ echo "Generating postscript file for remote classes..."
@ co_convert -q -d $(doc_dir)/en_us "$(pwre_sroot)/wbl/remote/src/remote_*.wb_load"
@ co_convert -q -l sv_se -d $(doc_dir)/sv_se "$(pwre_sroot)/wbl/remote/src/remote_*.wb_load"
$(exe_dir)/remote_xtthelp.dat :
@ echo "Generating xtt help files for remote classes"
@ co_convert -x -d $(exe_dir) "$(pwre_sroot)/wbl/remote/src/remote_c_*.wb_load"
@ co_convert -x -l sv_se -d $(exe_dir) "$(pwre_sroot)/wbl/remote/src/remote_c_*.wb_load"
clean_wbl :
@ if [ -e $(load_dir)/remote.dbs ]; then \
$(rm) $(rmflags) $(load_dir)/remote.dbs; \
fi
!
! Proview $Id: remote_c_buff1440.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_Buff1440.wb_load -- Defines the class Buff1440.
!
SObject Remote:Class
!
! Buff1440 Transbuffer
!
Object Buff1440 $ClassDef 28
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! Buff1440 Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "Buff1440"
EndBody
!
! Parameter Data
!
Object Data $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$Int16"
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 720
EndBody
EndObject
EndObject
!
! Template fr Buff1440
!
Object Template Buff1440
Body RtBody
EndBody
EndObject
!
! End Buff1440
!
EndObject
EndSObject
!
! Proview $Id: remote_c_buff256.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_Buff256.wb_load -- Defines the class Buff256.
!
SObject Remote:Class
!
! Buff256 Transbuffer
!
Object Buff256 $ClassDef 29
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! Buff256 Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "Buff256"
EndBody
!
! Parameter Data
!
Object Data $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$Int16"
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 128
EndBody
EndObject
EndObject
!
! Template fr Buff256
!
Object Template Buff256
Body RtBody
EndBody
EndObject
!
! End Buff256
!
EndObject
EndSObject
!
! Proview $Id: remote_c_buff32k.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_Buff32k.wb_load -- Defines the class Buff32k.
!
SObject Remote:Class
!
! Buff32k Transbuffer
!
Object Buff32k $ClassDef 30
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! Buff32k Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "Buff32k"
EndBody
!
! Parameter Data
!
Object Data $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$Int16"
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 16384
EndBody
EndObject
EndObject
!
! Template fr Buff32k
!
Object Template Buff32k
Body RtBody
EndBody
EndObject
!
! End Buff32k
!
EndObject
EndSObject
!
! Proview $Id: remote_c_buff4096.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_Buff4096.wb_load -- Defines the class Buff4096.
!
SObject Remote:Class
!
! Buff4096 Transbuffer
!
Object Buff4096 $ClassDef 31
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! Buff4096 Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "Buff4096"
EndBody
!
! Parameter Data
!
Object Data $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$Int16"
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 2048
EndBody
EndObject
EndObject
!
! Template fr Buff4096
!
Object Template Buff4096
Body RtBody
EndBody
EndObject
!
! End Buff4096
!
EndObject
EndSObject
!
! Proview $Id: remote_c_buffstr80.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_BuffStr80.wb_load -- Defines the class BuffStr80.
!
SObject Remote:Class
!
! BuffStr80 Transbuffer
!
Object BuffStr80 $ClassDef 32
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! BuffStr80 Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "BuffStr80"
EndBody
!
! Parameter Data
!
Object Data $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
EndObject
!
! Template fr BuffStr80
!
Object Template BuffStr80
Body RtBody
EndBody
EndObject
!
! End BuffStr80
!
EndObject
EndSObject
!
! Proview $Id: remote_c_loggconfig.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_LoggConfig.wb_load -- Defines the class LoggConfig.
!
SObject Remote:Class
Object LoggConfig $ClassDef 27
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! LoggConfig Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "LoggConfig"
EndBody
!
! Parameter Description
!
Object LoggFile $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String40"
EndBody
EndObject
Object NewVersion $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_INVISIBLE
Attr Flags |= PWR_MASK_STATE
EndBody
EndObject
Object Identity $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
Object LoggCount $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_INVISIBLE
Attr Flags |= PWR_MASK_STATE
EndBody
EndObject
Object FileOpenCount $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_INVISIBLE
Attr Flags |= PWR_MASK_STATE
EndBody
EndObject
EndObject
!
! Template fr LoggConfig
!
Object Template LoggConfig
Body RtBody
EndBody
EndObject
!
! End RttConfig
!
EndObject
EndSObject
!
! Proview $Id: remote_c_multicast.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_MultiCast.wb_load -- Defines the class MultiCast.
!
SObject Remote:Class
!
! MultiCast - MultiCast adresses for Remote ALCM
!
Object MultiCast $ClassDef 26
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! MultiCast Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "MultiCast"
EndBody
!
! Parameter Address Area and node number for 8 adresses
!
Object Address $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt16"
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 16
EndBody
EndObject
EndObject
!
! Template fr MultiCast
!
Object Template MultiCast
Body RtBody
EndBody
EndObject
!
! End MultiCast
!
EndObject ! $ClassDef
EndSObject ! SObject
!
! Proview $Id: remote_c_remai.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_RemAi.wb_load -- Defines the class RemAi.
!
SObject Remote:Class
!
! RemAi
!
Object RemAi $ClassDef 12
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! RemAi Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemAi"
EndBody
!
! Parameter Description
!
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
EndObject ! $ObjBodyDef
!
! Template fr RemAi
!
Object Template RemAi
Body RtBody
EndBody
EndObject
!
! End RemAi
!
EndObject
EndSObject
!
! Proview $Id: remote_c_remao.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_RemAo.wb_load -- Defines the class RemAo.
!
SObject Remote:Class
!
! RemAo
!
Object RemAo $ClassDef 13
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! RemAo Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemAo"
EndBody
!
! Parameter Description
!
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
EndObject ! $ObjBodyDef
!
! Template fr RemAo
!
Object Template RemAo
Body RtBody
EndBody
EndObject
!
! End RemAo
!
EndObject
EndSObject
!
! Proview $Id: remote_c_remchan_ai.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_RemChan_Ai.wb_load -- Defines the class RemChan_Ai.
!
SObject Remote:Class
!
! RemChan_Ai - CHANnel Analog Input
!
Object RemChan_Ai $ClassDef 15
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! RemChan_Ai Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemChan_Ai"
EndBody
!
! Parameter Description
!
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!
! Parameter SigChanCon
!
Object SigChanCon $ObjXRef 2
Body SysBody
Attr Identity = "Ai"
Attr Source = "ChanAi"
Attr Target = "Ai"
Attr SourceAttribute = "SigChanCon"
Attr TargetAttribute = "SigChanCon"
EndBody
EndObject
!
! Parameter Identity
!
Object Identity $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$String40"
EndBody
EndObject
!
! Parameter ActualValue
!
Object ActualValue $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
Attr Flags |= PWR_MASK_POINTER
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!
! Parameter SensorPolyType
!
Object SensorPolyType $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter SensorPolyCoef0
!
Object SensorPolyCoef0 $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!
! Parameter SensorPolyCoef1
!
Object SensorPolyCoef1 $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!
! Parameter SensorPolyCoef2
!
Object SensorPolyCoef2 $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!
! Parameter ConvOff Word offset in transbuffer
!
Object ConvOff $Attribute 9
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
EndObject
!
! Menu-objects
!
Object ConfiguratorPosnn $Menu
Object Pointed $Menu
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-DisconnectSingle"
Attr MethodArguments[0] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnectSingle"
Attr FilterArguments[0] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPoson $Menu
Object Pointed $Menu
Object Connect $MenuButton
Body SysBody
Attr ButtonName = "Connect Signal"
Attr MethodName = "$ObjXRef-Connect"
Attr MethodArguments[0] = "SigChanCon"
Attr MethodArguments[1] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkConnect"
Attr FilterArguments[0] = "SigChanCon"
Attr FilterArguments[1] = "SigChanCon"
EndBody
EndObject
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-Disconnect"
Attr MethodArguments[0] = "SigChanCon"
Attr MethodArguments[1] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnect"
Attr FilterArguments[0] = "SigChanCon"
Attr FilterArguments[1] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPosos $Menu
Object Pointed $Menu
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-DisconnectSingle"
Attr MethodArguments[0] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnectSingle"
Attr FilterArguments[0] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcsnn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcscs $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcscn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcson $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcsmn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
!
! Template fr RemChan_Ai
!
Object Template RemChan_Ai
Body RtBody
Attr SensorPolyType = 1
Attr SensorPolyCoef1 = 1
EndBody
EndObject
!
! End RemChan_Ai
!
EndObject
EndSObject
!
! Proview $Id: remote_c_remchan_ao.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_RemChan_Ao.wb_load -- Defines the class RemChan_Ao.
!
SObject Remote:Class
!
! RemChan_Ao - CHANnel Analog Output
!
Object RemChan_Ao $ClassDef 16
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! RemChan_Ao Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemChan_Ao"
EndBody
!
! Parameter Description
!
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!
! Parameter SigChanCon
!
Object SigChanCon $ObjXRef 2
Body SysBody
Attr Identity = "Ao"
Attr Source = "ChanAo"
Attr Target = "Ao"
Attr SourceAttribute = "SigChanCon"
Attr TargetAttribute = "SigChanCon"
EndBody
EndObject
!
! Parameter Identity
!
Object Identity $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$String40"
EndBody
EndObject
!
! Parameter ActualValue
!
Object ActualValue $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
Attr Flags |= PWR_MASK_POINTER
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!
! Parameter OutPolyCoef0
!
Object OutPolyCoef0 $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!
! Parameter OutPolyCoef1
!
Object OutPolyCoef1 $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!
! Parameter OutMaxLimit Max Engineering value
!
Object OutMaxLimit $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!
! Parameter OutMinLimit Min Engineering value
!
Object OutMinLimit $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!
! Parameter ConvOff Word offset in transbuffer
!
Object ConvOff $Attribute 9
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter OldValue Old raw value when PWR is master
!
Object OldValue $Attribute 10
Body SysBody
Attr TypeRef = "pwrs:Type-$Int16"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter PwrIsMaster
!
Object PwrIsMaster $Attribute 11
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
EndObject
!
! Menu-objects
!
Object ConfiguratorPosnn $Menu
Object Pointed $Menu
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-DisconnectSingle"
Attr MethodArguments[0] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnectSingle"
Attr FilterArguments[0] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPoson $Menu
Object Pointed $Menu
Object Connect $MenuButton
Body SysBody
Attr ButtonName = "Connect Signal"
Attr MethodName = "$ObjXRef-Connect"
Attr MethodArguments[0] = "SigChanCon"
Attr MethodArguments[1] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkConnect"
Attr FilterArguments[0] = "SigChanCon"
Attr FilterArguments[1] = "SigChanCon"
EndBody
EndObject
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-Disconnect"
Attr MethodArguments[0] = "SigChanCon"
Attr MethodArguments[1] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnect"
Attr FilterArguments[0] = "SigChanCon"
Attr FilterArguments[1] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPosos $Menu
Object Pointed $Menu
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-DisconnectSingle"
Attr MethodArguments[0] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnectSingle"
Attr FilterArguments[0] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcsnn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcscs $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcscn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcson $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcsmn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
!
! Template fr RemChan_Ao
!
Object Template RemChan_Ao
Body RtBody
Attr PwrIsMaster = 1
Attr OutPolyCoef1 = 1
Attr OutMaxLimit = 100
EndBody
EndObject
!
! End RemChan_Ao
!
EndObject
EndSObject
!
! Proview $Id: remote_c_remchan_co.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_RemChan_Co.wb_load -- Defines the class RemChan_Co.
!
SObject Remote:Class
!
! RemChan_Co - CHANnel Counter
!
Object RemChan_Co $ClassDef 17
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! RemChan_Co Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemChan_Co"
EndBody
!
! Parameter Description
!
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!
! Parameter SigChanCon
!
Object SigChanCon $ObjXRef 2
Body SysBody
Attr Identity = "Co"
Attr Source = "ChanCo"
Attr Target = "Co"
Attr SourceAttribute = "SigChanCon"
Attr TargetAttribute = "SigChanCon"
EndBody
EndObject
!
! Parameter Identity
!
Object Identity $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$String40"
EndBody
EndObject
!
! Parameter ActualValue
!
Object ActualValue $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
Attr Flags |= PWR_MASK_POINTER
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!
! Parameter ExtendedValue
!
Object ExtendedValue $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
Attr Flags |= PWR_MASK_POINTER
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!
! Parameter NoOfBits Length of raw value (16 or 24)
!
Object NoOfBits $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter ConvOff Long word offset in transbuffer
!
Object ConvOff $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter SyncRawValue Sync to remote Co not in use !
!
Object SyncRawValue $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter CounterZeroFlag Sync to remote Co not in use !
!
Object CounterZeroFlag $Attribute 9
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!
! Parameter CounterSyncFlag Sync to remote Co not in use !
!
Object CounterSyncFlag $Attribute 10
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
EndObject
!
! Menu-objects
!
Object ConfiguratorPosnn $Menu
Object Pointed $Menu
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-DisconnectSingle"
Attr MethodArguments[0] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnectSingle"
Attr FilterArguments[0] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPoson $Menu
Object Pointed $Menu
Object Connect $MenuButton
Body SysBody
Attr ButtonName = "Connect Signal"
Attr MethodName = "$ObjXRef-Connect"
Attr MethodArguments[0] = "SigChanCon"
Attr MethodArguments[1] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkConnect"
Attr FilterArguments[0] = "SigChanCon"
Attr FilterArguments[1] = "SigChanCon"
EndBody
EndObject
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-Disconnect"
Attr MethodArguments[0] = "SigChanCon"
Attr MethodArguments[1] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnect"
Attr FilterArguments[0] = "SigChanCon"
Attr FilterArguments[1] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPosos $Menu
Object Pointed $Menu
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-DisconnectSingle"
Attr MethodArguments[0] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnectSingle"
Attr FilterArguments[0] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcsnn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcscs $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcscn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcson $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcsmn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
!
! Template fr RemChan_Co
!
Object Template RemChan_Co
Body RtBody
Attr NoOfBits = 16
EndBody
EndObject
!
! End RemChan_Co
!
EndObject
EndSObject
!
! Proview $Id: remote_c_remchan_di.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_RemChan_Di.wb_load -- Defines the class RemChan_Di.
!
SObject Remote:Class
!
! RemChan_Di - REMote CHANnel Digital Input
!
Object RemChan_Di $ClassDef 19
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! RemChan_Di Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemChan_Di"
EndBody
!
! Parameter Description
!
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!
! Parameter SigChanCon
!
Object SigChanCon $ObjXRef 2
Body SysBody
Attr Identity = "Di"
Attr Source = "ChanDi"
Attr Target = "Di"
Attr SourceAttribute = "SigChanCon"
Attr TargetAttribute = "SigChanCon"
EndBody
EndObject
!
! Parameter Identity
!
Object Identity $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$String40"
EndBody
EndObject
!
! Parameter ActualValue
!
Object ActualValue $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_POINTER
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!
! Parameter ConvOff Bit offset in transbuffer
!
Object ConvOff $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter BuffOff Byte offset in transbuffer
!
Object BuffOff $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter ConvMask Bitmask
!
Object ConvMask $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt8"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
EndObject
!
! Menu-objects
!
Object ConfiguratorPosnn $Menu
Object Pointed $Menu
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-DisconnectSingle"
Attr MethodArguments[0] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnectSingle"
Attr FilterArguments[0] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPoson $Menu
Object Pointed $Menu
Object Connect $MenuButton
Body SysBody
Attr ButtonName = "Connect Signal"
Attr MethodName = "$ObjXRef-Connect"
Attr MethodArguments[0] = "SigChanCon"
Attr MethodArguments[1] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkConnect"
Attr FilterArguments[0] = "SigChanCon"
Attr FilterArguments[1] = "SigChanCon"
EndBody
EndObject
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-Disconnect"
Attr MethodArguments[0] = "SigChanCon"
Attr MethodArguments[1] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnect"
Attr FilterArguments[0] = "SigChanCon"
Attr FilterArguments[1] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPosos $Menu
Object Pointed $Menu
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-DisconnectSingle"
Attr MethodArguments[0] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnectSingle"
Attr FilterArguments[0] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcsnn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcscs $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcscn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcson $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcsmn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
!
! Template fr RemChan_Di
!
Object Template RemChan_Di
Body RtBody
EndBody
EndObject
!
! End RemChan_Di
!
EndObject
EndSObject
!
! Proview $Id: remote_c_remchan_do.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_RemChan_Do.wb_load -- Defines the class RemChan_Do.
!
SObject Remote:Class
!
! RemChan_Do - CHANnel Digital output
!
Object RemChan_Do $ClassDef 14
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! RemChan_Do Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemChan_Do"
EndBody
!
! Parameter Description
!
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!
! Parameter SigChanCon
!
Object SigChanCon $ObjXRef 2
Body SysBody
Attr Identity = "Do"
Attr Source = "ChanDo"
Attr Target = "Do"
Attr SourceAttribute = "SigChanCon"
Attr TargetAttribute = "SigChanCon"
EndBody
EndObject
!
! Parameter Identity
!
Object Identity $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$String40"
EndBody
EndObject
!
! Parameter ActualValue
!
Object ActualValue $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_POINTER
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!
! Parameter ConvOff Bit offset in transbuffer
!
Object ConvOff $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter BuffOff Byte offset in transbuffer
!
Object BuffOff $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter ConvMask Bitmask
!
Object ConvMask $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt8"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter PwrIsMaster
!
Object PwrIsMaster $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!
! Parameter OldValue
!
Object OldValue $Attribute 9
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
EndObject
!
! Menu-objects
!
Object ConfiguratorPosnn $Menu
Object Pointed $Menu
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-DisconnectSingle"
Attr MethodArguments[0] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnectSingle"
Attr FilterArguments[0] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPoson $Menu
Object Pointed $Menu
Object Connect $MenuButton
Body SysBody
Attr ButtonName = "Connect Signal"
Attr MethodName = "$ObjXRef-Connect"
Attr MethodArguments[0] = "SigChanCon"
Attr MethodArguments[1] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkConnect"
Attr FilterArguments[0] = "SigChanCon"
Attr FilterArguments[1] = "SigChanCon"
EndBody
EndObject
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-Disconnect"
Attr MethodArguments[0] = "SigChanCon"
Attr MethodArguments[1] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnect"
Attr FilterArguments[0] = "SigChanCon"
Attr FilterArguments[1] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPosos $Menu
Object Pointed $Menu
Object Disconnect $MenuButton
Body SysBody
Attr ButtonName = "Disconnect Signal"
Attr MethodName = "$ObjXRef-DisconnectSingle"
Attr MethodArguments[0] = "SigChanCon"
Attr FilterName = "$ObjXRef-IsOkDisconnectSingle"
Attr FilterArguments[0] = "SigChanCon"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcsnn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcscs $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcscn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcson $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
Object ConfiguratorPcsmn $Menu
Object Pointed $Menu
Object SetDefaults $MenuButton
Body SysBody
Attr ButtonName = "Default Name..."
Attr MethodName = "$Object-SetDefaults"
EndBody
EndObject
EndObject
EndObject
!
! Template fr RemChan_Do
!
Object Template RemChan_Do
Body RtBody
Attr PwrIsMaster = 1
EndBody
EndObject
!
! End RemChan_Do
!
EndObject
EndSObject
!
! Proview $Id: remote_c_remchan_dv.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_RemChan_Dv.wb_load -- Defines the class RemChan_Dv.
!
SObject Remote:Class
!
! RemChan_Dv - Dv
!
Object RemChan_Dv $ClassDef 18
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! RemChan_Dv Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemChan_Dv"
EndBody
!
! Parameter Description
!
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!
! Parameter SigChanCon
!
Object SigChanCon $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$Objid"
EndBody
EndObject
!
! Parameter ActualValue
!
Object ActualValue $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_POINTER
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!
! Parameter ConvOff Bit offset in transbuffer
!
Object ConvOff $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter BuffOff Byte offset in transbuffer
!
Object BuffOff $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter ConvMask Bitmask
!
Object ConvMask $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt8"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter PwrIsMaster
!
Object PwrIsMaster $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!
! Parameter OldValue
!
Object OldValue $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
EndObject
!
! Template fr RemChan_Dv
!
Object Template RemChan_Dv
Body RtBody
Attr PwrIsMaster = 1
EndBody
EndObject
!
! End RemChan_Dv
!
EndObject
EndSObject
!
! Proview $Id: remote_c_remco.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_RemCo.wb_load -- Defines the class RemCo.
!
SObject Remote:Class
!
! RemCo
!
Object RemCo $ClassDef 20
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! RemCo Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemCo"
EndBody
!
! Parameter Description
!
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
EndObject ! $ObjBodyDef
!
! Template fr RemCo
!
Object Template RemCo
Body RtBody
EndBody
EndObject
!
! End RemCo
!
EndObject
EndSObject
!
! Proview $Id: remote_c_remdi.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_remdi.wb_load -- Defines the class RemDi.
!
SObject Remote:Class
!
! RemDi - Hierarchy-object for remote Di
!
Object RemDi $ClassDef 21
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! RemDi Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemDi"
EndBody
!
! Parameter Description
!
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
EndObject ! $ObjBodyDef
!
! Template fr RemDi
!
Object Template RemDi
Body RtBody
EndBody
EndObject ! Template
!
! End RemDi
!
EndObject ! $ClassDef
EndSObject
!
! Proview $Id: remote_c_remdo.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_RemDo.wb_load -- Defines the class RemDo.
!
SObject Remote:Class
!
! RemDo
!
Object RemDo $ClassDef 22
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! RemDi Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemDo"
EndBody
!
! Parameter Description
!
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
EndObject ! $ObjBodyDef
!
! Template fr RemDo
!
Object Template RemDo
Body RtBody
EndBody
EndObject
!
! End RemDo
!
EndObject
EndSObject
!
! Proview $Id: remote_c_remdv.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_RemDv.wb_load -- Defines the class RemDv.
!
SObject Remote:Class
!
! RemDv
!
Object RemDv $ClassDef 23
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! RemDi Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemDv"
EndBody
!
! Parameter Description
!
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
EndObject ! $ObjBodyDef
!
! Template fr RemDv
!
Object Template RemDv
Body RtBody
EndBody
EndObject
!
! End RemDv
!
EndObject
EndSObject
!
! Proview $Id: remote_c_remnode.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_RemNode.wb_load -- Defines the class RemNode.
!
SObject Remote:Class
!
! RemNode - Remote NODE descripton
!
Object RemNode $ClassDef 24
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! REMNODE Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemNode"
EndBody
!
! Parameter Description
!
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!
! Parameter NodeName
!
Object NodeName $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$String40"
EndBody
EndObject
!
! Parameter Address Node-adress depending on transport-type
!
Object Address $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt16"
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 4
EndBody
EndObject
!
! Parameter TransportType (PAMS,VNET,ALCM,SIEMENS,LOCAL...)
!
Object TransportType $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter NumberOfRestarts (Number of restarts of transport the server
! is allowed to do before giving up)
!
Object NumberOfRestarts $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter CycleTime
!
Object CycleTime $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!
! Parameter ErrTime
!
Object ErrTime $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!
! Parameter IOCycleTime
!
Object IOCycleTime $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!
! Parameter IOStallTime
!
Object IOStallTime $Attribute 9
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!
! Parameter IOStallAction
!
Object IOStallAction $Attribute 10
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter IODataArea Buffer-Object for storing I/O-buffer
!
Object IODataArea $Attribute 11
Body SysBody
Attr TypeRef = "pwrs:Type-$Objid"
EndBody
EndObject
!
! Parameter NumberOfTrans
!
Object NumberOfTrans $Attribute 12
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter NumberOfDI
!
Object NumberOfDI $Attribute 13
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter NumberOfDO
!
Object NumberOfDO $Attribute 14
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter NumberOfAI
!
Object NumberOfAI $Attribute 15
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter NumberOfAO
!
Object NumberOfAO $Attribute 16
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter NumberOfDV
!
Object NumberOfDV $Attribute 17
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter NumberOfCo
!
Object NumberOfCo $Attribute 18
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter PollDiff
!
Object PollDiff $Attribute 19
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter ErrTransCount
!
Object ErrTransCount $Attribute 20
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter Poll
!
Object Poll $Attribute 21
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!
! Parameter IOStallFlag
!
Object IOStallFlag $Attribute 22
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
EndObject
!
! Template fr RemNode
!
Object Template RemNode
Body RtBody
Attr CycleTime = 0.1
Attr IOCycleTime = 1.0
Attr IOStallTime = 2.0
EndBody
EndObject
!
! End REMNODE
!
EndObject ! $ClassDef
EndSObject ! SObject
!
! Proview $Id: remote_c_remnode3964r.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_remnode3964r.wb_load -- Defines the class Remnode3964R.
!
SObject Remote:Class
!/**
! @Version 1.0
! @Group Servers,NodeConfiguration
! @Summary Configures communication to a remote system using Siemens 3964R on a serial line.
! Configures communication to a remote system using Siemens 3964R on a serial line..
!
! @b Object graph
! @image orm_remnode3964r_og.gif
!
! @b See also
! @classlink RemoteConfig pwrp_remoteconfig.html
! @classlink RemTrans ssab_remtrans.html
!*/
Object Remnode3964R $ClassDef 1
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
Attr PopEditor = 2
EndBody
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "Remnode3964R"
EndBody
!/**
! Optional description.
!*/
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Process priority for the transport process. For future use.
!*/
Object Prio $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
EndBody
EndObject
!/**
! Device name for the serial port, ex /dev/ttyS0.
! Dynamic change is not possible.
!*/
Object DevName $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$String32"
EndBody
EndObject
!/**
! Baud rate for the serial port, ex 9600.
! Dynamic change is not possible.
!*/
Object Speed $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! Type of parity for the serial port.
! Dynamic change is not possible.
!*/
Object Parity $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$Enum"
EndBody
EndObject
!/**
! Number of stop bits for the serial port.
! Dynamic change is not possible.
!*/
Object StopBits $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$Enum"
EndBody
EndObject
!/**
! Number of data bits for the serial port.
! Dynamic change is not possible.
!*/
Object DataBits $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$Enum"
EndBody
EndObject
!/**
! Timeout time in seconds between two characters used while reading data.
! Dynamic change is possible.
!*/
Object CharTimeout $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Timeout time in seconds used when waiting for DLE (acknowledge) in sending,
! and when waiting for data after sending DLE in receiving.
! Dynamic change is possible.
!*/
Object AckTimeout $Attribute 9
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Attribute that indicates connection with the remote node.
! The link is considered down when we reach the link supervision timeout
! time without receiving any valid message.
! The link is considered up again when receiving a valid message.
!*/
Object LinkUp $Attribute 10
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Time in seconds before the link is considered down.
! Dynamic change is possible
!*/
Object LinkTimeout $Attribute 11
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! When set, this attribute tells the remote handler not to start
! or restart the process that handles this remote node. If the transport process
! is running while the attribute is set it will terminate.
! Dynamic change is possible.
!*/
Object Disable $Attribute 12
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!/**
! This attribute shows how many times the remote handler has restarted the
! transport process that handles this remnode.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartCount $Attribute 13
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! The restart limit tells the remote handler how many times the transport process
! that handle this remnode can be restarted.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartLimit $Attribute 14
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! The restart time is set by the transport process at startup and therefore
! shows the latest (re)starttime.
!*/
Object RestartTime $Attribute 15
Body SysBody
Attr TypeRef = "pwrs:Type-$Time"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Scantime in seconds for outgoing RemTrans objects.
! Dynamic change is possible.
!*/
Object ScanTime $Attribute 16
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Error counter.
!*/
Object ErrCount $Attribute 17
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Type of remnode. Used in the RemoteConfig classgraph.
!*/
Object Id $Attribute 18
Body SysBody
Attr TypeRef = "pwrs:Type-$String8"
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Contains the objid for the RemTrans objects for this remnode.
! The objid's are inserted by the remote process.
!*/
Object RemTransObjects $Attribute 19
Body SysBody
Attr TypeRef = "pwrs:Type-$Objid"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_INVISIBLE
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 25
EndBody
EndObject
EndObject
Object Template Remnode3964R
Body RtBody
Attr Prio = 15
Attr DevName = "/dev/ttyS0"
Attr Speed = 9600
Attr Parity = 2
Attr StopBits = 1
Attr DataBits = 8
Attr CharTimeout = 0.22
Attr AckTimeout = 2.0
Attr LinkUp = 0
Attr LinkTimeout = 10.0
Attr Disable = 0
Attr RestartCount = 0
Attr RestartLimit = 100
Attr ScanTime = 0.1
Attr Id = "3964r"
EndBody
EndObject
EndObject
EndSObject
!
! Proview $Id: remote_c_remnodealcm.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_remnodealcm.wb_load -- Defines the class RemnodeALCM.
!
SObject Remote:Class
!/**
! @Version 1.0
! @Group Servers,NodeConfiguration
! @Summary Configures communication to a remote using the ALCM protocol.
! Configures communication to a remote using the ALCM protocol.
! ALCM is a simple message oriented protocol that uses low level ethernet
! frames with protocol type 60-06 (DEC customer use). On DEC-based systems,
! ELN and VMS, the usage is simple and supported by the operating system. The
! DECnet address is used for addressing.
! On Linux systems, we have to use raw sockets to gain access to low level
! ethernet frames and the device's MAC address for addressing.
!
! @b Object graph
! @image orm_remnodealcm_og.gif
!
! @b See also
! @classlink RemoteConfig pwrp_remoteconfig.html
! @classlink RemTrans ssab_remtrans.html
!*/
Object RemnodeALCM $ClassDef 2
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
Attr PopEditor = 2
EndBody
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemnodeALCM"
EndBody
!/**
! Optional description.
!*/
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Process priority for the transport process. For future use.
!*/
Object Prio $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
EndBody
EndObject
!/**
! Device name for the ethernet device, Not yet implemented, defaults to "eth0".
!*/
Object DevName $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$String32"
EndBody
EndObject
!/**
! Hostname for the remote node. Used when hostname is to be part of the
! ALCM header in remote I/O or when mirroring common areas.
! Dynamic change is possible.
!*/
Object RemoteHostname $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$String32"
EndBody
EndObject
!/**
! DEC-net or MAC-address for the remote node. These to address types have
! the same format and is used directly in the address field of the low
! level ethernet frame. Note that on Linux systems, we often override
! the systems MAC-address in /etc/interfaces when using ALCM. This way we don't
! have to change address in remote when changing network device.
!
! The notation for DECnet address is node.area, eg 4.21 (decimal notation)
! The notation for MAC address is for example AA:00:A4:00:01:54 (hex notation)
!
! Dynamic change is not possible.
!*/
Object RemoteAddress $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$String32"
EndBody
EndObject
!/**
! Attribute that indicates connection with the remote node.
! The link is considered down when we reach the link supervision timeout
! time without receiving any ALCM data or I/O messages. The link is
! considered up again when receiving any kind of message. Note that this
! supervision is separated from the remote I/O supervision which uses
! IOStallFlag and IOStallTime.
!*/
Object LinkUp $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Time in seconds before the link is considered down. A value of 0 (zero) disables
! the LinkUp supervision.
! Dynamic change is possible
!*/
Object LinkTimeout $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! When set, this attribute tells the remote handler not to start
! or restart the process that handles this remote node. If the transport process
! is running while the attribute is set it will terminate. Note that in ALCM there
! is only one process that handles all remote nodes.
! Dynamic change is possible.
!*/
Object Disable $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!/**
! This attribute shows how many times the remote handler has restarted the
! transport process that handles this remnode.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartCount $Attribute 9
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! The restart limit tells the remote handler how many times the transport process
! that handle this remnode can be restarted.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartLimit $Attribute 10
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! The restart time is set by the transport process at startup and therefore
! shows the latest (re)starttime.
!*/
Object RestartTime $Attribute 11
Body SysBody
Attr TypeRef = "pwrs:Type-$Time"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Scantime in seconds for outgoing RemTrans objects.
! Dynamic change is possible.
!*/
Object ScanTime $Attribute 12
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Time in seconds to wait before retransmit when using acknowledge and buffering.
! For more information about acknowledge handling and retransmitting,
! refer to the documentation of the RemTrans object.
! Dynamic change is possible.
!*/
Object RetransmitTime $Attribute 13
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Error counter.
!*/
Object ErrCount $Attribute 14
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!
! Parameter IOPoll
!
Object IOPoll $Attribute 15
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!
! Parameter IOPollTime
!
Object IOPollTime $Attribute 16
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!
! Parameter IOPollTimeSlow
!
Object IOPollTimeSlow $Attribute 17
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!
! Parameter IOPollDiff
!
Object IOPollDiff $Attribute 18
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter IOStallTime
!
Object IOStallTime $Attribute 19
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!
! Parameter IOStallAction
!
Object IOStallAction $Attribute 20
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter IOStallFlag
!
Object IOStallFlag $Attribute 21
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter IODataArea
!
Object IODataArea $Attribute 22
Body SysBody
Attr TypeRef = "pwrs:Type-$Objid"
EndBody
EndObject
!
! Parameter NumberOfDI
!
Object NumberOfDI $Attribute 23
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter NumberOfDO
!
Object NumberOfDO $Attribute 24
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter NumberOfAI
!
Object NumberOfAI $Attribute 25
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter NumberOfAO
!
Object NumberOfAO $Attribute 26
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter NumberOfDV
!
Object NumberOfDV $Attribute 27
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter NumberOfCo
!
Object NumberOfCo $Attribute 28
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!/**
! Type of remnode. Used in the RemoteConfig classgraph.
!*/
Object Id $Attribute 29
Body SysBody
Attr TypeRef = "pwrs:Type-$String8"
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Contains the objid for the RemTrans objects for this remnode.
! The objid's are inserted by the remote process.
!*/
Object RemTransObjects $Attribute 30
Body SysBody
Attr TypeRef = "pwrs:Type-$Objid"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_INVISIBLE
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 25
EndBody
EndObject
EndObject
Object Template RemnodeALCM
Body RtBody
Attr Prio = 15
Attr DevName = "eth0"
Attr LinkUp = 0
Attr LinkTimeout = 3.0
Attr Disable = 0
Attr RestartCount = 0
Attr RestartLimit = 100
Attr ScanTime = 0.1
Attr RetransmitTime = 10.0
Attr IOPoll = 0
Attr IOPollDiff = 0
Attr IOPollTime = 1.0
Attr IOPollTimeSlow = 5.0
Attr IOStallTime = 3.0
Attr IOStallAction = 3
Attr Id = "Alcm"
EndBody
EndObject
EndObject
EndSObject
!
! Proview $Id: remote_c_remnodemodbus.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! pwrb_c_remnodemodbus.wb_load -- Defines the class RemnodeModbus.
!
SObject Remote:Class
!/**
! @Version 1.0
! @Group Servers,NodeConfiguration
! @Summary Configures communication to a remote system using Modbus on a serial line.
! Configures communication to a remote system using Modbus on a serial line.
!
! @b Object graph
! @image orm_remnodemodbus_og.gif
!
! @b See also
! @classlink RemoteConfig pwrp_remoteconfig.html
! @classlink RemTrans ssab_remtrans.html
!*/
Object RemnodeModbus $ClassDef 3
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
Attr PopEditor = 2
EndBody
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemnodeModbus"
EndBody
!/**
! Optional description.
!*/
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Process priority for the transport process. For future use.
!*/
Object Prio $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
EndBody
EndObject
!/**
! Device name for the serial port, ex /dev/ttyS0.
! Dynamic change is not possible.
!*/
Object DevName $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$String32"
EndBody
EndObject
!/**
! Baud rate for the serial port, ex 9600.
! Dynamic change is not possible.
!*/
Object Speed $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! Type of parity for the serial port.
! Dynamic change is not possible.
!*/
Object Parity $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$Enum"
EndBody
EndObject
!/**
! Number of stop bits for the serial port.
! Dynamic change is not possible.
!*/
Object StopBits $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$Enum"
EndBody
EndObject
!/**
! Number of data bits for the serial port.
! Dynamic change is not possible.
!*/
Object DataBits $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$Enum"
EndBody
EndObject
!/**
! Timeout time in seconds used when reading a message from the serial port.
! Dynamic change is possible.
!*/
Object ReadTimeout $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Attribute that indicates connection with the remote node.
! The link is considered down when we reach the link supervision timeout
! time without receiving any valid message.
! The link is considered up again when receiving a valid message.
!*/
Object LinkUp $Attribute 9
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Time in seconds before the link is considered down.
! Dynamic change is possible
!*/
Object LinkTimeout $Attribute 10
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! When set, this attribute tells the remote handler not to start
! or restart the process that handles this remote node. If the transport process
! is running while the attribute is set it will terminate.
! Dynamic change is possible.
!*/
Object Disable $Attribute 11
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!/**
! This attribute shows how many times the remote handler has restarted the
! transport process that handles this remnode.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartCount $Attribute 12
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! The restart limit tells the remote handler how many times the transport process
! that handle this remnode can be restarted.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartLimit $Attribute 13
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! The restart time is set by the transport process at startup and therefore
! shows the latest (re)starttime.
!*/
Object RestartTime $Attribute 14
Body SysBody
Attr TypeRef = "pwrs:Type-$Time"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Scantime in seconds for outgoing RemTrans objects.
! Dynamic change is possible.
!*/
Object ScanTime $Attribute 15
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Error counter.
!*/
Object ErrCount $Attribute 16
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Type of remnode. Used in the RemoteConfig classgraph.
!*/
Object Id $Attribute 17
Body SysBody
Attr TypeRef = "pwrs:Type-$String8"
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Contains the objid for the RemTrans objects for this remnode.
! The objid's are inserted by the remote process.
!*/
Object RemTransObjects $Attribute 18
Body SysBody
Attr TypeRef = "pwrs:Type-$Objid"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_INVISIBLE
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 25
EndBody
EndObject
EndObject
Object Template RemnodeModbus
Body RtBody
Attr Prio = 15
Attr DevName = "/dev/ttyS0"
Attr Speed = 9600
Attr Parity = 0
Attr StopBits = 1
Attr DataBits = 8
Attr ReadTimeout = 0.05
Attr LinkUp = 0
Attr LinkTimeout = 10.0
Attr Disable = 0
Attr RestartCount = 0
Attr RestartLimit = 100
Attr ScanTime = 0.1
Attr Id = "Modbus"
EndBody
EndObject
EndObject
EndSObject
!
! Proview $Id: remote_c_remnodemq.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_remnodeudp.wb_load -- Defines the class RemnodeUDP.
!
SObject Remote:Class
!/**
! @Version 1.0
! @Group Servers,NodeConfiguration
! @Summary Configures communication through a message queue using BEA MessageQ.
! Configures communication through a message queue using BEA MessageQ as a client.
!
! @b Object graph
! @image orm_remnodemq_og.gif
!
! @b See also
! @classlink RemoteConfig pwrp_remoteconfig.html
! @classlink RemTrans ssab_remtrans.html
!*/
Object RemnodeMQ $ClassDef 4
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
Attr PopEditor = 2
EndBody
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemnodeMQ"
EndBody
!/**
! Optional description.
!*/
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Process priority for the transport process. For future use.
!*/
Object Prio $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
EndBody
EndObject
!/**
! My queue number that resides on the MQ server. If set to 0 (zero) the queue will
! be allocated dynamically and we will not know in advance what queue number we have (can be
! useful for one-way outgoing communication with no incoming messages). This attribute
! will in this case be updated with the attached queue number.
!*/
Object MyQueue $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
EndBody
EndObject
!/**
! MQ group for every outgoing message.
! Dynamic change is possible.
!*/
Object TargetGroup $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
EndBody
EndObject
!/**
! MQ queue for every outgoing message.
! Dynamic change is possible.
!*/
Object TargetQueue $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
EndBody
EndObject
!/**
! Scantime in seconds for outgoing RemTrans messages.
! Dynamic change is possible.
!*/
Object ScanTime $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! When set, this attribute tells the remote handler not to start
! or restart the process that handles this remote node. If the transport process
! is running while the attribute is set it will terminate. This can be used to force
! a restart of the process.
!*/
Object Disable $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!/**
! This attribute shows how many times the remote handler has restarted the
! transport process that handles this remnode.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartCount $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! The restart limit tells the remote handler how many times the transport process
! that handle this remnode can be restarted.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartLimit $Attribute 9
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! The restart time is set by the transport process at startup and therefore
! shows the latest (re)starttime.
!*/
Object RestartTime $Attribute 10
Body SysBody
Attr TypeRef = "pwrs:Type-$Time"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Error counter.
!*/
Object ErrCount $Attribute 11
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Type of remnode. Used in the RemoteConfig classgraph.
!*/
Object Id $Attribute 12
Body SysBody
Attr TypeRef = "pwrs:Type-$String8"
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Contains the objid for the RemTrans objects for this remnode.
! The objid's are inserted by the remote process.
!*/
Object RemTransObjects $Attribute 13
Body SysBody
Attr TypeRef = "pwrs:Type-$Objid"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_INVISIBLE
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 25
EndBody
EndObject
EndObject
Object Template RemnodeMQ
Body RtBody
Attr Prio = 15
Attr MyQueue = 0
Attr TargetGroup = 0
Attr TargetQueue = 0
Attr Disable = 0
Attr RestartCount = 0
Attr RestartLimit = 100
Attr ScanTime = 0.1
Attr Id = "MQ"
EndBody
EndObject
EndObject
EndSObject
!
! Proview $Id: remote_c_remnodeserial.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_remnodeserial.wb_load -- Defines the class RemnodeSerial.
!
SObject Remote:Class
!/**
! @Version 1.0
! @Group Servers,NodeConfiguration
! @Summary Configures communication to a remote system using a serial line.
! Configures communication to a remote system using a serial line.
!
! @b Object graph
! @image orm_remnodeserial_og.gif
!
! @b See also
! @classlink RemoteConfig pwrp_remoteconfig.html
! @classlink RemTrans ssab_remtrans.html
!*/
Object RemnodeSerial $ClassDef 6
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
Attr PopEditor = 2
EndBody
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemnodeSerial"
EndBody
!/**
! Optional description.
!*/
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Process priority for the transport process. For future use.
!*/
Object Prio $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
EndBody
EndObject
!/**
! Device name for the serial port, ex /dev/ttyS0.
! Dynamic change is not possible.
!*/
Object DevName $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$String32"
EndBody
EndObject
!/**
! Baud rate for the serial port, ex 9600.
! Dynamic change is not possible.
!*/
Object Speed $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! Type of parity for the serial port.
! Dynamic change is not possible.
!*/
Object Parity $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$Enum"
EndBody
EndObject
!/**
! Number of stop bits for the serial port.
! Dynamic change is not possible.
!*/
Object StopBits $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$Enum"
EndBody
EndObject
!/**
! Number of data bits for the serial port.
! Dynamic change is not possible.
!*/
Object DataBits $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$Enum"
EndBody
EndObject
!/**
! List of termination characters for incoming data in ASCII value. A value of -1 indicates end of list.
! If all entrys are set to -1, no termination character is used at all.
! Dynamic change is possible.
!*/
Object TermChar $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$Int16"
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 8
EndBody
EndObject
!/**
! Timeout time in seconds used when reading a message from the serial port.
! Dynamic change is possible.
!*/
Object ReadTimeout $Attribute 9
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Attribute that indicates connection with the remote node.
! The link is considered down when we reach the link supervision timeout
! time without receiving any valid message.
! The link is considered up again when receiving a valid message.
!*/
Object LinkUp $Attribute 10
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Time in seconds before the link is considered down.
! Dynamic change is possible
!*/
Object LinkTimeout $Attribute 11
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! When set, this attribute tells the remote handler not to start
! or restart the process that handles this remote node. If the transport process
! is running while the attribute is set it will terminate.
! Dynamic change is possible.
!*/
Object Disable $Attribute 12
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!/**
! This attribute shows how many times the remote handler has restarted the
! transport process that handles this remnode.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartCount $Attribute 13
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! The restart limit tells the remote handler how many times the transport process
! that handle this remnode can be restarted.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartLimit $Attribute 14
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! The restart time is set by the transport process at startup and therefore
! shows the latest (re)starttime.
!*/
Object RestartTime $Attribute 15
Body SysBody
Attr TypeRef = "pwrs:Type-$Time"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Scantime in seconds for outgoing RemTrans objects.
! Dynamic change is possible.
!*/
Object ScanTime $Attribute 16
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Error counter.
!*/
Object ErrCount $Attribute 17
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Type of remnode. Used in the RemoteConfig classgraph.
!*/
Object Id $Attribute 18
Body SysBody
Attr TypeRef = "pwrs:Type-$String8"
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Contains the objid for the RemTrans objects for this remnode.
! The objid's are inserted by the remote process.
!*/
Object RemTransObjects $Attribute 19
Body SysBody
Attr TypeRef = "pwrs:Type-$Objid"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_INVISIBLE
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 25
EndBody
EndObject
EndObject
Object Template RemnodeSerial
Body RtBody
Attr Prio = 15
Attr DevName = "/dev/ttyS0"
Attr Speed = 9600
Attr Parity = 0
Attr StopBits = 1
Attr DataBits = 8
Attr TermChar[0] = -1
Attr TermChar[1] = -1
Attr TermChar[2] = -1
Attr TermChar[3] = -1
Attr TermChar[4] = -1
Attr TermChar[5] = -1
Attr TermChar[6] = -1
Attr TermChar[7] = -1
Attr ReadTimeout = 0.5
Attr LinkUp = 0
Attr LinkTimeout = 10.0
Attr Disable = 0
Attr RestartCount = 0
Attr RestartLimit = 100
Attr ScanTime = 0.1
Attr Id = "Serial"
EndBody
EndObject
EndObject
EndSObject
!
! Proview $Id: remote_c_remnodetcp.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_remnodetcp.wb_load -- Defines the class RemnodeTCP.
!
SObject Remote:Class
!/**
! @Version 1.0
! @Group Servers,NodeConfiguration
! @Summary Configures communication to a remote using the TCP/ip protocol.
! Configures communication to a remote using the TCP/ip protocol.
!
! @b Object graph
! @image orm_remnodetcp_og.gif
!
! @b See also
! @classlink RemoteConfig pwrp_remoteconfig.html
! @classlink RemTrans ssab_remtrans.html
!*/
Object RemnodeTCP $ClassDef 8
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
Attr PopEditor = 2
EndBody
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemnodeTCP"
EndBody
!/**
! Optional description.
!*/
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Process priority for the transport process. For future use.
!*/
Object Prio $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
EndBody
EndObject
!/**
! Device name for the ethernet device, Not yet implemented, defaults to "eth0".
!*/
Object DevName $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$String32"
EndBody
EndObject
!/**
! Hostname for the remote node.
! Dynamic change is not possible.
!*/
Object RemoteHostname $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$String32"
EndBody
EndObject
!/**
! IP-address for the remote node. If address is omitted or invalid, RemoteHostname
! is used to get the address either locally or through DNS lookup.
! Dynamic change is not possible.
!*/
Object RemoteAddress $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$String32"
EndBody
EndObject
!/**
! Local portnumber.
! Dynamic change is not possible.
!*/
Object LocalPort $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! Remote portnumber.
! Dynamic change is not possible.
!*/
Object RemotePort $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! Connection mode determines if our side should act as client or as server.
! Dynamic change is not possible.
!*/
Object ConnectionMode $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$Enum"
EndBody
EndObject
!/**
! Attribute that indicates connection with the remote node.
! The link is considered down when we reach the link supervision timeout
! time without receiving any keepalive or other message.
! The link is considered up again when receiving any kind of message.
!*/
Object LinkUp $Attribute 9
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Time in seconds before the link is considered down. A value of 0 (zero) disables
! the LinkUp supervision.
! Dynamic change is possible
!*/
Object LinkTimeout $Attribute 10
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! When set, this attribute tells the remote handler not to start
! or restart the process that handles this remote node. If the transport process
! is running while the attribute is set it will terminate.
! Dynamic change is possible.
!*/
Object Disable $Attribute 11
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!/**
! This attribute shows how many times the remote handler has restarted the
! transport process that handles this remnode.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartCount $Attribute 12
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! The restart limit tells the remote handler how many times the transport process
! that handle this remnode can be restarted.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartLimit $Attribute 13
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! The restart time is set by the transport process at startup and therefore
! shows the latest (re)starttime.
!*/
Object RestartTime $Attribute 14
Body SysBody
Attr TypeRef = "pwrs:Type-$Time"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Scantime in seconds for outgoing RemTrans objects.
! Dynamic change is possible.
!*/
Object ScanTime $Attribute 15
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Time in seconds to wait before retransmit when using acknowledge and buffering.
! For more information about acknowledge handling and retransmitting,
! refer to the documentation of the RemTrans object.
! Dynamic change is possible.
!*/
Object RetransmitTime $Attribute 16
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! When set, this attribute enables the sending of keepalive messages.
! Dynamic change is possible.
!*/
Object UseKeepalive $Attribute 17
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!/**
! Time in seconds between the sending of keepalive messages if keepalive
! messages is enabled with UseKeepalive.
! Dynamic change is possible.
!*/
Object KeepaliveTime $Attribute 18
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Counter that keeps track of incoming and outgoing keepalive messanges.
! The counter is incremented when a keppalive message is sent and decremented
! when such a message is received.
!*/
Object KeepaliveDiff $Attribute 19
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! When set, this attribute disables use of the special Remote TCP header
! in each send message. Furthermore, when receiving a message, the whole part
! of the message is treated as data which means that it is not possible to
! tell which ingoing RemTrans object the message is meant for since this information
! lies in the header. Therefore each incoming message is placed in the first found
! RemTrans object.
! Dynamic change is possible.
!*/
Object DisableHeader $Attribute 20
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!/**
! Error counter.
!*/
Object ErrCount $Attribute 21
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Type of remnode. Used in the RemoteConfig classgraph.
!*/
Object Id $Attribute 22
Body SysBody
Attr TypeRef = "pwrs:Type-$String8"
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Contains the objid for the RemTrans objects for this remnode.
! The objid's are inserted by the remote process.
!*/
Object RemTransObjects $Attribute 23
Body SysBody
Attr TypeRef = "pwrs:Type-$Objid"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_INVISIBLE
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 25
EndBody
EndObject
EndObject
Object Template RemnodeTCP
Body RtBody
Attr Prio = 15
Attr DevName = "eth0"
Attr LocalPort = 0
Attr RemotePort = 0
Attr ConnectionMode = 0
Attr LinkUp = 0
Attr LinkTimeout = 3.0
Attr Disable = 0
Attr RestartCount = 0
Attr RestartLimit = 100
Attr ScanTime = 0.1
Attr RetransmitTime = 10.0
Attr UseKeepalive = 1
Attr KeepaliveTime = 1.0
Attr DisableHeader = 0
Attr Id = "TCP"
EndBody
EndObject
EndObject
EndSObject
!
! Proview $Id: remote_c_remnodeudp.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_remnodeudp.wb_load -- Defines the class RemnodeUDP.
!
SObject Remote:Class
!/**
! @Version 1.0
! @Group Servers,NodeConfiguration
! @Summary Configures communication to a remote using the UDP/ip protocol.
! Configures communication to a remote using the UDP/ip protocol.
!
! @b Object graph
! @image orm_remnodeudp_og.gif
!
! @b See also
! @classlink RemoteConfig pwrp_remoteconfig.html
! @classlink RemTrans ssab_remtrans.html
!*/
Object RemnodeUDP $ClassDef 5
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
Attr PopEditor = 2
EndBody
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemnodeUDP"
EndBody
!/**
! Optional description.
!*/
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Process priority for the transport process. For future use.
!*/
Object Prio $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
EndBody
EndObject
!/**
! Device name for the ethernet device, Not yet implemented, defaults to "eth0".
!*/
Object DevName $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$String32"
EndBody
EndObject
!/**
! Hostname for the remote node.
! Dynamic change is not possible.
!*/
Object RemoteHostname $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$String32"
EndBody
EndObject
!/**
! IP-address for the remote node. If address is omitted or invalid, RemoteHostname
! is used to get the address either locally or through DNS lookup.
! Dynamic change is not possible.
!*/
Object RemoteAddress $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$String32"
EndBody
EndObject
!/**
! Local portnumber.
! Dynamic change is not possible.
!*/
Object LocalPort $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! Remote portnumber.
! Dynamic change is not possible.
!*/
Object RemotePort $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! Attribute that indicates connection with the remote node.
! The link is considered down when we reach the link supervision timeout
! time without receiving any keepalive or other message.
! The link is considered up again when receiving any kind of message.
!*/
Object LinkUp $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Time in seconds before the link is considered down. A value of 0 (zero) disables
! the LinkUp supervision.
! Dynamic change is possible
!*/
Object LinkTimeout $Attribute 9
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! When set, this attribute tells the remote handler not to start
! or restart the process that handles this remote node. If the transport process
! is running while the attribute is set it will terminate.
! Dynamic change is possible.
!*/
Object Disable $Attribute 10
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!/**
! This attribute shows how many times the remote handler has restarted the
! transport process that handles this remnode.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartCount $Attribute 11
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! The restart limit tells the remote handler how many times the transport process
! that handle this remnode can be restarted.
! Dynamic change is possible and can be used in order to earn more restarts.
!*/
Object RestartLimit $Attribute 12
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! The restart time is set by the transport process at startup and therefore
! shows the latest (re)starttime.
!*/
Object RestartTime $Attribute 13
Body SysBody
Attr TypeRef = "pwrs:Type-$Time"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Scantime in seconds for outgoing RemTrans objects.
! Dynamic change is possible.
!*/
Object ScanTime $Attribute 14
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Time in seconds to wait before retransmit when using acknowledge and buffering.
! For more information about acknowledge handling and retransmitting,
! refer to the documentation of the RemTrans object.
! Dynamic change is possible.
!*/
Object RetransmitTime $Attribute 15
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! When set, this attribute enables the sending of keepalive messages.
! Dynamic change is possible.
!*/
Object UseKeepalive $Attribute 16
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!/**
! Time in seconds between the sending of keepalive messages if keepalive
! messages is enabled with UseKeepalive.
! Dynamic change is possible.
!*/
Object KeepaliveTime $Attribute 17
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Counter that keeps track of incoming and outgoing keepalive messanges.
! The counter is incremented when a keppalive message is sent and decremented
! when such a message is received.
!*/
Object KeepaliveDiff $Attribute 18
Body SysBody
Attr TypeRef = "pwrs:Type-$Int32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! When set, this attribute disables use of the special Remote UDP header
! in each send message. Furthermore, when receiving a message, the whole part
! of the message is treated as data which means that it is not possible to
! tell which ingoing RemTrans object the message is meant for since this information
! lies in the header. Therefore each incoming message is placed in the first found
! RemTrans object.
! Dynamic change is possible.
!*/
Object DisableHeader $Attribute 19
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!/**
! Error counter.
!*/
Object ErrCount $Attribute 20
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Type of remnode. Used in the RemoteConfig classgraph.
!*/
Object Id $Attribute 21
Body SysBody
Attr TypeRef = "pwrs:Type-$String8"
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
!/**
! Contains the objid for the RemTrans objects for this remnode.
! The objid's are inserted by the remote process.
!*/
Object RemTransObjects $Attribute 22
Body SysBody
Attr TypeRef = "pwrs:Type-$Objid"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_INVISIBLE
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 25
EndBody
EndObject
EndObject
Object Template RemnodeUDP
Body RtBody
Attr Prio = 15
Attr DevName = "eth0"
Attr LocalPort = 0
Attr RemotePort = 0
Attr LinkUp = 0
Attr LinkTimeout = 3.0
Attr Disable = 0
Attr RestartCount = 0
Attr RestartLimit = 100
Attr ScanTime = 0.1
Attr RetransmitTime = 10.0
Attr UseKeepalive = 1
Attr KeepaliveTime = 1.0
Attr DisableHeader = 0
Attr Id = "UDP"
EndBody
EndObject
EndObject
EndSObject
!
! Proview $Id: remote_c_remoteconfig.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! pwrb_c_remoteconfig.wb_load -- Defines the class RemoteConfig.
!
SObject Remote:Class
!/**
! @Version 1.0
! @Group Servers,NodeConfiguration
! @Summary Configures the remotehandler.
! Configures the remotehandler.
!
! @b Object graph
! @image orm_remoteconfig_og.gif
!
! @b See also
! @classlink RemNode ssab_remnode.html
! @classlink RemTrans ssab_remtrans.html
!*/
Object RemoteConfig $ClassDef 7
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
Attr PopEditor = 2
EndBody
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemoteConfig"
EndBody
!/**
! Optional description.
!*/
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Disable all remote communication transports. If this attribute is set (value=1) on startup, no
! remote transport will be started. If it is dynamically set during runtime, all remote
! transports will be terminated and restarts will be blocked until the attribute is reset
! (value=0) again.
!*/
Object Disable $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
EndBody
EndObject
!/**
! Contains the objid for the RemNode objects.
! The objid's are inserted by the remotehandler.
!*/
Object RemNodeObjects $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$Objid"
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_INVISIBLE
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 25
EndBody
EndObject
EndObject
EndObject
EndSObject
!
! Proview $Id: remote_c_remoterack_ssab.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
SObject Remote:Class
!/**
! @Version 1.0
! @Group IO,IO_PSS9000
! @Summary Configuration of a PSS9000 rack.
! Configuration of a distributed PSS9000 rack.
! The rack object resides in the root volume of the process node.
! The rack object is placed below the $Node object, and is parent
! to the card objects of the rack.
!
!*/
Object RemoteRack_SSAB $ClassDef 9
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
Attr Flags |= pwr_mClassDef_IO
EndBody
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemoteRack_SSAB"
EndBody
!/**
! Optional description.
!*/
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Maximum number of cards.
!*/
Object MaxNoOfCards $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt16"
Attr Flags |= PWR_MASK_CONST
EndBody
EndObject
!/**
! IP address of the remote rack, ex 192.168.1.3
!*/
Object address $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Local ip port that the I/O process use. Not editable.
!*/
Object port $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt16"
EndBody
EndObject
EndObject
Object Template RemoteRack_SSAB
Body RtBody
Attr MaxNoOfCards = 16
EndBody
EndObject
EndObject
EndSObject
!
! Proview $Id: remote_c_remtrans.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_RemTrans.wb_load -- Defines the class RemTrans.
!
SObject Remote:Class
!
! RemTrans - Remote Trans descripton
!
Object RemTrans $ClassDef 25
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
EndBody
!
! RemTrans Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemTrans"
EndBody
!
! Parameter Description
!
Object Description $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!
! Parameter TransName May be used for trans-identification
! VNET Taskname 6 letters
! ALCM Taskname 6 letters
! PAMS Not used
!
Object TransName $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$String40"
EndBody
EndObject
!
! Parameter Address May be used for trans-identification
! PAMS: Class, Type, ProccessNr.
! ALCM, VNET TransName is translated into this parameter
!
Object Address $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt16"
Attr Flags |= PWR_MASK_ARRAY
Attr Elements = 4
EndBody
EndObject
!
! Parameter Direction. (IN = 1, OUT = 2)
!
Object Direction $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter DataLength
!
Object DataLength $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter LoggLevel
!
Object LoggLevel $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter Maxbuffers (0 = no buffering)
!
Object MaxBuffers $Attribute 7
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!
! Parameter Buffers Number of used buffers
!
Object Buffers $Attribute 8
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter MaxLength Length of data-object
!
Object MaxLength $Attribute 9
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter LastSts. (Returkod)
!
Object LastSts $Attribute 10
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter TransTime Date and time for send / receive
!
Object TransTime $Attribute 11
Body SysBody
Attr TypeRef = "pwrs:Type-$Time"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter TransCount
!
Object TransCount $Attribute 12
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter BuffCount Number of buffered transactions
!
Object BuffCount $Attribute 13
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter LostCount Received but not treated
!
Object LostCount $Attribute 14
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter ErrCount Couldn't send
!
Object ErrCount $Attribute 15
Body SysBody
Attr TypeRef = "pwrs:Type-$UInt32"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter DataValid
!
Object DataValid $Attribute 16
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr Flags |= PWR_MASK_NOEDIT
EndBody
EndObject
!
! Parameter StructName
!
Object StructName $Attribute 17
Body SysBody
Attr TypeRef = "pwrs:Type-$String40"
EndBody
EndObject
!
! Parameter StructFile
!
Object StructFile $Attribute 18
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
EndObject
!
! Template fr RemTrans
!
Object Template RemTrans
Body RtBody
Attr Direction = 1
EndBody
EndObject
!
! End RemTrans
!
EndObject ! $ClassDef
EndSObject ! SObject
!
! Proview $Id: remote_c_remtransrcv.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_remtransrcv.wb_load -- Defines the class RemTransRcv.
!
SObject Remote:Class
!/**
! @Version 1.0
! @Code rs_plc_macro_nmps.h
! @Group Remote,Plc
! @Summary Supervision of a receive RemTrans object and unpacks the receive buffer.
! The object supervises a receive RemTrans object.
! @image orm_remtransrcv_fo.gif
! In a subwindow, code for unpacking the receive buffer of the remtrans
! can be programmed.
! When a transaction is recived, the subwindow is executed and the output
! Recieved is set to mark that new data is present.
!
! @b See also
! @classlink RemTrans remote_remtrans.html
! @classlink RemTransSend remote_remtranssend.html
!*/
Object RemTransRcv $ClassDef 11
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_RtConnectionsAndDevBodies
Attr PopEditor = 2
EndBody
!
! REMTRANSRCV Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemTransRcv"
EndBody
!/**
! Data input connected to a GetData refering to the RemTrans object.
!*/
Object RemTrans $Input 1
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
Attr Flags |= PWR_MASK_POINTER
Attr Flags |= PWR_MASK_PRIVATE
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_NOREMOVE
Attr GraphName = "Trs"
EndBody
EndObject
!/**
! Data is received. DataValid in the RemTrans object is detected, and
! the subwindow is executed.
! Received is true in one cycle.
!*/
Object Received $Output 2
Body SysBody
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr TypeRef = "pwrs:Type-$Boolean"
Attr GraphName = "rcv"
EndBody
EndObject
EndObject
!
! REMTRANSRCV Development Body
!
Object DevBody $ObjBodyDef 2
Object PlcNode $Buffer 1
Body SysBody
Attr Class = pwr_eClass_PlcNode
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
EndObject
Object GraphPlcNode $GraphPlcNode
Body SysBody
Attr object_type = 11
Attr parameters[0] = 1
Attr parameters[1] = 0
Attr parameters[2] = 1
Attr parameters[3] = 0
Attr subwindow_class[0] = "pwrb:Class-WindowPlc"
Attr subwindows = 1
Attr graphmethod = 16
Attr graphindex = 0
Attr default_mask[0] = 1
Attr default_mask[1] = 1
Attr segname_annotation = 1
Attr devbody_annotation = 0
Attr compmethod = 50
Attr compindex = 0
Attr tracemethod = 0
Attr traceindex = 0
Attr executeordermethod = 2
Attr objname = "RemRcv"
Attr graphname = "RemRcv"
Attr debugpar = ""
EndBody
EndObject
EndObject
EndSObject
!
! Proview $Id: remote_c_remtranssend.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_c_remtranssend.wb_load -- Defines the class RemTransSend.
!
SObject Remote:Class
!/**
! @Version 1.0
! @Code rs_plc_macro_nmps.h
! @Group Remote,Plc
! @Summary Fill and send a remtrans buffer.
! Fill a remtrans buffer and mark the RemTrans object for send.
! @image orm_remtranssend_fo.gif
!
! The object has a subwindow where code for fill in data in
! a remtrans buffer can be programmed. The object excecutes the
! subwindow and then sets the DataValid attribute in the RemTrans
! object, to indicate that new data is present. Status from the
! RemTrans object is stored in output attributes of the RemTransSend
! object.
!
! @b See also
! @classlink RemTrans remote_remtrans.html
! @classlink RemTransRcv remote_remtransrcv.html
!*/
Object RemTransSend $ClassDef 10
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_RtConnectionsAndDevBodies
Attr PopEditor = 2
EndBody
!
! REMTRANSSEND Runtime Body
!
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemTransSend"
EndBody
!/**
! Data input connected to a GetData which refers to the RemTrans object.
!*/
Object RemTrans $Input 1
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
Attr Flags |= PWR_MASK_POINTER
Attr Flags |= PWR_MASK_PRIVATE
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_NOREMOVE
Attr GraphName = "Trs"
EndBody
EndObject
!/**
! Data will be sent on positiv edge. The subwindow is executed and
! DataValid is set in the RemTrans object.
!*/
Object Send $Input 2
Body SysBody
Attr TypeRef = "pwrs:Type-$Boolean"
Attr GraphName = "snd"
Attr Flags |= PWR_MASK_NOINVERT
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr Flags |= PWR_MASK_NOREMOVE
EndBody
EndObject
!/**
! Indicates that the RemTrans object can't handle any new transactions
! for the moment. The last transaction is not yet sent, or if buffering
! is used, no more buffers are available.
!*/
Object Occupied $Output 3
Body SysBody
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr TypeRef = "pwrs:Type-$Boolean"
Attr GraphName = "occ"
EndBody
EndObject
!/**
! Indicates that there are buffered transactions.
!*/
Object Buffer $Output 4
Body SysBody
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr TypeRef = "pwrs:Type-$Boolean"
Attr GraphName = "buf"
EndBody
EndObject
!/**
! Error status was returned for the last transaction.
!*/
Object Error $Output 5
Body SysBody
Attr Flags |= PWR_MASK_STATE
Attr Flags |= PWR_MASK_NOEDIT
Attr TypeRef = "pwrs:Type-$Boolean"
Attr GraphName = "err"
EndBody
EndObject
EndObject
!
! REMTRANSSEND Development Body
!
Object DevBody $ObjBodyDef 2
Object PlcNode $Buffer 1
Body SysBody
Attr Class = pwr_eClass_PlcNode
Attr Flags |= PWR_MASK_INVISIBLE
EndBody
EndObject
EndObject
Object GraphPlcNode $GraphPlcNode
Body SysBody
Attr object_type = 11
Attr parameters[0] = 2
Attr parameters[1] = 0
Attr parameters[2] = 3
Attr parameters[3] = 0
Attr subwindow_class[0] = "pwrb:Class-WindowPlc"
Attr subwindows = 1
Attr graphmethod = 16
Attr graphindex = 0
Attr default_mask[0] = 3
Attr default_mask[1] = 5
Attr segname_annotation = 1
Attr devbody_annotation = 0
Attr compmethod = 50
Attr compindex = 0
Attr tracemethod = 0
Attr traceindex = 0
Attr executeordermethod = 2
Attr objname = "RemSend"
Attr graphname = "RemSend"
Attr debugpar = ""
EndBody
EndObject
EndObject
EndSObject
!
! Proview $Id: remote_ch_class.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelösund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_ch_class.wb_load -- Remote:Class hierarchy.
!
SObject Remote:
Object Class $ClassHier
EndObject
EndSObject
!
! Proview $Id: remote_v.wb_load,v 1.1 2006-01-12 06:39:33 claes Exp $
! Copyright (C) 2005 SSAB Oxelösund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! remote_v.wb_load -- Loads the remote volume
!
Volume Remote pwr_eClass_ClassVolume 0.0.1.4
EndVolume
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment