<< 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 |
server.SendAndReceiveDataByMask
Port operations can be used in nodes of the COM or TCP type.
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( );
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( );
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:
1 – if number:
0 – without a checksum
1 – the DCON checksum
2 – the CRC16 checksum
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:
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.
2 – number of elements in the initial table (if 0, the function only receives data and does not send anything)
3 – a table of format masks
4 – the initial table
5 – a table of masks of received data or nil
6 – maximal number of received bytes. If 0, the function only sends data.
Optional parameters:
7 – string name of the function that will be called before sending the request to the device;
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:
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);
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:
1 – if less than 0 – error code; if greater than or equals 0 – number of received bytes
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)
3 – number of elements in the table
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.
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:
-1 – timeout error
-11 – checksum error, or there is no an end character
-10 – not enough bytes for a checksum
-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
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
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
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