Functions to Operate with Ports

<< Click to Display Table of Contents >>

Navigation:  Multi-Protocol MasterOPC Server > Lua 5.1 Reference Manual > Function library > The SERVER Library >

Functions to Operate with Ports

Functions to Operate with Ports

mbul_mail server.CloseConnection

mbul_mail server.OpenConnection

mbul_mail server.SendAndReceiveData

mbul_mail server.SendAndReceiveDataByMask

mbul_mail server.SetDTR

mbul_mail server.SetRTS

Port operations can be used in nodes of the COM or TCP type.

server.CloseConnection

This function closes a port (terminates the connection).

Along with server.OpenConnection , the function can be used to re-initialize a node manually.

The function can be invoked from a script of a device or a tag of the PROGRAM type.

Example

server.CloseConnection( );

server.OpenConnection

This function opens a port (establishes the connection).

Along with server.CloseConnection , the function can be used to re-initialize a node manually.

The function can be invoked from a script of a device or a tag of the PROGRAM type.

Example

server.OpenConnection( );

server.SendAndReceiveData

Writes to the COM or TCP port  and receives from the port data according to node settings.

Input parameters are: data to be sent, a length of data to be sent by bytes, and a length of received data.

Example

err,buf,len =  server.SendAndReceiveData(srcbuf,srclen,dstlen)

err=TRUE if an error is detected when executing the function. buf is a string containing received data (nil if there was no a reception). len is a length of buf.

If a length of received data equals 0, the function only sends.

After writing data, the reception timeout is activated. If at least one data byte is received, the inter-character timeout is activated. If the inter-character timeout passed by, and there is no more information, the function ends and transfers to the output number of received bytes; otherwise, the function receives that number of bytes that is specified in the respective input parameter.

server.SendAndReceiveDataByMask

Sends a formatted sequence of bytes to a COM or TCP port.

A device address is obtained from the current device.

Input arguments are:

mbul   1 – if number:

mbul   0 – without a checksum

mbul   1 – the DCON checksum

mbul   2 – the CRC16 checksum

mbul   3 – the checksum LRC16 - when this function is selected, the Modbus ASCII frame is automatically generated. RTU bytes are converted to ASCII characters, also symbol "colon" is added at the beginning of the packet, an LRC checksum and two end characters (CR and LF). The packet received from the device is also converted: checksum, termination characters and colon are discarded, characters are converted to an RTU frame. Thus, when working with Modbus ASCII, the formation of the frame is completely identical as for Modbus RTU, and further conversion to the correct format is performed automatically.

if character or string:

mbul   checking the received byte sequence for the end of this character or string. To form a string from non-printable characters, you can use the function string.char;

Note. Checksums and the end character are not transferred into the input buffer.

mbul   2 – number of elements in the initial table (if 0, the function only receives data and does not send anything)

mbul   3 – a table of format masks

mbul   4 – the initial table

mbul   5 – a table of masks of received data or nil

mbul   6 – maximal number of received bytes. If 0, the function only sends data.

Optional parameters:

mbul   7 – string name of the function that will be called before sending the request to the device;

mbul   8 – the string name of the function that will be called after receiving the response from the instrument;

Parameters 7 and 8 are intended for calling the external processing functions of the output and input buffer. As an input argument, the functions being called should take a byte table, and should also return two parameters:

mbul   1 -  is the number of bytes generated, or the error code is a negative number (except -1, since this is a sign of no response);

mbul   2 - processed byte table (for example, a table with added checksum).

It can be used to invoke functions of checksum counting (see example).

A format of the mask of output conversions is String1:String2:String3, where String1 is a data format and String2 is a swapping string, String3 - number of items to send. Data formats are string, byte, int16, uint16, int32, uint32, float and double. The formats string and byte do not require a swapping string. For other formats, "10325476" is used if a swapping string is not specified. Formation examples - "int16:10:4" (4 int16 with swap "High first"), "byte::2" (2 bytes, swap not used).

A format of the mask of input conversions is String1:String2:String3, where String1 is a data format, String2 is a number of received numbers, and String3 is a string of byte swapping (or, for formats with the prefix s, number of bytes to receive a number of the specified format). Data formats are string, byte, int16, uint16, int32, uint32, float, double, sint32 and sdouble (the formats sint32 and sdouble require a string of byte number instead of a string of byte swapping).

Note. When specifying a mask of type string in the input conversion table, the following format masks are ignored. That is, for example, in the mask ("byte", "int16:1:01", "string", "float:1:3210") the mask "float:1:3210" will be ignored, and the bytes of this element will be included in the string. Therefore, if string elements are in the middle of a packet, must be read them as a set of regular bytes and then convert them to a string using the string.char function. This is not required for the table of masks of output transformations - the transformation is carried out according to the masks of the table, regardless of the data types of the masks.

If conversion masks are not defined, bytes are transferred from tables and received to tables without conversions.

If the mask of input conversions is used up, but still there are bytes in the reception buffer, then remained bytes are converted into single character string of the reception table.

Returned values are:

mbul   1 – if less than 0 – error code; if greater than or equals 0 – number of received bytes

mbul   2 – a table; each element of that table is equal to a number/string according to the mask of conversions, or to a byte from the reception buffer (if a mask of conversions is not defined)

mbul   3 – number of elements in the table

mbul   4 – a string; each character of that string is equal to a byte from the reception buffer (regardless of whether a mask is used or not). This string is needed if a non-standard checksum (the first argument is set to 0) is required to be calculated by each byte (see Example 3). This output parameter may be not used if one from standard checksums is calculated.

mbul   5 – number of received bytes. This element is needed, for example, if a non-standard checksum is required to be calculated. This output parameter may be not used if one from standard checksums is calculated.

Error codes are:

mbul   -1 – timeout error

mbul   -11 – checksum error, or there is no an end character

mbul   -10 – not enough bytes for a checksum

mbul   -12 – no ending characters CR and LF (for option 3 - Modbus ASCII).

Example 1

The function sends a byte string to a MODBUS device (read out 2 registers, starting from the address 0):

01 03 00 00 00 02 C4 0B

receives a string:

01 03 04 00 20 00 00 FB F9

and converts the received string into two int16-type numbers.

--dest[1] - 1

--dest[2] - 3

--dest[3] - 4

 

--dest[4] – 32 register from address 0

--dest[4] – 0 register from address 1

 

local send={1,3,0,3};

local sendmask={"byte","byte","int16:10","int16:10"};

local dest={};

local destmask={"byte","byte","byte","int16:2:10"};

local err,len;

err,dest,len=server.SendAndReceiveDataByMask(2,4,sendmask,send,destmask,200);

if err<0 then

server.Message("err=",err);

else

server.Message("lenb=",err," lentabl=",len);

server.Message("dest[1]=",dest[1]," dest[2]=",dest[2]," dest[3]=",dest[3]);

server.Message("dest[4]=",dest[4]," dest[5]=",dest[5]);

end

Example 2

The function sends a request to I-7017:

#01\r

and receives channel values in the character format:

>+05.000+04.235+03.235+02.235+01.235+00.235+04.235+07.235\r

--dest[1] - '>'

--dest[2] - 5

--dest[3] - 4.235

 

--dest[9] - 7.237

--dest[10] - '\r'

 

local send={'#01\r'};

local sendmask={};

local dest={};

local destmask={"string:1","sdouble:8:7","byte"};

local err,len;

err,dest,len=server.SendAndReceiveDataByMask(1,1,nil,send,destmask,200);

if err<0 then

server.Message("err=",err);

else

server.Message("lenb=",err," lentabl=",len);

server.Message("dest[1]=",dest[1]," dest[2]=",dest[2]," dest[3]=",dest[3]);

end

Example 3

The function sends into the device Metacon-562 ( Rnet protocol ) a reading request for a measured value of the INPUT1 input:

01 – device address

00 – channel number (numeration starts with 0)

01 – number of a register that stores a measured value

00 – reading command

CRC – checksum

The device reply is:

01 – device address

00 – channel number

01 – register number

00 – reading command

TYP – data type field

DATA – data (received value)

CRC – checksum

A checksum is considered according to its own algorithm. When calling the server.SendAndReciveDataByMask function, the user functions SendCrc and GetCrc are also called, which process the input and output buffer - they calculate the checksum, add / remove the checksum byte.

The code is:

--checksum calculation

function CRCsum(Frame)              

I,J=0;                       --Cycle counters

CRC=0;                          

AUX,DAT=0;                      

CRC = 255;                          

local Length = table.maxn(Frame); --Message length (without checksum!)

for I= 1,Length,1 do           - Cycle by message length

   DAT = Frame[I];  

   for J= 0, 7,1 do        

       AUX = bit.BitAnd(bit.BitXor(DAT,CRC),1 );    

       if AUX == 1 then CRC = bit.BitXor(CRC,24);

       end;    

       CRC = bit.BitRshift(CRC,1 );                  

       CRC = bit.BitOr(CRC,bit.BitLshift(AUX,7 ) );  

       DAT =bit.BitRshift(DAT,1 );                  

   end;                                

end;  

return CRC;                          

end

-- function called before sending to the device

function SendCrc(SendTable)

Byte1=CRCsum(SendTable);

table.insert(SendTable,Byte1);

--return the number of bytes and the modified table

return table.maxn(SendTable),SendTable;

end

 

--function called after receiving a response

function GetCrc(GetTable)

GetByte1=table.remove(GetTable); --delete the last one and save it in GetByte

CalcByte1=ModbusCRC(GetTable);

if GetByte1~=CalcByte1 then

   return -10,GetTable; --return checksum error

end

--return the number of bytes and the modified table

return table.maxn(GetTable),GetTable;

end

 

function OnRead()    

local Addr=server.GetCurrentDeviceAddress( );                  

local send = {Addr,1,1,0}; -- read request frame without checksum                                      

local sendmask={"byte","byte","byte","byte"}; --request mask

local dest={}; --masked value table

local destmask={"byte","byte","byte","byte","byte","int16:1:01"}; --response mask

--additional variables: error, number of elements in the dest table, number of bytes received

local err,len;

local n=0; --request retries

--perform queries in a loop

repeat

--request to device with calling checksum counting functions

err,dest,len=server.SendAndReceiveDataByMask(0,5,sendmask,send,destmask,200,"SendCrc","GetCrc");

if err==-1 then - no response from device

   break; --exit from loop

end

--check that the device address, channel number and register number match

if dest[1]~=send[1] or dest[2]~=send[2] or dest[3]~=send[3] then

   err=-2; --error

end    

n=n+1;

--exit from the cycle - correct response or exceeding the number of attempts

until err>=0  or n>=server.GetCurrentDeviceRetry( );

if err<0 then                  

 --Data is not accepted or data is incorrect. Set a bad quality

   server.WriteCurrentTag(0,OPC_QUALITY_BAD); --

else

   --Write the accepted value to the tag

   server.WriteCurrentTag(dest[len-1],OPC_QUALITY_GOOD);

end;

end

         

server.SetDTR

This function controls the DTR signal. A new state of the port output is passed to the function via its argument.

The function can be used only in a COM-type node.

Example

server.SetDTR(true);      

Note. For this function to work correctly, it is necessary that the port be open in advance. Functions server.SendAndReciveDataByMask and server.SendAndReciveData open the port when they are first called, so the port must be opened in advance using the function server.OpenConnection

 

server.SetRTS

This function controls the RTS signal. A new state of the port output is passed to the function via its argument.

The function can be used only in a COM-type node.

Example

server.SetRTS(true);      

Note. For this function to work correctly, it is necessary that the port be open in advance. Functions server.SendAndReciveDataByMask and server.SendAndReciveData open the port when they are first called, so the port must be opened in advance using the function server.OpenConnection