@@ -36,19 +36,43 @@ void TcpSlave::cbResponse(ResultCode res, void *data, uint16_t len)
3636 }
3737 else
3838 {
39- // respond to TCP master
40- // uint16_t ll = len +2;
41- // _MBAP[4] = ll >> 8;
42- // _MBAP[5] = ll & 0xff;
43- // _MBAP[6] = 0x01;
44- // uint8_t _buf[MODBUSIP_MAXFRAME];
45- // memcpy(_buf,_MBAP, 7);
46- // memcpy(&(_buf[7]),data, len);
47- // // _client.write((byte*)_MBAP, 7);
48- // _client.clearWriteError();
49- // _client.write((byte*)_buf, len+7);
50- // _client.flush();
51-
39+ Transaction *trans = searchTransaction (_frame);
40+ if (trans)
41+ {
42+ uint8_t *mem = (uint8_t *)malloc (len);
43+ if (mem)
44+ {
45+ free (trans->_responseFrame );
46+ trans->_responseFrame = mem;
47+ memcpy (trans->_responseFrame , data, len);
48+ trans->_responseFrameLen = len;
49+ trans->timestamp = millis ();
50+ }
51+ }
52+ else
53+ {
54+ Transaction newEntry;
55+ newEntry.timestamp = millis ();
56+ uint8_t *memReq = (uint8_t *)malloc (_len);
57+ if (memReq)
58+ {
59+ newEntry._requestFrame = memReq;
60+ memcpy (newEntry._requestFrame , _frame, _len);
61+ newEntry._requestFrameLen = _len;
62+ uint8_t *memResp = (uint8_t *)malloc (len);
63+ if (memResp)
64+ {
65+ newEntry._responseFrame = memResp;
66+ memcpy (newEntry._responseFrame , data, len);
67+ newEntry._responseFrameLen = len;
68+ _trans.push_back (newEntry);
69+ }
70+ else
71+ {
72+ free (memReq);
73+ }
74+ }
75+ }
5276 free (_frame);
5377 _len = len;
5478 _frame = (uint8_t *)malloc (len);
@@ -129,11 +153,30 @@ void TcpSlave::run()
129153 {
130154 if (_pClients[_clientIndex]->localPort () == _slavePort)
131155 {
156+ if (!SupportedFunction (_frame[0 ])) {
157+ exceptionResponse ((FunctionCode)_frame[0 ], EX_ILLEGAL_FUNCTION);
158+ }
132159 // forward incoming frame to RTU master
133- if (_rtuMaster.Transfer (_frame, _len, this ) == false )
160+ else if (_rtuMaster.Transfer (_frame, _len, this ) == false )
134161 {
135- exceptionResponse ((FunctionCode)_frame[0 ], EX_SLAVE_DEVICE_BUSY);
136- _rtuState = RTU_IDLE;
162+ Transaction *trans = searchTransaction (_frame);
163+ if (trans)
164+ {
165+ uint8_t *mem = (uint8_t *)malloc (trans->_responseFrameLen );
166+ if (mem)
167+ {
168+ _len = trans->_responseFrameLen ;
169+ free (_frame);
170+ _frame = mem;
171+ memcpy (_frame, trans->_responseFrame , _len);
172+ _rtuState = RTU_COMPLETE;
173+ }
174+ }
175+ else
176+ {
177+ exceptionResponse ((FunctionCode)_frame[0 ], EX_DEVICE_FAILED_TO_RESPOND);
178+ _rtuState = RTU_IDLE;
179+ }
137180 }
138181 else
139182 {
@@ -145,9 +188,25 @@ void TcpSlave::run()
145188 }
146189 if (_rtuState != RTU_COMPLETE)
147190 { // did not complete?
148- exceptionResponse ((FunctionCode)_frame[0 ], _rtuState == RTU_FAILED ? EX_GENERAL_FAILURE : EX_TIMEOUT);
149- _rtuState = RTU_IDLE;
150- _rtuMaster.reset ();
191+ Transaction *trans = searchTransaction (_frame);
192+ if (trans)
193+ {
194+ uint8_t *mem = (uint8_t *)malloc (trans->_responseFrameLen );
195+ if (mem)
196+ {
197+ _len = trans->_responseFrameLen ;
198+ free (_frame);
199+ _frame = mem;
200+ memcpy (_frame, trans->_responseFrame , _len);
201+ _rtuState = RTU_COMPLETE;
202+ }
203+ }
204+ else
205+ {
206+ exceptionResponse ((FunctionCode)_frame[0 ], _rtuState == RTU_FAILED ? EX_GENERAL_FAILURE : EX_DATA_MISMACH);
207+ _rtuState = RTU_IDLE;
208+ _rtuMaster.reset ();
209+ }
151210 }
152211 }
153212 }
@@ -204,5 +263,40 @@ void TcpSlave::cleanup()
204263 _pClients[i] = nullptr ;
205264 }
206265 }
266+ // remove old transactions
267+ for (auto it = _trans.begin (); it != _trans.end ();)
268+ {
269+ if (millis () - it->timestamp > TRANSACTION_LIFESPAN)
270+ {
271+ free (it->_requestFrame );
272+ free (it->_responseFrame );
273+ it = _trans.erase (it);
274+ }
275+ else
276+ it++;
277+ }
278+ }
279+ Transaction *TcpSlave::searchTransaction (uint8_t *frame)
280+ {
281+ std::vector<Transaction>::iterator it = std::find_if (_trans.begin (), _trans.end (), [frame](Transaction &trans) { return memcmp (trans._requestFrame , frame, trans._requestFrameLen ) == 0 ; });
282+ if (it != _trans.end ())
283+ return &*it;
284+ return nullptr ;
285+ }
286+
287+ boolean TcpSlave::SupportedFunction (uint8_t fcode) {
288+ bool rVal = false ;
289+ switch (fcode) {
290+ case FC_READ_REGS:
291+ case FC_READ_COILS:
292+ case FC_READ_INPUT_STAT:
293+ case FC_READ_INPUT_REGS:
294+ rVal = true ;
295+ break ;
296+
297+ default :
298+ rVal = false ;
299+ }
300+ return rVal;
207301}
208302} // namespace ModbusAdapter
0 commit comments