Commit 679d0b6f authored by Claes Sjofors's avatar Claes Sjofors

Remote rk512 ported from ELN

parent 3e599866
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) \
$(pwre_conf_libdir) $(pwre_conf_libpwrremote) $(pwre_conf_libpwrrt) $(pwre_conf_lib)
endif
......@@ -36,70 +36,88 @@
/*************************************************************************
*
* R K 5 1 2
* =========
* 3 9 6 4 R
* ==========
**************************************************************************
*
* Filename: rs_remote_rk512.c
*
* Date Pgm. Read. Remark
* Modified 951006 CJu
* 951124 TAn
* 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 RK512
* 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
/*System includes*/
#ifdef OS_VMS
#include <ssdef.h>
#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 <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>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
//#include <uio.h>
#include <termios.h>
#if defined OS_LINUX
#include <termio.h>
#endif
#if defined OS_LINUX || defined OS_MACOS
#include <sgtty.h>
#endif
#include <sys/ioctl.h>
/*PWR includes*/
#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"
#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_________________________________________________________________*/
......@@ -108,13 +126,24 @@
#define MAX_SIZE_DATA_BLOCK 128
#define MAX_SIZE_TELEGRAM 141
#define RESP_MESSAGE_SIZE 6
#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 TRUE 1
#define FALSE 0
//#define TIMEOUT_REC_CHAR_SEC 0
//#define TIMEOUT_REC_CHAR_USEC 900000
#define BYTE_MASK 0xFF
#define CPU_NR_MASK 0xF0
//#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
......@@ -122,613 +151,210 @@
#define DLE 16
#define NAK 21
#define DLE_BITMASK 0x10000
#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
*/
/*_variables_______________________________________________________________*/
unsigned int receive_ef;
unsigned int timer_ef;
unsigned int ef_mask;
unsigned int telegram_counter = 0; /* For control of follow on telegrams */
#endif
remnode_item rn;
pwr_sClass_RemnodeRK512 *rn_RK512;
int ser_fd; /* file domininator for serial port */
unsigned char debug=0; /* 1 if debug mode activated */
/*
* Variables common for VMS and ELN
*/
float time_since_poll;
float time_since_io;
float time_since_scan;
remnode_item remnode_struct;
remnode_item *remnode = &remnode_struct;
LARGE_INTEGER timeout_cycle;
int stall_action = 1;
int use_remote_io;
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;
void load_timeval(struct timeval *tv, float t)
{
tv->tv_sec = t;
tv->tv_usec = (t-(float)tv->tv_sec) * 1000000;
}
unsigned int telegram_counter = 0; /* For control of follow on telegrams */
short poll_id[2];
/*_variables_______________________________________________________________*/
/********** Function prototypes **********************************/
static int SendResponseTelegram(unsigned char CODE);
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
* Namn : send_pollbuff
*
* Typ : void
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Exit handler that is called before process termination
* Beskrivning : Sends a poll or IO update message to Remote node
*
**************************************************************************
**************************************************************************/
static void exith(void)
void send_pollbuff(remnode_item *remnode, pssupd_buffer_vnet *buf)
{
#ifdef OS_ELN
unsigned int sts, buf_size;
unsigned int sts;
/* 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];
#else
buf_size = buf->length * 2; /* Convert to bytes */
sts = send_it((char*)buf, buf_size);
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
* Namn : remnode_send
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Initiates the timers used in this process.
* Beskrivning : Sends a RemTrans message to Remote node
*
**************************************************************************
**************************************************************************/
static unsigned int InitTimers(void)
static unsigned int remnode_send(remnode_item *remnode,
pwr_sClass_RemTrans *remtrans,
char *buf,
int buffer_size)
{
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);
sts = send_it(buf, buffer_size);
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
* Namn : send_it
*
* Typ : unsigned int
*
* Typ Parameter IOGF Beskrivning
*
* Beskrivning : Sends a message to Remote node
* Beskrivning : Sends a buffer
*
**************************************************************************
**************************************************************************/
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 buffer_size)
{
unsigned int sts, i;
unsigned int size_of_telegram, datasize;
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 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 ch;
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;
unsigned char *restore_buf_ptr = (unsigned char *)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 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;
fd_set read_fd;
struct timeval tv;
/*************************************************************************/
/** Fill in the follow on telegram header and calculate BCC. **/
/** Count DLE characters and calculate the size of the telegram. **/
/*************************************************************************/
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;
}
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;
/*************************************************************************/
/** Execute the send procedure **/
/** Fill up telegram with contents of message and calculate 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) )
buf = (char *)restore_buf_ptr;
for ( i=0 ; i<(buffer_size + number_of_DLE) ; i++ )
{
ch = telegram[i] = *buf++;
BCC ^= ch;
if ( ch == DLE )
{
/* 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);
telegram[++i] = DLE;
BCC ^= ch;
}
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) )
{
}
telegram[i++] = DLE;
telegram[i++] = ETX;
telegram[i] = BCC;
/*************************************************************************/
/** The sending was a SUCCESS. Take care of the response message **/
/** Execute the send procedure **/
/*************************************************************************/
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);
/**** set up timeout ****/
follow_on = FALSE;
// tv.tv_sec = TIMEOUT_SND_ANSWER_SEC;
// tv.tv_usec = TIMEOUT_SND_ANSWER_USEC;
load_timeval(&tv, rn_RK512->AckTimeout);
/* Ensure that error status is returned */
sts = FALSE;
}
}while( follow_on );
FD_ZERO(&read_fd);
FD_SET(ser_fd, &read_fd);
return(sts);
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 RK512, 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_RK512->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_RK512->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 RK512 sndning misslyckades, inget initierande DLE-tecken frn mottagaren");
else if(buff!=DLE)
errh_Error("Remtrans RK512 sndning misslyckades, inget avslutande DLE-tecken frn mottagaren");
sts=FALSE;
}
return sts; /*and return status*/
}
/*************************************************************************
/*************************************************************************
**************************************************************************
*
* Namn : Receive
......@@ -744,66 +370,76 @@ static unsigned int remnode_send(remnode_item *remnode,
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};
static int sts;
int rsts;
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 ****/
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);
load_timeval(&tv, 0); // poll
// load_timeval(&tv, rn_RK512->ScanTime);
// tv.tv_sec = TIMEOUT_REC_ANSWER_SEC;
// tv.tv_usec = TIMEOUT_REC_ANSWER_USEC;
if (sts == ELN$_SUCCESS)
/**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)
{
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 */
/* Write DLE to respond */
if(!write(ser_fd, sdle, 1))
return 0;
rsts = ReceiveHandler(ser_fd);
while( ODD(rsts) && sts > 0 && telegram_counter) {
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 && received_char == STX) {
/* Write DLE to respond */
if(!write(ser_fd, sdle, 1))
return 0;
rsts = ReceiveHandler(ser_fd);
}
else
rsts = 0;
}
}
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);
write(ser_fd, snak, 1);
errh_Error("RK512 felaktigt meddelande i mottagning, annat starttecken n STX (0x%x)", received_char);
sts=0; //felstatus
}
}
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);
if (sts < 1 || EVEN(rsts))
{
rn_RK512->ErrCount++;
telegram_counter = 0;
}
}
return(1);
}
/*************************************************************************
/*************************************************************************
**************************************************************************
*
* Namn : ReceiveHandler
......@@ -817,112 +453,130 @@ static unsigned int Receive()
**************************************************************************
**************************************************************************/
static unsigned int ReceiveHandler()
static unsigned int ReceiveHandler(int fd)
{
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 int sts;
//unsigned int nbr_of_bytes_written = 0;
//unsigned int nbr_of_bytes_read = 0;
unsigned int data_size = 0;
char cont = TRUE;
char search_remtrans = FALSE;
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'};
unsigned char receive_buffer[MAX_SIZE_TELEGRAM];
unsigned char sdle = DLE;
unsigned char received_char;
remtrans_item *remtrans;
int i;
unsigned char CODE = '\0';
static unsigned int datasize;
static unsigned char *TelegramBuffer;
static unsigned char *TelegramBuffer_ptr;
DDA$_BREAK_MASK DLE_mask = DLE;
DDA$_BREAK_MASK STX_mask = STX;
unsigned int pos_counter = 0;
unsigned int delta_pos = 0;
fd_set read_fd;
struct timeval tv;
/**** set up timeout,****/
/*************************************************************************/
/** We have received STX earlier, send DLE to responde **/
/*************************************************************************/
load_timeval(&tv, rn_RK512->CharTimeout);
// tv.tv_sec = TIMEOUT_REC_CHAR_SEC;
// tv.tv_usec = TIMEOUT_REC_CHAR_USEC;
/* 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 **/
/** Read telegram **/
/*************************************************************************/
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++ )
cont = TRUE;
data_size = 0;
while (cont)
{
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);
/* Read until DLE is received */
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);
received_char=0;
BCC_checksum = received_char;
terminate = TRUE;
}
else
while(received_char != DLE)
{
/* 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;
load_timeval(&tv, rn_RK512->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
else //timeout g tillbaka
{
/* This is a duplicated DLE character. Throw away. */
i--;
char_buffer = '\0';
errh_Error("RK512 mottagning, character timeout");
return(FALSE);
}
}
/* Read one more */
load_timeval(&tv, rn_RK512->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("RK512 mottagning, character timeout");
return(FALSE);
}
if (receive_buffer[data_size] == ETX)
{
data_size++;
/* Read one more, should be checksum */
load_timeval(&tv, rn_RK512->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("RK512 mottagning, character timeout");
return(FALSE);
}
data_size++;
cont = FALSE;
}
} /* endfor */
else
if (receive_buffer[data_size] != DLE ) data_size++;
}
/*************************************************************************/
/** 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);
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 */
return(FALSE);
errh_Error("RK512 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);
}
if ( !telegram_counter && (ReceiveBuffer[0] == 0X00) )
if ( !telegram_counter && (receive_buffer[0] == 0X00) )
{
/*************************************************************************/
/** This is a ordinary A-telegram. Make some error checks and treat it. */
......@@ -930,47 +584,48 @@ static unsigned int ReceiveHandler()
/* 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;
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] == receive_buffer[4])
search_remtrans = false;
}
}
} /* endwhile */
if ( search_remtrans ) remtrans = (remtrans_item *) remtrans->next;
}
if (search_remtrans)
{
/* No corresponding RemTrans object found */
remnode->objp->ErrTransCount++;
rn_RK512->ErrCount++;
CODE = '\x0A';
}
if ( !CODE )
{
/* Allowed type of telegram ? */
if ( ReceiveBuffer[2] != 'A' )
if ( receive_buffer[2] != 'A' )
CODE = '\x16';
}
if ( !CODE )
{
/* Allowed type of data ? */
if ( ReceiveBuffer[3] != 'D' )
if ( receive_buffer[3] != 'D' )
CODE = '\x10';
}
if ( !CODE )
{
/* Check size of received message */
datasize = (unsigned int)ReceiveBuffer[6];
datasize = (unsigned int)receive_buffer[6];
datasize = datasize << 8;
datasize = datasize | (unsigned int)ReceiveBuffer[7];
datasize = datasize | (unsigned int)receive_buffer[7];
datasize = datasize * 2; /* Convert from 16 bit words to bytes */
if ( datasize <= remtrans->objp->MaxLength)
{
......@@ -995,7 +650,7 @@ static unsigned int ReceiveHandler()
i < (HEADER_SIZE + MAX_SIZE_DATA_BLOCK) ;
i++ )
{
*TelegramBuffer_ptr++ = ReceiveBuffer[i];
*TelegramBuffer_ptr++ = receive_buffer[i];
}
pos_counter = MAX_SIZE_DATA_BLOCK;
}
......@@ -1003,9 +658,8 @@ static unsigned int ReceiveHandler()
if ( !CODE )
{
/* This message contains only one telegram. Treat it! */
ReceiveBuffer_ptr = &ReceiveBuffer[HEADER_SIZE];
sts = RemTrans_Receive(remtrans,
ReceiveBuffer_ptr,
(char *)&receive_buffer[HEADER_SIZE],
datasize);
if ( EVEN(sts) )
{
......@@ -1019,12 +673,12 @@ static unsigned int ReceiveHandler()
if ( !telegram_counter )
/* Wrong type of telegram received when A-telegram was expected */
{
remnode->objp->ErrTransCount++;
rn_RK512->ErrCount++;
CODE = '\x10';
}
}
if ( telegram_counter && (ReceiveBuffer[0] == 0XFF) && !CODE )
if ( telegram_counter && (receive_buffer[0] == 0XFF) && !CODE )
{
/*************************************************************************/
/** This is a follow on telegram. Make some error checks and treat it. **/
......@@ -1033,14 +687,14 @@ static unsigned int ReceiveHandler()
if ( !CODE )
{
/* Allowed type of telegram ? */
if ( ReceiveBuffer[2] != 'A' )
if ( receive_buffer[2] != 'A' )
CODE = '\x16';
}
if ( !CODE )
{
/* Allowed type of data ? */
if ( ReceiveBuffer[3] != 'D' )
if ( receive_buffer[3] != 'D' )
CODE = '\x10';
}
......@@ -1059,7 +713,7 @@ static unsigned int ReceiveHandler()
i < (FOLLOW_ON_HEADER_SIZE + delta_pos) ;
i++ )
{
*TelegramBuffer_ptr++ = ReceiveBuffer[i];
*TelegramBuffer_ptr++ = receive_buffer[i];
}
telegram_counter -= 1;
pos_counter += delta_pos;
......@@ -1076,7 +730,7 @@ static unsigned int ReceiveHandler()
}
TelegramBuffer_ptr = TelegramBuffer;
sts = RemTrans_Receive(remtrans,
TelegramBuffer_ptr,
(char *)TelegramBuffer_ptr,
datasize);
free(TelegramBuffer);
if ( EVEN(sts) )
......@@ -1100,7 +754,7 @@ static unsigned int ReceiveHandler()
}
sts = SendResponseTelegram(CODE);
if ( EVEN(sts) || (sts == ELN$_TIMEOUT) )
if ( EVEN(sts))
{
/* A fail has occured when sending response telegram */
return(FALSE);
......@@ -1109,227 +763,344 @@ static unsigned int ReceiveHandler()
{
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.
*
**************************************************************************
**************************************************************************/
#if 0
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 */
/*************************************************************************/
/** 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);
pwr_tClassId remnode_class; /* Vr remnod's class */
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");
#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;
time_since_io = 0;
rn_RK512->LinkUp = 1;
/* Get process-id to be able to kill myself.
Create subprocess to kill or to signal switch. */
return(sts);
}
}
ker$job_port(&sts, &job_port);
ker$current_process(&sts, &my_proc);
/*************************************************************************/
/** 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;
/* Create a name for my own process (first process in job) */
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 */
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);
/*************************************************************************/
/** 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;
ker$create_process( &sts, &id_p, WaitFor_PLC_Change,NULL);
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);
time_GetTime(&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, (char *)receive_buffer, data_size-3);
if ( EVEN(sts) )
{
remtrans->objp->ErrCount++;
return (FALSE);
}
}
else
{
/* No remtrans */
errh_Error("Remtrans RK512 no remtrans for this message");
rn_RK512->ErrCount++;
return (FALSE);
}
return (TRUE);
#endif
}
DeclareExitHandler();
static int SendResponseTelegram(unsigned char CODE)
{
unsigned int sts;
unsigned char BCC = '\0';
unsigned char ResponseTelegram[RESP_MESSAGE_SIZE+1];
sts = gdh_Init("rs_remote_rk512");
if (EVEN(sts)) exit(sts);
/* Hmta remnodens objid frn argumentvektorn */
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;
if (argc >= 3)
{
sts = cdh_StringToObjid( argv[2], &remnode->objid);
if (EVEN(sts)) exit(sts);
}
else
remnode->objid = pwr_cNObjid;
sts = send_it( (char *)ResponseTelegram, RESP_MESSAGE_SIZE);
return sts;
}
/* Kontrollera att objektet verkligen r en remnod */
/***************************************************
****** Main routine *****************
***************************************************/
sts = gdh_GetObjectClass(remnode->objid, &remnode_class);
if (EVEN(sts)) exit(sts);
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((char *) id, argv[1]);
else
strcpy((char *) id, "0");
/* Build process name with id */
if (remnode_class != pwr_cClass_RemNode) exit(0);
sprintf((char *) pname, "rs_remrk512_%s", id);
/* Hmta en pekare till remnoden */
/* Init of errh */
sts = gdh_ObjidToPointer(remnode->objid, (pwr_tAddress *) &remnode->objp);
if (EVEN(sts)) exit(sts);
errh_Init((char *) pname, errh_eAnix_remote);
errh_SetStatus(PWR__SRVSTARTUP);
/* Kontrollera att det r rtt transport */
/* Init of gdh */
if (remnode->objp->TransportType != REMNODE_TRANSPORT_RK512) exit(0);
sts = gdh_Init((char *) pname);
if ( EVEN(sts)) {
errh_Error("gdh_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
remnode->Time_since_scan = 0;
remnode->Time_since_poll = 0;
remnode->Time_since_IO = 0;
remnode->Time_since_send = 0;
/* Arg number 3 should be my remnodes objid in string representation,
read it, convert to real objid and store in remnode_item */
/* Initialize remtrans objects */
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);
}
sts = RemTrans_Init(remnode, 0);
if (EVEN(sts)) exit(sts);
/* Get pointer to RemnodeRK512 object and store locally */
sts = gdh_ObjidToPointer(rn.objid, (pwr_tAddress *) &rn_RK512);
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_RK512->ErrCount = 0;
sts = RemTrans_Init(&rn);
if ( EVEN(sts)) {
errh_Error("RemTrans_Init, %m", sts);
errh_SetStatus(PWR__SRVTERM);
exit(sts);
}
/* Get pointer to $Node-object */
sts = RemIO_Init_3964R(&rn);
sts = gdh_GetClassList( pwr_cClass_PlcProcess, &pwr_node);
sts = gdh_ObjidToPointer(pwr_node, (pwr_tAddress *) &pwr_nodep);
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_RK512 object */
remtrans = rn.remtrans;
i = 0;
while(remtrans) {
rn_RK512->RemTransObjects[i++] = remtrans->objid;
if ( i >= (int)(sizeof(rn_RK512->RemTransObjects)/sizeof(rn_RK512->RemTransObjects[0])))
break;
remtrans = (remtrans_item *) remtrans->next;
}
/* Initialize device */
sts = InitNet();
if (EVEN(sts)) exit(sts);
/* Initialize timers */
sts = InitTimers();
if (EVEN(sts)) exit(sts);
ser_fd = RemUtils_InitSerialDev(rn_RK512->DevName,
rn_RK512->Speed,
rn_RK512->DataBits,
rn_RK512->StopBits,
rn_RK512->Parity);
if (!ser_fd) {
errh_Error("InitDev, %d", ser_fd);
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
first = TRUE;
rn_RK512->LinkUp = 1;
/* Loop forever */
while (!doomsday)
while (1)
{
sts = Receive();
if (EVEN(sts)) exit(sts);
remnode->Time_since_send += remnode->objp->CycleTime;
sts = RemTrans_Cyclic(remnode, &remnode_send);
if (rn_RK512->Disable == 1) {
errh_Fatal("Disabled, exiting");
errh_SetStatus(PWR__SRVTERM);
exit(0);
}
// Wait micro time
// Wait cycle time
// timer = (int) (rn_RK512->ScanTime * 1000000.0);
usleep(30000);
Receive();
// time_since_poll += rn_RK512->ScanTime;
// time_since_io += rn_RK512->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_RK512->ScanTime) {
if (debug) printf("Remtrans Cyclic\n");
RemTrans_Cyclic(&rn, &remnode_send);
time_since_scan = 0.0;
}
if (use_remote_io) {
if ((rn_RK512->LinkUp && time_since_poll >= rn_RK512->ScanTime*2.0) ||
(!rn_RK512->LinkUp && time_since_poll >= rn_RK512->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_RK512->LinkTimeout && rn_RK512->LinkTimeout > 0) {
if (debug) printf("RemIO Stall\n");
sts = RemIO_Stall_3964R(&rn, stall_action);
}
}
first = FALSE;
}
}
......@@ -61,6 +61,7 @@
* i skvgarna till exe-filerna
* 040422 C Jurstrand 4.0.0
* 101209 R Karlsson Adderat std fr Websphere MQ
* 111102 cs RK512 ported from ELN version.
*
* Description:
* Start and control of transportprocesses for remote communication
......@@ -329,6 +330,28 @@ static void AddTransports()
sts = gdh_GetNextObject (objid, &objid);
}
sts = gdh_GetClassList (pwr_cClass_RemnodeRK512, &objid);
while ( ODD(sts))
{
sts = gdh_ObjidToPointer(objid, &objref);
sprintf(tp[tpcount].path, "rs_remote_rk512");
tp[tpcount].id = 0;
tp[tpcount].disable = &((pwr_sClass_Remnode3964R *) objref)->Disable;
tp[tpcount].restart_limit = &((pwr_sClass_RemnodeRK512 *) objref)->RestartLimit;
tp[tpcount].restarts = &((pwr_sClass_RemnodeRK512 *) objref)->RestartCount;
((pwr_sClass_RemnodeRK512 *) objref)->RestartCount = 0;
tp[tpcount].objid = objid;
tp[tpcount].objref = objref;
tp[tpcount].classid = pwr_cClass_RemnodeRK512;
tp[tpcount].cpid = -1;
tp[tpcount].first = true;
remcfgp->RemNodeObjects[tpcount] = objid;
tpcount++;
sts = gdh_GetNextObject (objid, &objid);
}
return;
}
......
!
! Proview Open Source Process Control.
! Copyright (C) 2005-2011 SSAB Oxelosund AB.
!
! This file is part of Proview.
!
! 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 Proview. If not, see <http://www.gnu.org/licenses/>
!
! Linking Proview statically or dynamically with other modules is
! making a combined work based on Proview. Thus, the terms and
! conditions of the GNU General Public License cover the whole
! combination.
!
! In addition, as a special exception, the copyright holders of
! Proview give you permission to, from the build function in the
! Proview Configurator, combine Proview with modules generated by the
! Proview PLC Editor to a PLC program, regardless of the license
! terms of these modules. You may copy and distribute the resulting
! combined work under the terms of your choice, provided that every
! copy of the combined work is accompanied by a complete copy of
! the source code of Proview (the version used to produce the
! combined work), being distributed under the terms of the GNU
! General Public License plus this exception.
!
! remote_c_remnoderk512.wb_load -- Defines the class RemnodeRK512.
!
SObject Remote:Class
!/**
! @Version 1.0
! @Group Servers,NodeConfiguration
! @Summary Configures communication to a remote system using Siemens RK512 on a serial line.
! Configures communication to a remote system using Siemens RK512 on a serial line..
!
! @b Object graph
! @image orm_remnoderk512_og.gif
!
! @b See also
! @classlink RemoteConfig pwrp_remoteconfig.html
! @classlink RemTrans ssab_remtrans.html
!*/
Object RemnodeRK512 $ClassDef 9
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_Standard
Attr PopEditor = 2
EndBody
Object RtBody $ObjBodyDef 1
Body SysBody
Attr StructName = "RemnodeRK512"
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 RemnodeRK512
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 = "rk512"
EndBody
EndObject
EndObject
EndSObject
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