diff --git a/Modbus TCP/Common.cin b/Modbus TCP/Common.cin new file mode 100644 index 0000000..11d4075 --- /dev/null +++ b/Modbus TCP/Common.cin @@ -0,0 +1,26 @@ +/*@!Encoding:1252*/ +void bin_to_strhex(byte bin[], char result[]) +{ + char hex_str[17]= "0123456789ABCDEF"; + word i; + word binsz; + + binsz = elCount(bin); + if (binsz > 20) + binsz = 20; + + for (i = 0; i < binsz; i++) + { + result[i * 3 + 0] = hex_str[bin[i] >> 4 ]; + result[i * 3 + 1] = hex_str[bin[i] & 0x0F]; + result[i * 3 + 2] = ' '; + } + + if (elCount(bin) > 20) + { + result[56] = '.'; + result[57] = '.'; + result[58] = '.'; + } + result[binsz * 3 - 1] = 0; +} \ No newline at end of file diff --git a/Modbus TCP/TcpCommon.can b/Modbus TCP/TcpCommon.can deleted file mode 100644 index 44a99a4..0000000 --- a/Modbus TCP/TcpCommon.can +++ /dev/null @@ -1,241 +0,0 @@ -/*@!Encoding:1252*/ -includes -{ -} - -variables -{ - const long WSA_IO_PENDING = 997; - const long WSAEWOULDBLOCK = 10035; - const dword INVALID_IP = 0xffffffff; - - long gIpLastErr = 0; - char gIpLastErrStr[512] = ""; - TcpSocket gSocket; - - - char gTcpRxBuffer[8192]; - char gUdpRxBuffer[4096]; -/* - - dword gIpAddress = INVALID_IP; - char gIpLastErrStr[1024] = ""; - char gIpAddressStr[32] = ""; - int gIpLastErr = 0; - - dword gUdpPort = 0; - long gUdpSocket = INVALID_SOCKET; - - dword gTcpPort = 0; - long gTcpSocket = INVALID_SOCKET; - long gTcpDataSocket = INVALID_SOCKET; - - // status - int gStatus = 0; - const int gkSTATUS_UNINITIALISED = 0; - const int gkSTATUS_INITIALISED = 1; -*/ -} -/* -long UdpRecv() -{ - int result = 0; - - result = gSocket.UdpReceiveFrom(gUdpRxBuffer, elcount( gUdpRxBuffer)); - - if ( 0 != result) - { - gIpLastErr = gSocket.GetLastSocketError(); - - if ( WSA_IO_PENDING != gIpLastErr) - { - gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount( gIpLastErrStr)); - - writelineex( 0, 2, "UdpReceive error (%d): %s", gIpLastErr, gIpLastErrStr); - } - } - - return result; -} -*/ - - -dword SetupIp(char Local_IP[]) -{ - int adapterIndex; - char text[512] = ""; - char info[512] = ""; - int size = 512; - dword addresses[1]; - dword address; - - writeClear(0); - - if (IpGetAdapterCount() < 1) - { - writelineex(0, 3, "<%BASE_FILE_NAME%> Error: There is no network interface available!"); - - stop(); - } - - adapterIndex = @sysvar::TCPIP::AdapterIndex; - - if (IpGetAdapterAddress(adapterIndex, addresses, 1) != 0) - { - writelineex(0, 3, "<%BASE_FILE_NAME%> Error: Could not retrieve ip address!"); - - stop(); - } - - address = addresses[0]; // the interface used - - if (address == INVALID_IP) - { - writelineex(0, 3, "<%BASE_FILE_NAME%> Error: ip address to be used is invalid!"); - - stop(); - } - - IpGetAdapterDescription(adapterIndex, text, size); - snprintf(info, size, "<%BASE_FILE_NAME%> Interface: %s", text); - writelineex(0, 1, info); - - IpGetAdapterAddressAsString(adapterIndex, text, size); - snprintf(info, size, "<%BASE_FILE_NAME%> Ip address: %s", text); - strncpy(Local_IP, text, 16); - writelineex(0, 1, info); - - IpGetAdapterMaskAsString(adapterIndex, text, size); - snprintf(info, size, "<%BASE_FILE_NAME%> Subnet mask: %s", text); - writelineex(0, 1, info); - - IpGetAdapterGatewayAsString(adapterIndex, text, size); - snprintf(info, size, "<%BASE_FILE_NAME%> Gateway address: %s", text); - writelineex(0, 1, info); - - return address; -} - -word OpenSocket() -{ - char Local_IP[16]; - dword localIp; - word localPort; - dword i = 0; - CHAR errorText[200]; - - localIp = SetupIp(Local_IP); - localPort = random(65535-10240)+10240; - - // Try to open socket - do - { - gSocket = TcpSocket::Open(localIp, localPort); - if (gSocket.GetLastSocketError() != 0) - { - gSocket.GetLastSocketErrorAsString(errorText, elcount(errorText)); - writelineex(0, 1, "<%BASE_FILE_NAME%> Error: could not open Tcp socket on %s:%d, %s (%d)!", Local_IP, localPort, errorText, gSocket.GetLastSocketError()); - } - } - while (gSocket.GetLastSocketError() != 0 && i++ < 9); - - if (gSocket.GetLastSocketError() != 0) - { - writelineex(0, 1, "<%BASE_FILE_NAME%> Error: could not open Tcp socket!"); - return gSocket.GetLastSocketError(); - } - else - { - writelineex(0, 1, "<%BASE_FILE_NAME%> Tcp socket opened on %s:%d.", Local_IP, localPort); - } - return 0; - -} - -word TcpConnectTo(char Remote_IP[], word remotePort) -{ - dword remoteIp; - long fehler; - - // Try to open a socket - fehler = OpenSocket(); - if (fehler != 0) - { - return fehler; - } - - // Convert IP string to Number - remoteIp = IpGetAddressAsNumber(Remote_IP); - if (remoteIp == INVALID_IP) - { - writelineex(0, 1, "<%BASE_FILE_NAME%> Error: invalid server Ip address!"); - - return 1; - } - - - // Connect to Server - if (gSocket.Connect(remoteIp, remotePort) != 0) - { - fehler = gSocket.GetLastSocketError(); - - if (fehler != WSAEWOULDBLOCK) // OnTcpConnect will be called otherwise - { - write("<%BASE_FILE_NAME%> No Port-Connection: %d", fehler); - return fehler; - } - return 0; - } - else - { - writelineex(0, 1, "<%BASE_FILE_NAME%> Successfully connected to server %s:%d", Remote_IP, remotePort); - TcpRecv(); - return 0; - } - -} - -void OnTcpConnect(dword socket, long result) -{ - if (result != 0) - { - gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr)); - - writelineex(0, 2, "<%BASE_FILE_NAME%> OnTcpConnect error (%d): %s", gSocket.GetLastSocketError(), gIpLastErrStr); - - return; - } - else - { - writelineex(0, 1, "<%BASE_FILE_NAME%> Successfully connected to server"); - } -} - -long TcpRecv() -{ - int result; - - result = gSocket.Receive(gTcpRxBuffer, elcount(gTcpRxBuffer)); - - if (result != 0) - { - gIpLastErr = gSocket.GetLastSocketError(); - - if (WSA_IO_PENDING != gIpLastErr) - { - gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount( gIpLastErrStr)); - - writelineex(0, 2, "<%BASE_FILE_NAME%> TcpReceive error (%d): %s", gIpLastErr, gIpLastErrStr); - } - else - { - writelineex(0, 1, "<%BASE_FILE_NAME%> TcpReceive was IO pending", gTcpRxBuffer); - } - } - else - { - writelineex(0, 1, "<%BASE_FILE_NAME%> TcpReceive: %s", gTcpRxBuffer); - } - - return result; -} \ No newline at end of file diff --git a/Modbus TCP/TcpCommon.cin b/Modbus TCP/TcpCommon.cin new file mode 100644 index 0000000..e2d36c8 --- /dev/null +++ b/Modbus TCP/TcpCommon.cin @@ -0,0 +1,260 @@ +/*@!Encoding:1252*/ +includes +{ + #include "Common.cin" +} + +variables +{ + const long WSA_IO_PENDING = 997; + const long WSAEWOULDBLOCK = 10035; + const dword INVALID_IP = 0xffffffff; + + long gIpLastErr = 0; + char gIpLastErrStr[512] = ""; + TcpSocket g_%NODE_NAME%_Socket; + + enum TcpState { NULL, OK, ERROR, CLOSED }; + enum TcpState g_%NODE_NAME%_TcpState = NULL; + + + byte gTcpRxBuffer[8192]; +} + + +dword SetupIp(char Local_IP[]) +{ + int adapterIndex; + char text[512] = ""; + char info[512] = ""; + int size = 512; + dword addresses[1]; + dword address; + + writeClear(0); + + if (IpGetAdapterCount() < 1) + { + writelineex(0, 3, "<%BASE_FILE_NAME%> Error: There is no network interface available!"); + + stop(); + } + + adapterIndex = @sysvar::TCPIP::AdapterIndex; + + if (IpGetAdapterAddress(adapterIndex, addresses, 1) != 0) + { + writelineex(0, 3, "<%BASE_FILE_NAME%> Error: Could not retrieve ip address!"); + + stop(); + } + + address = addresses[0]; // the interface used + + if (address == INVALID_IP) + { + writelineex(0, 3, "<%BASE_FILE_NAME%> Error: ip address to be used is invalid!"); + + stop(); + } + + IpGetAdapterDescription(adapterIndex, text, size); + snprintf(info, size, "<%BASE_FILE_NAME%> Interface: %s", text); + writelineex(0, 1, info); + + IpGetAdapterAddressAsString(adapterIndex, text, size); + snprintf(info, size, "<%BASE_FILE_NAME%> Ip address: %s", text); + strncpy(Local_IP, text, 16); + writelineex(0, 1, info); + + IpGetAdapterMaskAsString(adapterIndex, text, size); + snprintf(info, size, "<%BASE_FILE_NAME%> Subnet mask: %s", text); + writelineex(0, 1, info); + + IpGetAdapterGatewayAsString(adapterIndex, text, size); + snprintf(info, size, "<%BASE_FILE_NAME%> Gateway address: %s", text); + writelineex(0, 1, info); + + return address; +} + +word OpenSocket() +{ + char Local_IP[16]; + dword localIp; + word localPort; + dword i = 0; + CHAR errorText[200]; + + localIp = SetupIp(Local_IP); + localPort = random(65535-10240)+10240; + + // Try to open socket + do + { + g_%NODE_NAME%_Socket = TcpSocket::Open(localIp, localPort); + if (g_%NODE_NAME%_Socket.GetLastSocketError() != 0) + { + g_%NODE_NAME%_Socket.GetLastSocketErrorAsString(errorText, elcount(errorText)); + writelineex(0, 1, "<%BASE_FILE_NAME%> Error: could not open Tcp socket on %s:%d, %s (%d)!", Local_IP, localPort, errorText, g_%NODE_NAME%_Socket.GetLastSocketError()); + } + } + while (g_%NODE_NAME%_Socket.GetLastSocketError() != 0 && i++ < 9); + + if (g_%NODE_NAME%_Socket.GetLastSocketError() != 0) + { + writelineex(0, 1, "<%BASE_FILE_NAME%> Error: could not open Tcp socket!"); + return g_%NODE_NAME%_Socket.GetLastSocketError(); + } + else + { + writelineex(0, 1, "<%BASE_FILE_NAME%> Tcp socket opened on %s:%d.", Local_IP, localPort); + } + return 0; + +} + +word TcpConnectTo(char Remote_IP[], word remotePort) +{ + dword remoteIp; + long fehler; + + // Try to open a socket + fehler = OpenSocket(); + if (fehler != 0) + { + return fehler; + } + + // Convert IP string to Number + remoteIp = IpGetAddressAsNumber(Remote_IP); + if (remoteIp == INVALID_IP) + { + writelineex(0, 1, "<%BASE_FILE_NAME%> Error: invalid server Ip address!"); + + return 1; + } + + + // Connect to Server + if (g_%NODE_NAME%_Socket.Connect(remoteIp, remotePort) != 0) + { + fehler = g_%NODE_NAME%_Socket.GetLastSocketError(); + + if (fehler != WSAEWOULDBLOCK) // OnTcpConnect will be called otherwise + { + write("<%BASE_FILE_NAME%> No Port-Connection: %d", fehler); + g_%NODE_NAME%_TcpState = ERROR; + return fehler; + } + return 0; + } + else + { + writelineex(0, 1, "<%BASE_FILE_NAME%> Successfully connected to server %s:%d", Remote_IP, remotePort); + g_%NODE_NAME%_TcpState = OK; + return 0; + } + +} + +void OnTcpConnect(dword socket, long result) +{ + if (result != 0) + { + g_%NODE_NAME%_Socket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr)); + writelineex(0, 2, "<%BASE_FILE_NAME%> OnTcpConnect error (%d): %s", g_%NODE_NAME%_Socket.GetLastSocketError(), gIpLastErrStr); + g_%NODE_NAME%_TcpState = ERROR; + return; + } + else + { + writelineex(0, 1, "<%BASE_FILE_NAME%> Successfully connected to server"); + g_%NODE_NAME%_TcpState = OK; + } +} + +void TcpRecv() +{ + int result; + + if (g_%NODE_NAME%_TcpState != OK) + { + writelineex(0, 2, "TcpRecv: Socket status is not OK!"); + return; + } + + result = g_%NODE_NAME%_Socket.Receive(gTcpRxBuffer, elcount(gTcpRxBuffer)); + + if (result != 0) // Calling OnTcpReceive otherwise + { + gIpLastErr = g_%NODE_NAME%_Socket.GetLastSocketError(); + + if (gIpLastErr != WSA_IO_PENDING) // Calling OnTcpReceive otherwise + { + g_%NODE_NAME%_Socket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr)); + writelineex(0, 2, "<%BASE_FILE_NAME%> TcpReceive error (%d): %s", gIpLastErr, gIpLastErrStr); + g_%NODE_NAME%_Socket.Close(); + g_%NODE_NAME%_TcpState = CLOSED; + } + } + + return; +} + +void OnTcpReceive(dword socket, long result, dword address, dword port, char buffer[], dword size) +{ + char str[20*3]; + + if (result == 0) + { + if (size == 0) + { + // Size of zero indicates that the socket was closed by the communication peer. + writelineex(0, 2, "<%BASE_FILE_NAME%> OnTcpReceive: Socket closed by peer"); + g_%NODE_NAME%_Socket.Close(); + g_%NODE_NAME%_TcpState = CLOSED; + } + else + { + // Sucessfully received some bytes over the TCP/IP connection. + bin_to_strhex(gTcpRxBuffer, str); + writelineex(0, 1, "<%BASE_FILE_NAME%> OnTcpReceive: %s", str); + } + } + else + { + gIpLastErr = g_%NODE_NAME%_Socket.GetLastSocketError(); + g_%NODE_NAME%_Socket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr)); + writelineex(0, 2, "<%BASE_FILE_NAME%> OnTcpReceive error (%d): %s", gIpLastErr, gIpLastErrStr); + g_%NODE_NAME%_Socket.Close(); + g_%NODE_NAME%_TcpState = CLOSED; + } +} + +void TcpSnd(byte buffer[]) +{ + char str[20*3]; + + if (g_%NODE_NAME%_TcpState != OK) + { + writelineex(0, 2, "TcpSnd: Socket status is not OK!"); + return; + } + + bin_to_strhex(buffer, str); + writelineex(0, 1, "<%BASE_FILE_NAME%> TcpSnd: %s (Länge: %d)", str, elCount(buffer)); + + if (g_%NODE_NAME%_Socket.Send(buffer, elCount(buffer)) != 0) + { + gIpLastErr = g_%NODE_NAME%_Socket.GetLastSocketError(); + + if (gIpLastErr != WSA_IO_PENDING) + { + g_%NODE_NAME%_Socket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr)); + writelineex(0, 2, "<%BASE_FILE_NAME%> TcpSnd error (%d): %s", gIpLastErr, gIpLastErrStr); + g_%NODE_NAME%_Socket.Close(); + g_%NODE_NAME%_TcpState = CLOSED; + } + } +} \ No newline at end of file diff --git a/Modbus TCP/socket.can b/Modbus TCP/socket.can index c68a4a2..f367184 100644 --- a/Modbus TCP/socket.can +++ b/Modbus TCP/socket.can @@ -2,12 +2,11 @@ includes { - #include "TcpCommon.can" + #include "TcpCommon.cin" } variables { - int state = 0; } // Get information of local network interface such like ip address @@ -21,34 +20,31 @@ on start { long fehler; - fehler = TcpConnectTo("192.168.1.3", 502); - state = fehler == 0; + TcpConnectTo("192.168.1.3", 502); } -on key 'd' +on key 's' { SendTcpData(); } +on key 'r' +{ + TcpRecv(); +} + void SendTcpData() { const word length = 12; - char buffer[length]; - - if (state == 0) - { - writelineex(0, 2, "Tcp socket is invalid!"); - - return; - } + byte buffer[length]; // Modbus Application Header - buffer[00] = 0x23; // [2] Transaction ID - buffer[01] = 0x45; + buffer[00] = 0x0C; // [2] Transaction ID + buffer[01] = 0x2D; buffer[02] = 0x00; // [2] Protocol ID = 0 buffer[03] = 0x00; buffer[04] = (length-6)>>8; // [2] Length; Number of bytes following - buffer[05] = (length-6); + buffer[05] = (length-6)&0xFF; buffer[06] = 0xFF; // [1] Unit identifier; not relevant // Payload buffer[07] = 0x01; // [1] Function Code; 1:Read DI; 2:Read DIO; 3:Read AIO; 4:Read AI; 5:Write 1 DO; 6:Write 1 AO; 7: Read Exeption, 15:Write n DO; 16:Write n AO; @@ -56,24 +52,8 @@ void SendTcpData() buffer[09] = 0x00; buffer[10] = 0x01; // [2] Number of items; 1:max 2000=0x7D0 buffer[11] = 0xFF; - - write("Sende '%s' (Länge: %d)", buffer, length); - if (gSocket.Send(buffer, elCount(buffer)) != 0) - { - gIpLastErr = gSocket.GetLastSocketError(); - - if (gIpLastErr != WSA_IO_PENDING) - { - gSocket.GetLastSocketErrorAsString(gIpLastErrStr, elcount(gIpLastErrStr)); - - writelineex(0, 2, "Tcp send error (%d): %s", gIpLastErr, gIpLastErrStr); - } - } - else - { - writelineex(0, 1, "Tcp data sent successfully!"); - } + TcpSnd(buffer); } /**/