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