/*=============================================================================| | PROJECT SNAP7 1.4.0 | |==============================================================================| | Copyright (C) 2013, 2014 Davide Nardella | | All rights reserved. | |==============================================================================| | SNAP7 is free software: you can redistribute it and/or modify | | it under the terms of the Lesser GNU General Public License as published by | | the Free Software Foundation, either version 3 of the License, or | | (at your option) any later version. | | | | It means that you can distribute your commercial software linked with | | SNAP7 without the requirement to distribute the source code of your | | application and without the requirement that your application be itself | | distributed under LGPL. | | | | SNAP7 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 | | Lesser GNU General Public License for more details. | | | | You should have received a copy of the GNU General Public License and a | | copy of Lesser GNU General Public License along with Snap7. | | If not, see http://www.gnu.org/licenses/ | |==============================================================================| | | | Server Example | | | |=============================================================================*/ #include #include #include #include "snap7.h" S7Object Server; typedef byte TRWBuffer[1024]; typedef byte *PRWBuffer; byte cnt = 0; //------------------------------------------------------------------------------ // hexdump, a very nice function, it's not mine. // I found it on the net somewhere some time ago... thanks to the author ;-) //------------------------------------------------------------------------------ #ifndef HEXDUMP_COLS #define HEXDUMP_COLS 16 #endif void hexdump(void *mem, unsigned int len) { unsigned int i, j; for (i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++) { /* print offset */ if (i % HEXDUMP_COLS == 0) { printf("0x%04x: ", i); } /* print hex data */ if (i < len) { printf("%02x ", 0xFF & ((char*)mem)[i]); } else /* end of block, just aligning for ASCII dump */ { printf(" "); } /* print ASCII dump */ if (i % HEXDUMP_COLS == (HEXDUMP_COLS - 1)) { for (j = i - (HEXDUMP_COLS - 1); j <= i; j++) { if (j >= len) /* end of block, not really printing */ { putchar(' '); } else if (isprint((((char*)mem)[j] & 0x7F))) /* printable char */ { putchar(0xFF & ((char*)mem)[j]); } else /* other char */ { putchar('.'); } } putchar('\n'); } } } //------------------------------------------------------------------------------ // Read/Write callback //------------------------------------------------------------------------------ int S7API RWAreaCallBack(void *usrPtr, int Sender, int Operation, PS7Tag PTag, void *pUsrData) { PRWBuffer PBuffer = (PRWBuffer)pUsrData; int c; if (Operation == OperationRead) printf("Read Request\n"); else printf("Write Request\n"); switch (PTag->Area) { //case S7AreaPE: printf("Area : PE, "); case 0x81: printf("Area : PE, "); break; case 0x82: printf("Area : PA, "); break; case 0x83: printf("Area : MK, "); break; case 0x1C: printf("Area : CT, "); break; case 0x1D: printf("Area : TM, "); break; case 0x84: printf("Area : DB%d, ", PTag->DBNumber); break; default: printf("Unknown area %d, ", PTag->Area); } printf("Start : %d, ", PTag->Start); printf("Size : %d\n", PTag->Size); if (Operation == OperationWrite) hexdump(pUsrData, PTag->Size); else { for (c = 0; c < 1024; c++) PBuffer[c] = cnt; cnt++; } printf("\n"); return 0; }; // Here we use the callback to show the log, this is not the best choice since // the callback is synchronous with the client access, i.e. the server cannot // handle futher request from that client until the callback is complete. // The right choice is to use the log queue via the method PickEvent. void S7API EventCallBack(void *usrPtr, PSrvEvent PEvent, int Size) { // print the event char text[1024]; Srv_EventText(PEvent, text, 1024); printf("%s\n",text); }; int main(int argc, char* argv[]) { int Error; char text[1024]; Server = Srv_Create(); // Filter a bit of noise Srv_SetMask(Server, mkEvent, 0x3ff); // Set the Read/Write callback Srv_SetRWAreaCallback(Server, RWAreaCallBack, NULL); // Set the event callback to show something : it's not strictly needed. // If you comment next line the server still works fine. Srv_SetEventsCallback(Server, EventCallBack, NULL); // Start the server onto the default adapter. // To select an adapter we have to use Srv_StartTo(Server, "192.168.x.y"). // Start() is the same of StartTo("0.0.0.0"); Error=Srv_Start(Server); if (Error==0) { // Now the server is running ... wait a key to terminate getchar(); } else { Srv_ErrorText(Error, text, 1024); printf("%s\n", text); } // If you got a start error: // Windows - most likely you ar running the server in a pc on wich is // installed step 7 : open a command prompt and type // "net stop s7oiehsx" (Win32) or // "net stop s7oiehsx64" (Win64) // And after this test : // "net start s7oiehsx" (Win32) or // "net start s7oiehsx64" (Win64) // Unix - you need root rights :-( because the isotcp port (102) is // low and so it's considered "privileged". Srv_Stop(Server); // <- not strictly needed, every server is stopped on deletion // and every client is gracefully disconnected. Srv_Destroy(&Server); } // Finally, this is a very minimalist (but working) server : /* int main(int argc, char* argv[]) { TS7Server *Server = new TS7Server; Server->Start(); getchar(); delete Server; } */