Massimo Cristofolini / Settimino
Committer:
il_mix
Date:
Thu Nov 17 08:29:05 2016 +0000
Revision:
1:2f8bf824ec67
Parent:
0:90ad5ee1ff15
Child:
2:f9537de477ee
Reset default connection type to original Settimino default.; Updated copyright notice in .cpp file.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
il_mix 0:90ad5ee1ff15 1 /*=============================================================================|
il_mix 1:2f8bf824ec67 2 | PROJECT SETTIMINO 4 MBED 0.1.0 |
il_mix 0:90ad5ee1ff15 3 |==============================================================================|
il_mix 0:90ad5ee1ff15 4 | Copyright (C) 2013, Davide Nardella |
il_mix 1:2f8bf824ec67 5 | MBED porting by Massimo Cristofolini |
il_mix 0:90ad5ee1ff15 6 | All rights reserved. |
il_mix 0:90ad5ee1ff15 7 |==============================================================================|
il_mix 0:90ad5ee1ff15 8 | SETTIMINO is free software: you can redistribute it and/or modify |
il_mix 0:90ad5ee1ff15 9 | it under the terms of the Lesser GNU General Public License as published by |
il_mix 0:90ad5ee1ff15 10 | the Free Software Foundation, either version 3 of the License, or |
il_mix 0:90ad5ee1ff15 11 | (at your option) any later version. |
il_mix 0:90ad5ee1ff15 12 | |
il_mix 0:90ad5ee1ff15 13 | It means that you can distribute your commercial software linked with |
il_mix 0:90ad5ee1ff15 14 | SETTIMINO without the requirement to distribute the source code of your |
il_mix 0:90ad5ee1ff15 15 | application and without the requirement that your application be itself |
il_mix 0:90ad5ee1ff15 16 | distributed under LGPL. |
il_mix 0:90ad5ee1ff15 17 | |
il_mix 0:90ad5ee1ff15 18 | SETTIMINO is distributed in the hope that it will be useful, |
il_mix 0:90ad5ee1ff15 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
il_mix 0:90ad5ee1ff15 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
il_mix 0:90ad5ee1ff15 21 | Lesser GNU General Public License for more details. |
il_mix 0:90ad5ee1ff15 22 | |
il_mix 0:90ad5ee1ff15 23 | You should have received a copy of the GNU General Public License and a |
il_mix 0:90ad5ee1ff15 24 | copy of Lesser GNU General Public License along with Snap7. |
il_mix 0:90ad5ee1ff15 25 | If not, see http://www.gnu.org/licenses/ |
il_mix 0:90ad5ee1ff15 26 |=============================================================================*/
il_mix 0:90ad5ee1ff15 27 #include "Settimino.h"
il_mix 0:90ad5ee1ff15 28
il_mix 0:90ad5ee1ff15 29 // For further informations about structures (the byte arrays and they meanins)
il_mix 0:90ad5ee1ff15 30 // see http://snap7.sourceforge.net project.
il_mix 0:90ad5ee1ff15 31
il_mix 0:90ad5ee1ff15 32 /*
il_mix 0:90ad5ee1ff15 33 Arduino has not a multithread environment and all Client functions are
il_mix 0:90ad5ee1ff15 34 fully synchronous, so to save memory we can define telegrams and I/O
il_mix 0:90ad5ee1ff15 35 data areas as globals, since only one client at time will use them.
il_mix 0:90ad5ee1ff15 36 */
il_mix 0:90ad5ee1ff15 37
il_mix 0:90ad5ee1ff15 38 // ISO Connection Request telegram (contains also ISO Header and COTP Header)
il_mix 0:90ad5ee1ff15 39 byte ISO_CR[] = {
il_mix 0:90ad5ee1ff15 40 // TPKT (RFC1006 Header)
il_mix 0:90ad5ee1ff15 41 0x03, // RFC 1006 ID (3)
il_mix 0:90ad5ee1ff15 42 0x00, // Reserved, always 0
il_mix 0:90ad5ee1ff15 43 0x00, // High part of packet lenght (entire frame, payload and TPDU included)
il_mix 0:90ad5ee1ff15 44 0x16, // Low part of packet lenght (entire frame, payload and TPDU included)
il_mix 0:90ad5ee1ff15 45 // COTP (ISO 8073 Header)
il_mix 0:90ad5ee1ff15 46 0x11, // PDU Size Length
il_mix 0:90ad5ee1ff15 47 0xE0, // CR - Connection Request ID
il_mix 0:90ad5ee1ff15 48 0x00, // Dst Reference HI
il_mix 0:90ad5ee1ff15 49 0x00, // Dst Reference LO
il_mix 0:90ad5ee1ff15 50 0x00, // Src Reference HI
il_mix 0:90ad5ee1ff15 51 0x01, // Src Reference LO
il_mix 0:90ad5ee1ff15 52 0x00, // Class + Options Flags
il_mix 0:90ad5ee1ff15 53 0xC0, // PDU Max Length ID
il_mix 0:90ad5ee1ff15 54 0x01, // PDU Max Length HI
il_mix 0:90ad5ee1ff15 55 0x0A, // PDU Max Length LO
il_mix 0:90ad5ee1ff15 56 0xC1, // Src TSAP Identifier
il_mix 0:90ad5ee1ff15 57 0x02, // Src TSAP Length (2 bytes)
il_mix 0:90ad5ee1ff15 58 0x01, // Src TSAP HI (will be overwritten by ISOConnect())
il_mix 0:90ad5ee1ff15 59 0x00, // Src TSAP LO (will be overwritten by ISOConnect())
il_mix 0:90ad5ee1ff15 60 0xC2, // Dst TSAP Identifier
il_mix 0:90ad5ee1ff15 61 0x02, // Dst TSAP Length (2 bytes)
il_mix 0:90ad5ee1ff15 62 0x01, // Dst TSAP HI (will be overwritten by ISOConnect())
il_mix 0:90ad5ee1ff15 63 0x02 // Dst TSAP LO (will be overwritten by ISOConnect())
il_mix 0:90ad5ee1ff15 64 };
il_mix 0:90ad5ee1ff15 65
il_mix 0:90ad5ee1ff15 66 // S7 PDU Negotiation Telegram (contains also ISO Header and COTP Header)
il_mix 0:90ad5ee1ff15 67 byte S7_PN[] = {
il_mix 0:90ad5ee1ff15 68 0x03, 0x00, 0x00, 0x19, 0x02, 0xf0, 0x80, // TPKT + COTP (see above for info)
il_mix 0:90ad5ee1ff15 69 0x32, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, 0x00,
il_mix 0:90ad5ee1ff15 70 0x00, 0xf0, 0x00, 0x00, 0x01, 0x00, 0x01,
il_mix 0:90ad5ee1ff15 71 0x00, 0xf0 // PDU Length Requested = HI-LO 240 bytes
il_mix 0:90ad5ee1ff15 72 };
il_mix 0:90ad5ee1ff15 73
il_mix 0:90ad5ee1ff15 74 // S7 Read/Write Request Header (contains also ISO Header and COTP Header)
il_mix 0:90ad5ee1ff15 75 byte S7_RW[] = { // 31-35 bytes
il_mix 0:90ad5ee1ff15 76 0x03, 0x00,
il_mix 0:90ad5ee1ff15 77 0x00, 0x1f, // Telegram Length (Data Size + 31 or 35)
il_mix 0:90ad5ee1ff15 78 0x02, 0xf0, 0x80, // COTP (see above for info)
il_mix 0:90ad5ee1ff15 79 0x32, // S7 Protocol ID
il_mix 0:90ad5ee1ff15 80 0x01, // Job Type
il_mix 0:90ad5ee1ff15 81 0x00, 0x00, // Redundancy identification
il_mix 0:90ad5ee1ff15 82 0x05, 0x00, // PDU Reference
il_mix 0:90ad5ee1ff15 83 0x00, 0x0e, // Parameters Length
il_mix 0:90ad5ee1ff15 84 0x00, 0x00, // Data Length = Size(bytes) + 4
il_mix 0:90ad5ee1ff15 85 0x04, // Function 4 Read Var, 5 Write Var
il_mix 0:90ad5ee1ff15 86 0x01, // Items count
il_mix 0:90ad5ee1ff15 87 0x12, // Var spec.
il_mix 0:90ad5ee1ff15 88 0x0a, // Length of remaining bytes
il_mix 0:90ad5ee1ff15 89 0x10, // Syntax ID
il_mix 0:90ad5ee1ff15 90 S7WLByte, // Transport Size
il_mix 0:90ad5ee1ff15 91 0x00,0x00, // Num Elements
il_mix 0:90ad5ee1ff15 92 0x00,0x00, // DB Number (if any, else 0)
il_mix 0:90ad5ee1ff15 93 0x84, // Area Type
il_mix 0:90ad5ee1ff15 94 0x00, 0x00, 0x00, // Area Offset
il_mix 0:90ad5ee1ff15 95 // WR area
il_mix 0:90ad5ee1ff15 96 0x00, // Reserved
il_mix 0:90ad5ee1ff15 97 0x04, // Transport size
il_mix 0:90ad5ee1ff15 98 0x00, 0x00, // Data Length * 8 (if not timer or counter)
il_mix 0:90ad5ee1ff15 99 };
il_mix 0:90ad5ee1ff15 100
il_mix 0:90ad5ee1ff15 101 #ifdef _EXTENDED
il_mix 0:90ad5ee1ff15 102
il_mix 0:90ad5ee1ff15 103 // S7 Get Block Info Request Header (contains also ISO Header and COTP Header)
il_mix 0:90ad5ee1ff15 104 byte S7_BI[] = {
il_mix 0:90ad5ee1ff15 105 0x03, 0x00, 0x00, 0x25, 0x02, 0xf0, 0x80, 0x32,
il_mix 0:90ad5ee1ff15 106 0x07, 0x00, 0x00, 0x05, 0x00, 0x00, 0x08, 0x00,
il_mix 0:90ad5ee1ff15 107 0x0c, 0x00, 0x01, 0x12, 0x04, 0x11, 0x43, 0x03,
il_mix 0:90ad5ee1ff15 108 0x00, 0xff, 0x09, 0x00, 0x08, 0x30, 0x41,
il_mix 0:90ad5ee1ff15 109 0x30, 0x30, 0x30, 0x30, 0x30, // ASCII DB Number
il_mix 0:90ad5ee1ff15 110 0x41
il_mix 0:90ad5ee1ff15 111 };
il_mix 0:90ad5ee1ff15 112
il_mix 0:90ad5ee1ff15 113 // S7 Put PLC in STOP state Request Header (contains also ISO Header and COTP Header)
il_mix 0:90ad5ee1ff15 114 byte S7_STOP[] = {
il_mix 0:90ad5ee1ff15 115 0x03, 0x00, 0x00, 0x21, 0x02, 0xf0, 0x80, 0x32,
il_mix 0:90ad5ee1ff15 116 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x10, 0x00,
il_mix 0:90ad5ee1ff15 117 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
il_mix 0:90ad5ee1ff15 118 0x50, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x41,
il_mix 0:90ad5ee1ff15 119 0x4d
il_mix 0:90ad5ee1ff15 120 };
il_mix 0:90ad5ee1ff15 121
il_mix 0:90ad5ee1ff15 122 // S7 Put PLC in RUN state Request Header (contains also ISO Header and COTP Header)
il_mix 0:90ad5ee1ff15 123 byte S7_START[] = {
il_mix 0:90ad5ee1ff15 124 0x03, 0x00, 0x00, 0x25, 0x02, 0xf0, 0x80, 0x32,
il_mix 0:90ad5ee1ff15 125 0x01, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x14, 0x00,
il_mix 0:90ad5ee1ff15 126 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
il_mix 0:90ad5ee1ff15 127 0xfd, 0x00, 0x00, 0x09, 0x50, 0x5f, 0x50, 0x52,
il_mix 0:90ad5ee1ff15 128 0x4f, 0x47, 0x52, 0x41, 0x4d
il_mix 0:90ad5ee1ff15 129 };
il_mix 0:90ad5ee1ff15 130
il_mix 0:90ad5ee1ff15 131 // S7 Get PLC Status Request Header (contains also ISO Header and COTP Header)
il_mix 0:90ad5ee1ff15 132 byte S7_PLCGETS[] = {
il_mix 0:90ad5ee1ff15 133 0x03, 0x00, 0x00, 0x21, 0x02, 0xf0, 0x80, 0x32,
il_mix 0:90ad5ee1ff15 134 0x07, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x08, 0x00,
il_mix 0:90ad5ee1ff15 135 0x08, 0x00, 0x01, 0x12, 0x04, 0x11, 0x44, 0x01,
il_mix 0:90ad5ee1ff15 136 0x00, 0xff, 0x09, 0x00, 0x04, 0x04, 0x24, 0x00,
il_mix 0:90ad5ee1ff15 137 0x00
il_mix 0:90ad5ee1ff15 138 };
il_mix 0:90ad5ee1ff15 139
il_mix 0:90ad5ee1ff15 140 #endif // _EXTENDED
il_mix 0:90ad5ee1ff15 141
il_mix 0:90ad5ee1ff15 142 TPDU PDU;
il_mix 0:90ad5ee1ff15 143
il_mix 0:90ad5ee1ff15 144 #ifdef _S7HELPER
il_mix 0:90ad5ee1ff15 145
il_mix 0:90ad5ee1ff15 146 S7Helper S7;
il_mix 0:90ad5ee1ff15 147 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 148 bool S7Helper::BitAt(void *Buffer, int ByteIndex, byte BitIndex)
il_mix 0:90ad5ee1ff15 149 {
il_mix 0:90ad5ee1ff15 150 byte mask[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
il_mix 0:90ad5ee1ff15 151 pbyte Pointer = pbyte(Buffer) + ByteIndex;
il_mix 0:90ad5ee1ff15 152
il_mix 0:90ad5ee1ff15 153 if (BitIndex>7)
il_mix 0:90ad5ee1ff15 154 return false;
il_mix 0:90ad5ee1ff15 155 else
il_mix 0:90ad5ee1ff15 156 return (*Pointer & mask[BitIndex]);
il_mix 0:90ad5ee1ff15 157 }
il_mix 0:90ad5ee1ff15 158 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 159 bool S7Helper::BitAt(int ByteIndex, int BitIndex)
il_mix 0:90ad5ee1ff15 160 {
il_mix 0:90ad5ee1ff15 161 return BitAt(&PDU.DATA[0], ByteIndex, BitIndex);
il_mix 0:90ad5ee1ff15 162 }
il_mix 0:90ad5ee1ff15 163 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 164 byte S7Helper::ByteAt(void *Buffer, int index)
il_mix 0:90ad5ee1ff15 165 {
il_mix 0:90ad5ee1ff15 166 pbyte Pointer = pbyte(Buffer) + index;
il_mix 0:90ad5ee1ff15 167 return *Pointer;
il_mix 0:90ad5ee1ff15 168 }
il_mix 0:90ad5ee1ff15 169 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 170 byte S7Helper::ByteAt(int index)
il_mix 0:90ad5ee1ff15 171 {
il_mix 0:90ad5ee1ff15 172 return ByteAt(&PDU.DATA, index);
il_mix 0:90ad5ee1ff15 173 }
il_mix 0:90ad5ee1ff15 174 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 175 word S7Helper::WordAt(void *Buffer, int index)
il_mix 0:90ad5ee1ff15 176 {
il_mix 0:90ad5ee1ff15 177 word hi=(*(pbyte(Buffer) + index))<<8;
il_mix 0:90ad5ee1ff15 178 return hi+*(pbyte(Buffer) + index+1);
il_mix 0:90ad5ee1ff15 179 }
il_mix 0:90ad5ee1ff15 180 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 181 word S7Helper::WordAt(int index)
il_mix 0:90ad5ee1ff15 182 {
il_mix 0:90ad5ee1ff15 183 return WordAt(&PDU.DATA, index);
il_mix 0:90ad5ee1ff15 184 }
il_mix 0:90ad5ee1ff15 185 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 186 dword S7Helper::DWordAt(void *Buffer, int index)
il_mix 0:90ad5ee1ff15 187 {
il_mix 0:90ad5ee1ff15 188 pbyte pb;
il_mix 0:90ad5ee1ff15 189 dword dw1;
il_mix 0:90ad5ee1ff15 190
il_mix 0:90ad5ee1ff15 191 pb=pbyte(Buffer) + index;
il_mix 0:90ad5ee1ff15 192 dw1=*pb;dw1<<=8;
il_mix 0:90ad5ee1ff15 193 pb=pbyte(Buffer) + index + 1;
il_mix 0:90ad5ee1ff15 194 dw1+=*pb;dw1<<=8;
il_mix 0:90ad5ee1ff15 195 pb=pbyte(Buffer) + index + 2;
il_mix 0:90ad5ee1ff15 196 dw1+=*pb;dw1<<=8;
il_mix 0:90ad5ee1ff15 197 pb=pbyte(Buffer) + index + 3;
il_mix 0:90ad5ee1ff15 198 dw1+=*pb;
il_mix 0:90ad5ee1ff15 199 return dw1;
il_mix 0:90ad5ee1ff15 200 }
il_mix 0:90ad5ee1ff15 201 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 202 dword S7Helper::DWordAt(int index)
il_mix 0:90ad5ee1ff15 203 {
il_mix 0:90ad5ee1ff15 204 return DWordAt(&PDU.DATA, index);
il_mix 0:90ad5ee1ff15 205 }
il_mix 0:90ad5ee1ff15 206 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 207 float S7Helper::FloatAt(void *Buffer, int index)
il_mix 0:90ad5ee1ff15 208 {
il_mix 0:90ad5ee1ff15 209 dword dw = DWordAt(Buffer, index);
il_mix 0:90ad5ee1ff15 210 return *(pfloat(&dw));
il_mix 0:90ad5ee1ff15 211 }
il_mix 0:90ad5ee1ff15 212 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 213 float S7Helper::FloatAt(int index)
il_mix 0:90ad5ee1ff15 214 {
il_mix 0:90ad5ee1ff15 215 return FloatAt(&PDU.DATA, index);
il_mix 0:90ad5ee1ff15 216 }
il_mix 0:90ad5ee1ff15 217 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 218 integer S7Helper::IntegerAt(void *Buffer, int index)
il_mix 0:90ad5ee1ff15 219 {
il_mix 0:90ad5ee1ff15 220 word w = WordAt(Buffer, index);
il_mix 0:90ad5ee1ff15 221 return *(pinteger(&w));
il_mix 0:90ad5ee1ff15 222 }
il_mix 0:90ad5ee1ff15 223 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 224 integer S7Helper::IntegerAt(int index)
il_mix 0:90ad5ee1ff15 225 {
il_mix 0:90ad5ee1ff15 226 return IntegerAt(&PDU.DATA, index);
il_mix 0:90ad5ee1ff15 227 }
il_mix 0:90ad5ee1ff15 228 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 229 long S7Helper::DintAt(void *Buffer, int index)
il_mix 0:90ad5ee1ff15 230 {
il_mix 0:90ad5ee1ff15 231 dword dw = DWordAt(Buffer, index);
il_mix 0:90ad5ee1ff15 232 return *(pdint(&dw));
il_mix 0:90ad5ee1ff15 233 }
il_mix 0:90ad5ee1ff15 234 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 235 long S7Helper::DintAt(int index)
il_mix 0:90ad5ee1ff15 236 {
il_mix 0:90ad5ee1ff15 237 return DintAt(&PDU.DATA, index);
il_mix 0:90ad5ee1ff15 238 }
il_mix 0:90ad5ee1ff15 239 #endif // _S7HELPER
il_mix 0:90ad5ee1ff15 240 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 241 S7Client::S7Client()
il_mix 0:90ad5ee1ff15 242 {
il_mix 1:2f8bf824ec67 243 // Default TSAP values for connectiong as PG to a S7300 (Rack 0, Slot 2)
il_mix 0:90ad5ee1ff15 244 LocalTSAP_HI = 0x01;
il_mix 0:90ad5ee1ff15 245 LocalTSAP_LO = 0x00;
il_mix 0:90ad5ee1ff15 246 RemoteTSAP_HI= 0x01;
il_mix 0:90ad5ee1ff15 247 RemoteTSAP_LO= 0x02;
il_mix 1:2f8bf824ec67 248 ConnType = PG;
il_mix 0:90ad5ee1ff15 249 Connected = false;
il_mix 0:90ad5ee1ff15 250 LastError = 0;
il_mix 0:90ad5ee1ff15 251 PDULength = 0;
il_mix 0:90ad5ee1ff15 252 RecvTimeout = 500; // 500 ms
il_mix 0:90ad5ee1ff15 253 }
il_mix 0:90ad5ee1ff15 254 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 255 S7Client::~S7Client()
il_mix 0:90ad5ee1ff15 256 {
il_mix 0:90ad5ee1ff15 257 Disconnect();
il_mix 0:90ad5ee1ff15 258 }
il_mix 0:90ad5ee1ff15 259 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 260 int S7Client::SetLastError(int Error)
il_mix 0:90ad5ee1ff15 261 {
il_mix 0:90ad5ee1ff15 262 LastError=Error;
il_mix 0:90ad5ee1ff15 263 return Error;
il_mix 0:90ad5ee1ff15 264 }
il_mix 0:90ad5ee1ff15 265 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 266 void S7Client::FlushSocket()
il_mix 0:90ad5ee1ff15 267 {
il_mix 0:90ad5ee1ff15 268 char buffer[32];
il_mix 0:90ad5ee1ff15 269 while(TCPClient.receive_all(buffer, sizeof(buffer)) > 0)
il_mix 0:90ad5ee1ff15 270 {}
il_mix 0:90ad5ee1ff15 271 }
il_mix 0:90ad5ee1ff15 272 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 273 int S7Client::IsoPduSize()
il_mix 0:90ad5ee1ff15 274 {
il_mix 0:90ad5ee1ff15 275 uint16_t Size = PDU.H[2];
il_mix 0:90ad5ee1ff15 276 return (Size<<8) + PDU.H[3];
il_mix 0:90ad5ee1ff15 277 }
il_mix 0:90ad5ee1ff15 278 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 279 int S7Client::RecvPacket(char *buf, uint16_t Size)
il_mix 0:90ad5ee1ff15 280 {
il_mix 0:90ad5ee1ff15 281 TCPClient.set_blocking(true, RecvTimeout);
il_mix 0:90ad5ee1ff15 282 int ret = TCPClient.receive(buf, Size);
il_mix 0:90ad5ee1ff15 283 TCPClient.set_blocking(false);
il_mix 0:90ad5ee1ff15 284 if(ret == 0)
il_mix 0:90ad5ee1ff15 285 return SetLastError(errTCPConnectionReset);
il_mix 0:90ad5ee1ff15 286 return SetLastError(0);
il_mix 0:90ad5ee1ff15 287 }
il_mix 0:90ad5ee1ff15 288 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 289 void S7Client::SetConnectionParams(const char* Address, uint16_t LocalTSAP, uint16_t RemoteTSAP)
il_mix 0:90ad5ee1ff15 290 {
il_mix 0:90ad5ee1ff15 291 sprintf(Peer, "%s", Address);
il_mix 0:90ad5ee1ff15 292 LocalTSAP_HI = LocalTSAP>>8;
il_mix 0:90ad5ee1ff15 293 LocalTSAP_LO = LocalTSAP & 0x00FF;
il_mix 0:90ad5ee1ff15 294 RemoteTSAP_HI = RemoteTSAP>>8;
il_mix 0:90ad5ee1ff15 295 RemoteTSAP_LO = RemoteTSAP & 0x00FF;
il_mix 0:90ad5ee1ff15 296 }
il_mix 0:90ad5ee1ff15 297 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 298 void S7Client::SetConnectionType(uint16_t ConnectionType)
il_mix 0:90ad5ee1ff15 299 {
il_mix 0:90ad5ee1ff15 300 ConnType = ConnectionType;
il_mix 0:90ad5ee1ff15 301 }
il_mix 0:90ad5ee1ff15 302 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 303 int S7Client::ConnectTo(const char* Address, uint16_t Rack, uint16_t Slot)
il_mix 0:90ad5ee1ff15 304 {
il_mix 0:90ad5ee1ff15 305 SetConnectionParams(Address, 0x0100, (ConnType<<8)+(Rack * 0x20) + Slot);
il_mix 0:90ad5ee1ff15 306 return Connect();
il_mix 0:90ad5ee1ff15 307 }
il_mix 0:90ad5ee1ff15 308 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 309 int S7Client::Connect()
il_mix 0:90ad5ee1ff15 310 {
il_mix 0:90ad5ee1ff15 311 LastError = 0;
il_mix 0:90ad5ee1ff15 312 if (!Connected)
il_mix 0:90ad5ee1ff15 313 {
il_mix 0:90ad5ee1ff15 314 TCPConnect();
il_mix 0:90ad5ee1ff15 315 if (LastError==0) // First stage : TCP Connection
il_mix 0:90ad5ee1ff15 316 {
il_mix 0:90ad5ee1ff15 317 ISOConnect();
il_mix 0:90ad5ee1ff15 318 if (LastError==0) // Second stage : ISOTCP (ISO 8073) Connection
il_mix 0:90ad5ee1ff15 319 {
il_mix 0:90ad5ee1ff15 320 LastError=NegotiatePduLength(); // Third stage : S7 PDU negotiation
il_mix 0:90ad5ee1ff15 321 }
il_mix 0:90ad5ee1ff15 322 }
il_mix 0:90ad5ee1ff15 323 }
il_mix 0:90ad5ee1ff15 324 Connected=LastError==0;
il_mix 0:90ad5ee1ff15 325 return LastError;
il_mix 0:90ad5ee1ff15 326 }
il_mix 0:90ad5ee1ff15 327 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 328 void S7Client::Disconnect()
il_mix 0:90ad5ee1ff15 329 {
il_mix 0:90ad5ee1ff15 330 if (Connected)
il_mix 0:90ad5ee1ff15 331 {
il_mix 0:90ad5ee1ff15 332 TCPClient.close();
il_mix 0:90ad5ee1ff15 333 Connected = false;
il_mix 0:90ad5ee1ff15 334 PDULength = 0;
il_mix 0:90ad5ee1ff15 335 LastError = 0;
il_mix 0:90ad5ee1ff15 336 }
il_mix 0:90ad5ee1ff15 337 }
il_mix 0:90ad5ee1ff15 338 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 339 int S7Client::TCPConnect()
il_mix 0:90ad5ee1ff15 340 {
il_mix 0:90ad5ee1ff15 341 if (TCPClient.connect(Peer, isotcp))
il_mix 0:90ad5ee1ff15 342 return SetLastError(0);
il_mix 0:90ad5ee1ff15 343 else
il_mix 0:90ad5ee1ff15 344 return SetLastError(errTCPConnectionFailed);
il_mix 0:90ad5ee1ff15 345 }
il_mix 0:90ad5ee1ff15 346 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 347 int S7Client::RecvISOPacket(uint16_t *Size)
il_mix 0:90ad5ee1ff15 348 {
il_mix 0:90ad5ee1ff15 349 bool Done = false;
il_mix 0:90ad5ee1ff15 350 pbyte Target = pbyte(&PDU.H[0])+Shift;
il_mix 0:90ad5ee1ff15 351 LastError=0;
il_mix 0:90ad5ee1ff15 352
il_mix 0:90ad5ee1ff15 353 while ((LastError==0) && !Done)
il_mix 0:90ad5ee1ff15 354 {
il_mix 0:90ad5ee1ff15 355 // Get TPKT (4 bytes)
il_mix 0:90ad5ee1ff15 356 RecvPacket(PDU.H, 4);
il_mix 0:90ad5ee1ff15 357 if (LastError==0)
il_mix 0:90ad5ee1ff15 358 {
il_mix 0:90ad5ee1ff15 359 *Size = IsoPduSize();
il_mix 0:90ad5ee1ff15 360 // Check 0 bytes Data Packet (only TPKT+COTP - 7 bytes)
il_mix 0:90ad5ee1ff15 361 if (*Size==7)
il_mix 0:90ad5ee1ff15 362 RecvPacket(PDU.H, 3); // Skip remaining 3 bytes and Done is still false
il_mix 0:90ad5ee1ff15 363 else
il_mix 0:90ad5ee1ff15 364 {
il_mix 0:90ad5ee1ff15 365 if ((*Size>MaxPduSize) || (*Size<MinPduSize))
il_mix 0:90ad5ee1ff15 366 LastError=errISOInvalidPDU;
il_mix 0:90ad5ee1ff15 367 else
il_mix 0:90ad5ee1ff15 368 Done = true; // a valid Length !=7 && >16 && <247
il_mix 0:90ad5ee1ff15 369 }
il_mix 0:90ad5ee1ff15 370 }
il_mix 0:90ad5ee1ff15 371 }
il_mix 0:90ad5ee1ff15 372 if (LastError==0)
il_mix 0:90ad5ee1ff15 373 {
il_mix 0:90ad5ee1ff15 374 RecvPacket(PDU.H, 3); // Skip remaining 3 COTP bytes
il_mix 0:90ad5ee1ff15 375 LastPDUType=PDU.H[1]; // Stores PDU Type, we need it
il_mix 0:90ad5ee1ff15 376 *Size-=ISOSize;
il_mix 0:90ad5ee1ff15 377 // We need to align with PDU.DATA
il_mix 0:90ad5ee1ff15 378 RecvPacket(Target, *Size);
il_mix 0:90ad5ee1ff15 379 }
il_mix 0:90ad5ee1ff15 380 if (LastError!=0)
il_mix 0:90ad5ee1ff15 381 FlushSocket();
il_mix 0:90ad5ee1ff15 382 return LastError;
il_mix 0:90ad5ee1ff15 383 }
il_mix 0:90ad5ee1ff15 384 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 385 int S7Client::ISOConnect()
il_mix 0:90ad5ee1ff15 386 {
il_mix 0:90ad5ee1ff15 387 uint16_t Length;
il_mix 0:90ad5ee1ff15 388 // Setup TSAPs
il_mix 0:90ad5ee1ff15 389 ISO_CR[16]=LocalTSAP_HI;
il_mix 0:90ad5ee1ff15 390 ISO_CR[17]=LocalTSAP_LO;
il_mix 0:90ad5ee1ff15 391 ISO_CR[20]=RemoteTSAP_HI;
il_mix 0:90ad5ee1ff15 392 ISO_CR[21]=RemoteTSAP_LO;
il_mix 0:90ad5ee1ff15 393
il_mix 0:90ad5ee1ff15 394 if (TCPClient.send(ISO_CR, sizeof(ISO_CR))==sizeof(ISO_CR))
il_mix 0:90ad5ee1ff15 395 {
il_mix 0:90ad5ee1ff15 396 RecvISOPacket(&Length);
il_mix 0:90ad5ee1ff15 397 if ((LastError==0) && (Length==15)) // 15 = 22 (sizeof CC telegram) - 7 (sizeof Header)
il_mix 0:90ad5ee1ff15 398 {
il_mix 0:90ad5ee1ff15 399 if (LastPDUType==CC) // Connection confirm
il_mix 0:90ad5ee1ff15 400 return 0;
il_mix 0:90ad5ee1ff15 401 else
il_mix 0:90ad5ee1ff15 402 return SetLastError(errISOInvalidPDU);
il_mix 0:90ad5ee1ff15 403 }
il_mix 0:90ad5ee1ff15 404 else
il_mix 0:90ad5ee1ff15 405 return LastError;
il_mix 0:90ad5ee1ff15 406 }
il_mix 0:90ad5ee1ff15 407 else
il_mix 0:90ad5ee1ff15 408 return SetLastError(errISOConnectionFailed);
il_mix 0:90ad5ee1ff15 409 }
il_mix 0:90ad5ee1ff15 410 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 411 int S7Client::NegotiatePduLength()
il_mix 0:90ad5ee1ff15 412 {
il_mix 0:90ad5ee1ff15 413 uint16_t Length;
il_mix 0:90ad5ee1ff15 414 if (TCPClient.send(S7_PN, sizeof(S7_PN))==sizeof(S7_PN))
il_mix 0:90ad5ee1ff15 415 {
il_mix 0:90ad5ee1ff15 416 RecvISOPacket(&Length);
il_mix 0:90ad5ee1ff15 417 if (LastError==0)
il_mix 0:90ad5ee1ff15 418 {
il_mix 0:90ad5ee1ff15 419 // check S7 Error
il_mix 0:90ad5ee1ff15 420 if ((Length==20) && (PDU.H[27]==0) && (PDU.H[28]==0)) // 20 = size of Negotiate Answer
il_mix 0:90ad5ee1ff15 421 {
il_mix 0:90ad5ee1ff15 422 PDULength = PDU.H[35];
il_mix 0:90ad5ee1ff15 423 PDULength = (PDULength<<8) + PDU.H[36]; // Value negotiated
il_mix 0:90ad5ee1ff15 424 if (PDULength>0)
il_mix 0:90ad5ee1ff15 425 return 0;
il_mix 0:90ad5ee1ff15 426 else
il_mix 0:90ad5ee1ff15 427 return SetLastError(errISONegotiatingPDU);
il_mix 0:90ad5ee1ff15 428 }
il_mix 0:90ad5ee1ff15 429 else
il_mix 0:90ad5ee1ff15 430 return SetLastError(errISONegotiatingPDU);
il_mix 0:90ad5ee1ff15 431 }
il_mix 0:90ad5ee1ff15 432 else
il_mix 0:90ad5ee1ff15 433 return LastError;
il_mix 0:90ad5ee1ff15 434 }
il_mix 0:90ad5ee1ff15 435 else
il_mix 0:90ad5ee1ff15 436 return SetLastError(errISONegotiatingPDU);
il_mix 0:90ad5ee1ff15 437 }
il_mix 0:90ad5ee1ff15 438 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 439 int S7Client::ReadArea(int Area, uint16_t DBNumber, uint16_t Start, uint16_t Amount, void *ptrData)
il_mix 0:90ad5ee1ff15 440 {
il_mix 0:90ad5ee1ff15 441 unsigned long Address;
il_mix 0:90ad5ee1ff15 442 uint16_t NumElements;
il_mix 0:90ad5ee1ff15 443 uint16_t MaxElements;
il_mix 0:90ad5ee1ff15 444 uint16_t TotElements;
il_mix 0:90ad5ee1ff15 445 uint16_t SizeRequested;
il_mix 0:90ad5ee1ff15 446 uint16_t Length;
il_mix 0:90ad5ee1ff15 447
il_mix 0:90ad5ee1ff15 448 pbyte Target;
il_mix 0:90ad5ee1ff15 449 uintptr_t Offset = 0;
il_mix 0:90ad5ee1ff15 450 int WordSize = 1;
il_mix 0:90ad5ee1ff15 451
il_mix 0:90ad5ee1ff15 452 LastError=0;
il_mix 0:90ad5ee1ff15 453
il_mix 0:90ad5ee1ff15 454 // If we are addressing Timers or counters the element size is 2
il_mix 0:90ad5ee1ff15 455 if ((Area==S7AreaCT) || (Area==S7AreaTM))
il_mix 0:90ad5ee1ff15 456 WordSize = 2;
il_mix 0:90ad5ee1ff15 457
il_mix 0:90ad5ee1ff15 458 MaxElements=(PDULength-18) / WordSize; // 18 = Reply telegram header
il_mix 0:90ad5ee1ff15 459 TotElements=Amount;
il_mix 0:90ad5ee1ff15 460 // If we use the internal buffer only, we cannot exced the PDU limit
il_mix 0:90ad5ee1ff15 461 if (ptrData==NULL)
il_mix 0:90ad5ee1ff15 462 {
il_mix 0:90ad5ee1ff15 463 if (TotElements>MaxElements)
il_mix 0:90ad5ee1ff15 464 TotElements=MaxElements;
il_mix 0:90ad5ee1ff15 465 }
il_mix 0:90ad5ee1ff15 466
il_mix 0:90ad5ee1ff15 467 while ((TotElements>0) && (LastError==0))
il_mix 0:90ad5ee1ff15 468 {
il_mix 0:90ad5ee1ff15 469 NumElements=TotElements;
il_mix 0:90ad5ee1ff15 470 if (NumElements>MaxElements)
il_mix 0:90ad5ee1ff15 471 NumElements=MaxElements;
il_mix 0:90ad5ee1ff15 472
il_mix 0:90ad5ee1ff15 473 SizeRequested =NumElements * WordSize;
il_mix 0:90ad5ee1ff15 474
il_mix 0:90ad5ee1ff15 475 Target=pbyte(ptrData)+Offset;
il_mix 0:90ad5ee1ff15 476
il_mix 0:90ad5ee1ff15 477 // Setup the telegram
il_mix 0:90ad5ee1ff15 478 memcpy(&PDU.H, S7_RW, Size_RD);
il_mix 0:90ad5ee1ff15 479
il_mix 0:90ad5ee1ff15 480 // Set DB Number
il_mix 0:90ad5ee1ff15 481 PDU.H[27] = Area;
il_mix 0:90ad5ee1ff15 482 if (Area==S7AreaDB)
il_mix 0:90ad5ee1ff15 483 {
il_mix 0:90ad5ee1ff15 484 PDU.H[25] = DBNumber>>8;
il_mix 0:90ad5ee1ff15 485 PDU.H[26] = DBNumber & 0x00FF;
il_mix 0:90ad5ee1ff15 486 }
il_mix 0:90ad5ee1ff15 487
il_mix 0:90ad5ee1ff15 488 // Adjusts Start and word length
il_mix 0:90ad5ee1ff15 489 if ((Area==S7AreaCT) || (Area==S7AreaTM))
il_mix 0:90ad5ee1ff15 490 {
il_mix 0:90ad5ee1ff15 491 Address = Start;
il_mix 0:90ad5ee1ff15 492 if (Area==S7AreaCT)
il_mix 0:90ad5ee1ff15 493 PDU.H[22]=S7WLCounter;
il_mix 0:90ad5ee1ff15 494 else
il_mix 0:90ad5ee1ff15 495 PDU.H[22]=S7WLTimer;
il_mix 0:90ad5ee1ff15 496 }
il_mix 0:90ad5ee1ff15 497 else
il_mix 0:90ad5ee1ff15 498 Address = Start<<3;
il_mix 0:90ad5ee1ff15 499
il_mix 0:90ad5ee1ff15 500 // Num elements
il_mix 0:90ad5ee1ff15 501 PDU.H[23]=NumElements<<8;
il_mix 0:90ad5ee1ff15 502 PDU.H[24]=NumElements;
il_mix 0:90ad5ee1ff15 503
il_mix 0:90ad5ee1ff15 504 // Address into the PLC
il_mix 0:90ad5ee1ff15 505 PDU.H[30] = Address & 0x000000FF;
il_mix 0:90ad5ee1ff15 506 Address = Address >> 8;
il_mix 0:90ad5ee1ff15 507 PDU.H[29] = Address & 0x000000FF;
il_mix 0:90ad5ee1ff15 508 Address = Address >> 8;
il_mix 0:90ad5ee1ff15 509 PDU.H[28] = Address & 0x000000FF;
il_mix 0:90ad5ee1ff15 510
il_mix 0:90ad5ee1ff15 511 if (TCPClient.send(PDU.H, Size_RD)==Size_RD)
il_mix 0:90ad5ee1ff15 512 {
il_mix 0:90ad5ee1ff15 513 RecvISOPacket(&Length);
il_mix 0:90ad5ee1ff15 514 if (LastError==0)
il_mix 0:90ad5ee1ff15 515 {
il_mix 0:90ad5ee1ff15 516 if (Length>=18)
il_mix 0:90ad5ee1ff15 517 {
il_mix 0:90ad5ee1ff15 518 if ((Length-18==SizeRequested) && (PDU.H[31]==0xFF))
il_mix 0:90ad5ee1ff15 519 {
il_mix 0:90ad5ee1ff15 520 if (ptrData!=NULL)
il_mix 0:90ad5ee1ff15 521 memcpy(Target, &PDU.DATA[0], SizeRequested); // Copies in the user's buffer
il_mix 0:90ad5ee1ff15 522 Offset+=SizeRequested;
il_mix 0:90ad5ee1ff15 523 }
il_mix 0:90ad5ee1ff15 524 else
il_mix 0:90ad5ee1ff15 525 LastError = errS7DataRead;
il_mix 0:90ad5ee1ff15 526 }
il_mix 0:90ad5ee1ff15 527 else
il_mix 0:90ad5ee1ff15 528 LastError = errS7InvalidPDU;
il_mix 0:90ad5ee1ff15 529 }
il_mix 0:90ad5ee1ff15 530 }
il_mix 0:90ad5ee1ff15 531 else
il_mix 0:90ad5ee1ff15 532 LastError = errTCPDataSend;
il_mix 0:90ad5ee1ff15 533
il_mix 0:90ad5ee1ff15 534 TotElements -= NumElements;
il_mix 0:90ad5ee1ff15 535 Start += NumElements*WordSize;
il_mix 0:90ad5ee1ff15 536 }
il_mix 0:90ad5ee1ff15 537 return LastError;
il_mix 0:90ad5ee1ff15 538 }
il_mix 0:90ad5ee1ff15 539 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 540 int S7Client::WriteArea(int Area, uint16_t DBNumber, uint16_t Start, uint16_t Amount, void *ptrData)
il_mix 0:90ad5ee1ff15 541 {
il_mix 0:90ad5ee1ff15 542 unsigned long Address;
il_mix 0:90ad5ee1ff15 543 uint16_t NumElements;
il_mix 0:90ad5ee1ff15 544 uint16_t MaxElements;
il_mix 0:90ad5ee1ff15 545 uint16_t TotElements;
il_mix 0:90ad5ee1ff15 546 uint16_t DataSize;
il_mix 0:90ad5ee1ff15 547 uint16_t IsoSize;
il_mix 0:90ad5ee1ff15 548 uint16_t Length;
il_mix 0:90ad5ee1ff15 549
il_mix 0:90ad5ee1ff15 550 pbyte Source;
il_mix 0:90ad5ee1ff15 551 uintptr_t Offset = 0;
il_mix 0:90ad5ee1ff15 552 int WordSize = 1;
il_mix 0:90ad5ee1ff15 553
il_mix 0:90ad5ee1ff15 554 LastError=0;
il_mix 0:90ad5ee1ff15 555
il_mix 0:90ad5ee1ff15 556 // If we are addressing Timers or counters the element size is 2
il_mix 0:90ad5ee1ff15 557 if ((Area==S7AreaCT) || (Area==S7AreaTM))
il_mix 0:90ad5ee1ff15 558 WordSize = 2;
il_mix 0:90ad5ee1ff15 559
il_mix 0:90ad5ee1ff15 560 MaxElements=(PDULength-35) / WordSize; // 35 = Write telegram header
il_mix 0:90ad5ee1ff15 561 TotElements=Amount;
il_mix 0:90ad5ee1ff15 562 if (ptrData==NULL)
il_mix 0:90ad5ee1ff15 563 {
il_mix 0:90ad5ee1ff15 564 if (TotElements>MaxElements)
il_mix 0:90ad5ee1ff15 565 TotElements=MaxElements;
il_mix 0:90ad5ee1ff15 566 }
il_mix 0:90ad5ee1ff15 567
il_mix 0:90ad5ee1ff15 568 while ((TotElements>0) && (LastError==0))
il_mix 0:90ad5ee1ff15 569 {
il_mix 0:90ad5ee1ff15 570 NumElements=TotElements;
il_mix 0:90ad5ee1ff15 571 if (NumElements>MaxElements)
il_mix 0:90ad5ee1ff15 572 NumElements=MaxElements;
il_mix 0:90ad5ee1ff15 573 // If we use the internal buffer only, we cannot exced the PDU limit
il_mix 0:90ad5ee1ff15 574 DataSize=NumElements*WordSize;
il_mix 0:90ad5ee1ff15 575 IsoSize=Size_WR+DataSize;
il_mix 0:90ad5ee1ff15 576
il_mix 0:90ad5ee1ff15 577 // Setup the telegram
il_mix 0:90ad5ee1ff15 578 memcpy(&PDU.H, S7_RW, Size_WR);
il_mix 0:90ad5ee1ff15 579 // Whole telegram Size
il_mix 0:90ad5ee1ff15 580 PDU.H[2]=IsoSize>>8;
il_mix 0:90ad5ee1ff15 581 PDU.H[3]=IsoSize & 0x00FF;
il_mix 0:90ad5ee1ff15 582 // Data Length
il_mix 0:90ad5ee1ff15 583 Length=DataSize+4;
il_mix 0:90ad5ee1ff15 584 PDU.H[15]=Length>>8;
il_mix 0:90ad5ee1ff15 585 PDU.H[16]=Length & 0x00FF;
il_mix 0:90ad5ee1ff15 586 // Function
il_mix 0:90ad5ee1ff15 587 PDU.H[17]=0x05;
il_mix 0:90ad5ee1ff15 588 // Set DB Number
il_mix 0:90ad5ee1ff15 589 PDU.H[27] = Area;
il_mix 0:90ad5ee1ff15 590 if (Area==S7AreaDB)
il_mix 0:90ad5ee1ff15 591 {
il_mix 0:90ad5ee1ff15 592 PDU.H[25] = DBNumber>>8;
il_mix 0:90ad5ee1ff15 593 PDU.H[26] = DBNumber & 0x00FF;
il_mix 0:90ad5ee1ff15 594 }
il_mix 0:90ad5ee1ff15 595 // Adjusts Start and word length
il_mix 0:90ad5ee1ff15 596 if ((Area==S7AreaCT) || (Area==S7AreaTM))
il_mix 0:90ad5ee1ff15 597 {
il_mix 0:90ad5ee1ff15 598 Address = Start;
il_mix 0:90ad5ee1ff15 599 Length = DataSize;
il_mix 0:90ad5ee1ff15 600 if (Area==S7AreaCT)
il_mix 0:90ad5ee1ff15 601 PDU.H[22]=S7WLCounter;
il_mix 0:90ad5ee1ff15 602 else
il_mix 0:90ad5ee1ff15 603 PDU.H[22]=S7WLTimer;
il_mix 0:90ad5ee1ff15 604 }
il_mix 0:90ad5ee1ff15 605 else
il_mix 0:90ad5ee1ff15 606 {
il_mix 0:90ad5ee1ff15 607 Address = Start<<3;
il_mix 0:90ad5ee1ff15 608 Length = DataSize<<3;
il_mix 0:90ad5ee1ff15 609 }
il_mix 0:90ad5ee1ff15 610 // Num elements
il_mix 0:90ad5ee1ff15 611 PDU.H[23]=NumElements<<8;
il_mix 0:90ad5ee1ff15 612 PDU.H[24]=NumElements;
il_mix 0:90ad5ee1ff15 613 // Address into the PLC
il_mix 0:90ad5ee1ff15 614 PDU.H[30] = Address & 0x000000FF;
il_mix 0:90ad5ee1ff15 615 Address = Address >> 8;
il_mix 0:90ad5ee1ff15 616 PDU.H[29] = Address & 0x000000FF;
il_mix 0:90ad5ee1ff15 617 Address = Address >> 8;
il_mix 0:90ad5ee1ff15 618 PDU.H[28] = Address & 0x000000FF;
il_mix 0:90ad5ee1ff15 619 // Length
il_mix 0:90ad5ee1ff15 620 PDU.H[33]=Length>>8;
il_mix 0:90ad5ee1ff15 621 PDU.H[34]=Length & 0x00FF;
il_mix 0:90ad5ee1ff15 622 // Copy data
il_mix 0:90ad5ee1ff15 623 Source=pbyte(ptrData)+Offset;
il_mix 0:90ad5ee1ff15 624 if (ptrData!=NULL)
il_mix 0:90ad5ee1ff15 625 memcpy(&PDU.H[35], Source, DataSize);
il_mix 0:90ad5ee1ff15 626
il_mix 0:90ad5ee1ff15 627 if (TCPClient.send(PDU.H, IsoSize)==IsoSize)
il_mix 0:90ad5ee1ff15 628 {
il_mix 0:90ad5ee1ff15 629 RecvISOPacket(&Length);
il_mix 0:90ad5ee1ff15 630 if (LastError==0)
il_mix 0:90ad5ee1ff15 631 {
il_mix 0:90ad5ee1ff15 632 if (Length==15)
il_mix 0:90ad5ee1ff15 633 {
il_mix 0:90ad5ee1ff15 634 if ((PDU.H[27]!=0x00) || (PDU.H[28]!=0x00) || (PDU.H[31]!=0xFF))
il_mix 0:90ad5ee1ff15 635 LastError = errS7DataWrite;
il_mix 0:90ad5ee1ff15 636 }
il_mix 0:90ad5ee1ff15 637 else
il_mix 0:90ad5ee1ff15 638 LastError = errS7InvalidPDU;
il_mix 0:90ad5ee1ff15 639 }
il_mix 0:90ad5ee1ff15 640 }
il_mix 0:90ad5ee1ff15 641 else
il_mix 0:90ad5ee1ff15 642 LastError = errTCPDataSend;
il_mix 0:90ad5ee1ff15 643
il_mix 0:90ad5ee1ff15 644 Offset+=DataSize;
il_mix 0:90ad5ee1ff15 645 TotElements -= NumElements;
il_mix 0:90ad5ee1ff15 646 Start += NumElements*WordSize;
il_mix 0:90ad5ee1ff15 647 }
il_mix 0:90ad5ee1ff15 648 return LastError;
il_mix 0:90ad5ee1ff15 649 }
il_mix 0:90ad5ee1ff15 650 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 651 #ifdef _EXTENDED
il_mix 0:90ad5ee1ff15 652
il_mix 0:90ad5ee1ff15 653 int S7Client::GetDBSize(uint16_t DBNumber, uint16_t *Size)
il_mix 0:90ad5ee1ff15 654 {
il_mix 0:90ad5ee1ff15 655 uint16_t Length;
il_mix 0:90ad5ee1ff15 656 LastError=0;
il_mix 0:90ad5ee1ff15 657 *Size=0;
il_mix 0:90ad5ee1ff15 658 // Setup the telegram
il_mix 0:90ad5ee1ff15 659 memcpy(&PDU.H, S7_BI, sizeof(S7_BI));
il_mix 0:90ad5ee1ff15 660 // Set DB Number
il_mix 0:90ad5ee1ff15 661 PDU.H[31]=(DBNumber / 10000)+0x30;
il_mix 0:90ad5ee1ff15 662 DBNumber=DBNumber % 10000;
il_mix 0:90ad5ee1ff15 663 PDU.H[32]=(DBNumber / 1000)+0x30;
il_mix 0:90ad5ee1ff15 664 DBNumber=DBNumber % 1000;
il_mix 0:90ad5ee1ff15 665 PDU.H[33]=(DBNumber / 100)+0x30;
il_mix 0:90ad5ee1ff15 666 DBNumber=DBNumber % 100;
il_mix 0:90ad5ee1ff15 667 PDU.H[34]=(DBNumber / 10)+0x30;
il_mix 0:90ad5ee1ff15 668 DBNumber=DBNumber % 10;
il_mix 0:90ad5ee1ff15 669 PDU.H[35]=(DBNumber / 1)+0x30;
il_mix 0:90ad5ee1ff15 670 if (TCPClient.send(PDU.H, sizeof(S7_BI))==sizeof(S7_BI))
il_mix 0:90ad5ee1ff15 671 {
il_mix 0:90ad5ee1ff15 672 RecvISOPacket(&Length);
il_mix 0:90ad5ee1ff15 673 if (LastError==0)
il_mix 0:90ad5ee1ff15 674 {
il_mix 0:90ad5ee1ff15 675 if (Length>25) // 26 is the minimum expected
il_mix 0:90ad5ee1ff15 676 {
il_mix 0:90ad5ee1ff15 677 if ((PDU.H[37]==0x00) && (PDU.H[38]==0x00) && (PDU.H[39]==0xFF))
il_mix 0:90ad5ee1ff15 678 {
il_mix 0:90ad5ee1ff15 679 *Size=PDU.H[83];
il_mix 0:90ad5ee1ff15 680 *Size=(*Size<<8)+PDU.H[84];
il_mix 0:90ad5ee1ff15 681 }
il_mix 0:90ad5ee1ff15 682 else
il_mix 0:90ad5ee1ff15 683 LastError = errS7Function;
il_mix 0:90ad5ee1ff15 684 }
il_mix 0:90ad5ee1ff15 685 else
il_mix 0:90ad5ee1ff15 686 LastError = errS7InvalidPDU;
il_mix 0:90ad5ee1ff15 687 }
il_mix 0:90ad5ee1ff15 688 }
il_mix 0:90ad5ee1ff15 689 else
il_mix 0:90ad5ee1ff15 690 LastError = errTCPDataSend;
il_mix 0:90ad5ee1ff15 691
il_mix 0:90ad5ee1ff15 692 return LastError;
il_mix 0:90ad5ee1ff15 693 }
il_mix 0:90ad5ee1ff15 694 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 695 int S7Client::DBGet(uint16_t DBNumber, void *ptrData, uint16_t *Size)
il_mix 0:90ad5ee1ff15 696 {
il_mix 0:90ad5ee1ff15 697 uint16_t Length;
il_mix 0:90ad5ee1ff15 698 int Result;
il_mix 0:90ad5ee1ff15 699
il_mix 0:90ad5ee1ff15 700 Result=GetDBSize(DBNumber, &Length);
il_mix 0:90ad5ee1ff15 701
il_mix 0:90ad5ee1ff15 702 if (Result==0)
il_mix 0:90ad5ee1ff15 703 {
il_mix 0:90ad5ee1ff15 704 if (Length<=*Size) // Check if the buffer supplied is big enough
il_mix 0:90ad5ee1ff15 705 {
il_mix 0:90ad5ee1ff15 706 Result=ReadArea(S7AreaDB, DBNumber, 0, Length, ptrData);
il_mix 0:90ad5ee1ff15 707 if (Result==0)
il_mix 0:90ad5ee1ff15 708 *Size=Length;
il_mix 0:90ad5ee1ff15 709 }
il_mix 0:90ad5ee1ff15 710 else
il_mix 0:90ad5ee1ff15 711 Result=errBufferTooSmall;
il_mix 0:90ad5ee1ff15 712 }
il_mix 0:90ad5ee1ff15 713
il_mix 0:90ad5ee1ff15 714 return Result;
il_mix 0:90ad5ee1ff15 715 }
il_mix 0:90ad5ee1ff15 716 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 717 int S7Client::PlcStop()
il_mix 0:90ad5ee1ff15 718 {
il_mix 0:90ad5ee1ff15 719 uint16_t Length;
il_mix 0:90ad5ee1ff15 720 LastError=0;
il_mix 0:90ad5ee1ff15 721 // Setup the telegram
il_mix 0:90ad5ee1ff15 722 memcpy(&PDU.H, S7_STOP, sizeof(S7_STOP));
il_mix 0:90ad5ee1ff15 723 if (TCPClient.send(PDU.H, sizeof(S7_STOP))==sizeof(S7_STOP))
il_mix 0:90ad5ee1ff15 724 {
il_mix 0:90ad5ee1ff15 725 RecvISOPacket(&Length);
il_mix 0:90ad5ee1ff15 726 if (LastError==0)
il_mix 0:90ad5ee1ff15 727 {
il_mix 0:90ad5ee1ff15 728 if (Length>12) // 13 is the minimum expected
il_mix 0:90ad5ee1ff15 729 {
il_mix 0:90ad5ee1ff15 730 if ((PDU.H[27]!=0x00) || (PDU.H[28]!=0x00))
il_mix 0:90ad5ee1ff15 731 LastError = errS7Function;
il_mix 0:90ad5ee1ff15 732 }
il_mix 0:90ad5ee1ff15 733 else
il_mix 0:90ad5ee1ff15 734 LastError = errS7InvalidPDU;
il_mix 0:90ad5ee1ff15 735 }
il_mix 0:90ad5ee1ff15 736 }
il_mix 0:90ad5ee1ff15 737 else
il_mix 0:90ad5ee1ff15 738 LastError = errTCPDataSend;
il_mix 0:90ad5ee1ff15 739
il_mix 0:90ad5ee1ff15 740 return LastError;
il_mix 0:90ad5ee1ff15 741 }
il_mix 0:90ad5ee1ff15 742 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 743 int S7Client::PlcStart()
il_mix 0:90ad5ee1ff15 744 {
il_mix 0:90ad5ee1ff15 745 uint16_t Length;
il_mix 0:90ad5ee1ff15 746 LastError=0;
il_mix 0:90ad5ee1ff15 747 // Setup the telegram
il_mix 0:90ad5ee1ff15 748 memcpy(&PDU.H, S7_START, sizeof(S7_START));
il_mix 0:90ad5ee1ff15 749 if (TCPClient.send(PDU.H, sizeof(S7_START))==sizeof(S7_START))
il_mix 0:90ad5ee1ff15 750 {
il_mix 0:90ad5ee1ff15 751 RecvISOPacket(&Length);
il_mix 0:90ad5ee1ff15 752 if (LastError==0)
il_mix 0:90ad5ee1ff15 753 {
il_mix 0:90ad5ee1ff15 754 if (Length>12) // 13 is the minimum expected
il_mix 0:90ad5ee1ff15 755 {
il_mix 0:90ad5ee1ff15 756 if ((PDU.H[27]!=0x00) || (PDU.H[28]!=0x00))
il_mix 0:90ad5ee1ff15 757 LastError = errS7Function;
il_mix 0:90ad5ee1ff15 758 }
il_mix 0:90ad5ee1ff15 759 else
il_mix 0:90ad5ee1ff15 760 LastError = errS7InvalidPDU;
il_mix 0:90ad5ee1ff15 761 }
il_mix 0:90ad5ee1ff15 762 }
il_mix 0:90ad5ee1ff15 763 else
il_mix 0:90ad5ee1ff15 764 LastError = errTCPDataSend;
il_mix 0:90ad5ee1ff15 765
il_mix 0:90ad5ee1ff15 766 return LastError;
il_mix 0:90ad5ee1ff15 767 }
il_mix 0:90ad5ee1ff15 768 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 769 int S7Client::GetPlcStatus(int *Status)
il_mix 0:90ad5ee1ff15 770 {
il_mix 0:90ad5ee1ff15 771 uint16_t Length;
il_mix 0:90ad5ee1ff15 772 LastError=0;
il_mix 0:90ad5ee1ff15 773 // Setup the telegram
il_mix 0:90ad5ee1ff15 774 memcpy(&PDU.H, S7_PLCGETS, sizeof(S7_PLCGETS));
il_mix 0:90ad5ee1ff15 775 if (TCPClient.send(PDU.H, sizeof(S7_PLCGETS))==sizeof(S7_PLCGETS))
il_mix 0:90ad5ee1ff15 776 {
il_mix 0:90ad5ee1ff15 777 RecvISOPacket(&Length);
il_mix 0:90ad5ee1ff15 778 if (LastError==0)
il_mix 0:90ad5ee1ff15 779 {
il_mix 0:90ad5ee1ff15 780 if (Length>53) // 54 is the minimum expected
il_mix 0:90ad5ee1ff15 781 {
il_mix 0:90ad5ee1ff15 782 switch (PDU.H[54])
il_mix 0:90ad5ee1ff15 783 {
il_mix 0:90ad5ee1ff15 784 case S7CpuStatusUnknown :
il_mix 0:90ad5ee1ff15 785 case S7CpuStatusRun :
il_mix 0:90ad5ee1ff15 786 case S7CpuStatusStop : *Status=PDU.H[54];
il_mix 0:90ad5ee1ff15 787 break;
il_mix 0:90ad5ee1ff15 788 default :
il_mix 0:90ad5ee1ff15 789 // Since RUN status is always 0x08 for all CPUs and CPs, STOP status
il_mix 0:90ad5ee1ff15 790 // sometime can be coded as 0x03 (especially for old cpu...)
il_mix 0:90ad5ee1ff15 791 *Status=S7CpuStatusStop;
il_mix 0:90ad5ee1ff15 792 }
il_mix 0:90ad5ee1ff15 793 }
il_mix 0:90ad5ee1ff15 794 else
il_mix 0:90ad5ee1ff15 795 LastError = errS7InvalidPDU;
il_mix 0:90ad5ee1ff15 796 }
il_mix 0:90ad5ee1ff15 797 }
il_mix 0:90ad5ee1ff15 798 else
il_mix 0:90ad5ee1ff15 799 LastError = errTCPDataSend;
il_mix 0:90ad5ee1ff15 800
il_mix 0:90ad5ee1ff15 801 return LastError;
il_mix 0:90ad5ee1ff15 802 }
il_mix 0:90ad5ee1ff15 803 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 804 int S7Client::IsoExchangeBuffer(uint16_t *Size)
il_mix 0:90ad5ee1ff15 805 {
il_mix 0:90ad5ee1ff15 806 LastError=0;
il_mix 0:90ad5ee1ff15 807
il_mix 0:90ad5ee1ff15 808 if (TCPClient.send(PDU.H, int(Size))==*Size)
il_mix 0:90ad5ee1ff15 809 RecvISOPacket(Size);
il_mix 0:90ad5ee1ff15 810 else
il_mix 0:90ad5ee1ff15 811 LastError = errTCPDataSend;
il_mix 0:90ad5ee1ff15 812
il_mix 0:90ad5ee1ff15 813 return LastError;
il_mix 0:90ad5ee1ff15 814 }
il_mix 0:90ad5ee1ff15 815 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 816 void S7Client::ErrorText(int Error, char *Text, int TextLen)
il_mix 0:90ad5ee1ff15 817 {
il_mix 0:90ad5ee1ff15 818
il_mix 0:90ad5ee1ff15 819 }
il_mix 0:90ad5ee1ff15 820 #endif // _EXTENDED
il_mix 0:90ad5ee1ff15 821 //-----------------------------------------------------------------------------
il_mix 0:90ad5ee1ff15 822