1 /*=============================================================================| 2 | PROJECT SNAP7 1.4.0 | 3 |==============================================================================| 4 | Copyright (C) 2013, Davide Nardella | 5 | All rights reserved. | 6 |==============================================================================| 7 | SNAP7 is free software: you can redistribute it and/or modify | 8 | it under the terms of the Lesser GNU General Public License as published by | 9 | the Free Software Foundation, either version 3 of the License, or | 10 | (at your option) any later version. | 11 | | 12 | It means that you can distribute your commercial software linked with | 13 | SNAP7 without the requirement to distribute the source code of your | 14 | application and without the requirement that your application be itself | 15 | distributed under LGPL. | 16 | | 17 | SNAP7 is distributed in the hope that it will be useful, | 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 20 | Lesser GNU General Public License for more details. | 21 | | 22 | You should have received a copy of the GNU General Public License and a | 23 | copy of Lesser GNU General Public License along with Snap7. | 24 | If not, see http://www.gnu.org/licenses/ | 25 |==============================================================================| 26 | | 27 | Resourceless Server example (1.4.0) | 28 | The Server ha not shared resources. On every Read/Write request a callback | 29 | is invoked. | 30 | To the callback are passed the Tag (Area, Start...) and a pointer to a data | 31 | that you can read/write. | 32 | | 33 |=============================================================================*/ 34 35 using System; 36 using System.Runtime.InteropServices; 37 using System.Text; 38 using Snap7; 39 40 class ServerDemo 41 { 42 static S7Server Server; 43 private static S7Server.TSrvCallback TheEventCallBack; // <== Static var containig the callback 44 private static S7Server.TSrvRWAreaCallback TheRWAreaCallBack; // <== Static var containig the callback 45 private static byte cnt = 0; 46 //------------------------------------------------------------------------------ 47 // HexDump, a very nice function, it's not mine. 48 // I found it on the net somewhere some time ago... thanks to the author ;-) 49 //------------------------------------------------------------------------------ HexDump(byte[] bytes, int Size)50 static void HexDump(byte[] bytes, int Size) 51 { 52 if (bytes == null) 53 return; 54 int bytesLength = Size; 55 int bytesPerLine = 16; 56 57 char[] HexChars = "0123456789ABCDEF".ToCharArray(); 58 59 int firstHexColumn = 60 8 // 8 characters for the address 61 + 3; // 3 spaces 62 63 int firstCharColumn = firstHexColumn 64 + bytesPerLine * 3 // - 2 digit for the hexadecimal value and 1 space 65 + (bytesPerLine - 1) / 8 // - 1 extra space every 8 characters from the 9th 66 + 2; // 2 spaces 67 68 int lineLength = firstCharColumn 69 + bytesPerLine // - characters to show the ascii value 70 + Environment.NewLine.Length; // Carriage return and line feed (should normally be 2) 71 72 char[] line = (new String(' ', lineLength - 2) + Environment.NewLine).ToCharArray(); 73 int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine; 74 StringBuilder result = new StringBuilder(expectedLines * lineLength); 75 76 for (int i = 0; i < bytesLength; i += bytesPerLine) 77 { 78 line[0] = HexChars[(i >> 28) & 0xF]; 79 line[1] = HexChars[(i >> 24) & 0xF]; 80 line[2] = HexChars[(i >> 20) & 0xF]; 81 line[3] = HexChars[(i >> 16) & 0xF]; 82 line[4] = HexChars[(i >> 12) & 0xF]; 83 line[5] = HexChars[(i >> 8) & 0xF]; 84 line[6] = HexChars[(i >> 4) & 0xF]; 85 line[7] = HexChars[(i >> 0) & 0xF]; 86 87 int hexColumn = firstHexColumn; 88 int charColumn = firstCharColumn; 89 90 for (int j = 0; j < bytesPerLine; j++) 91 { 92 if (j > 0 && (j & 7) == 0) hexColumn++; 93 if (i + j >= bytesLength) 94 { 95 line[hexColumn] = ' '; 96 line[hexColumn + 1] = ' '; 97 line[charColumn] = ' '; 98 } 99 else 100 { 101 byte b = bytes[i + j]; 102 line[hexColumn] = HexChars[(b >> 4) & 0xF]; 103 line[hexColumn + 1] = HexChars[b & 0xF]; 104 line[charColumn] = (b < 32 ? '·' : (char)b); 105 } 106 hexColumn += 3; 107 charColumn++; 108 } 109 result.Append(line); 110 #if __MonoCS__ 111 result.Append('\n'); 112 #endif 113 } 114 Console.WriteLine(result.ToString()); 115 } 116 117 //------------------------------------------------------------------------------ 118 // HexDump, a very nice function, it's not mine. 119 // I found it on the net somewhere some time ago... thanks to the author ;-) 120 //------------------------------------------------------------------------------ EventCallback(IntPtr usrPtr, ref S7Server.USrvEvent Event, int Size)121 static void EventCallback(IntPtr usrPtr, ref S7Server.USrvEvent Event, int Size) 122 { 123 Console.WriteLine(Server.EventText(ref Event)); 124 } 125 SrvRWAreaCallback(IntPtr usrPtr, int Sender, int Operation, ref S7Consts.S7Tag Tag, ref S7Server.RWBuffer Buffer)126 static int SrvRWAreaCallback(IntPtr usrPtr, int Sender, int Operation, ref S7Consts.S7Tag Tag, ref S7Server.RWBuffer Buffer) 127 { 128 129 if (Operation == S7Server.OperationRead) 130 Console.WriteLine("Read Request"); 131 else 132 Console.WriteLine("Write Request"); 133 134 switch (Tag.Area) 135 { 136 case S7Server.S7AreaPE : Console.Write("Area : PE, "); 137 break; 138 case S7Server.S7AreaPA: Console.Write("Area : PA, "); 139 break; 140 case S7Server.S7AreaMK: Console.Write("Area : MK, "); 141 break; 142 case S7Server.S7AreaCT: Console.Write("Area : CT, "); 143 break; 144 case S7Server.S7AreaTM: Console.Write("Area : TM, "); 145 break; 146 case S7Server.S7AreaDB: Console.Write("Area : DB" + System.Convert.ToString(Tag.DBNumber)+" "); 147 break; 148 default: Console.Write("Unknown area "+System.Convert.ToString(Tag.Area)); 149 break; 150 } 151 152 Console.Write("Start : "+ System.Convert.ToString(Tag.Start)+", "); 153 Console.WriteLine("Size : "+ System.Convert.ToString(Tag.Size)); 154 155 if (Operation == S7Server.OperationWrite) 156 HexDump(Buffer.Data, Tag.Size); 157 else 158 { 159 for (int c = 0; c < 1024; c++ ) 160 Buffer.Data[c] = cnt; 161 cnt++; 162 } 163 return 0; 164 } 165 166 Main(string[] args)167 static void Main(string[] args) 168 { 169 Server = new S7Server(); 170 171 // Set the callbacks (using the static var to avoid the garbage collect) 172 TheEventCallBack = new S7Server.TSrvCallback(EventCallback); 173 TheRWAreaCallBack = new S7Server.TSrvRWAreaCallback(SrvRWAreaCallback); 174 175 176 // Filter a bit of noise 177 Server.EventMask = 0x3ff; 178 Server.SetEventsCallBack(TheEventCallBack, IntPtr.Zero); 179 Server.SetRWAreaCallBack(TheRWAreaCallBack, IntPtr.Zero); 180 181 // Uncomment next line if you don't want to see wrapped messages 182 // (Note : Doesn't work in Mono 2.10) 183 184 Console.SetBufferSize(100, Int16.MaxValue - 1); 185 186 // Start the server onto the default adapter. 187 // To select an adapter we have to use Server->StartTo("192.168.x.y"). 188 // Start() is the same of StartTo("0.0.0.0"); 189 int Error = Server.Start(); 190 if (Error == 0) 191 { 192 // Now the server is running ... wait a key to terminate 193 Console.ReadKey(); 194 Server.Stop(); 195 } 196 else 197 Console.WriteLine(Server.ErrorText(Error)); 198 // If you got a start error: 199 // Windows - most likely you ar running the server in a pc on wich is 200 // installed step 7 : open a command prompt and type 201 // "net stop s7oiehsx" (Win32) or 202 // "net stop s7oiehsx64" (Win64) 203 // And after this test : 204 // "net start s7oiehsx" (Win32) or 205 // "net start s7oiehsx64" (Win64) 206 // Unix - you need root rights :-( because the isotcp port (102) is 207 // low and so it's considered "privileged". 208 209 } 210 } 211