Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Settimino.cpp@1:2f8bf824ec67, 2016-11-17 (annotated)
- 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?
User | Revision | Line number | New 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 |