|
|
Go to the documentation of this file.
15#ifdef FAUDES_IODEVICE_MODBUS
44 FD_DHV( "mbDevice(" << mName << ")::mbDevice()");
46 mDefaultLabel = "ModbusDevice";
53 mMessage= new char[260];
56 mSlaveAddress.IpColonPort( "localhost:502");
96 std::stringstream errstr;
97 errstr << "image size must not exceed 2000 bits (image #" << i+1 << ")";
98 throw Exception( "mbDevice:Read", errstr.str(), 52);
113 std::stringstream errstr;
114 errstr << "Slave must have localhost as SlaveAddress";
115 throw Exception( "mbDevice:Compile()", errstr.str(), 52);
209 while(rTr. Peek(token)) {
215 std::stringstream errstr;
216 errstr << "Invalid role tag, value attribute missing" << rTr. FileLine();
217 throw Exception( "mpiDevice:Read", errstr.str(), 52);
220 std::transform(val.begin(), val.end(), val.begin(), tolower);
224 std::stringstream errstr;
225 errstr << "Invalid value attribute in role tag" << rTr. FileLine();
226 throw Exception( "spiDevice:Read", errstr.str(), 52);
232 if(token. IsBegin( "SlaveAddress")) {
233 FD_DHV( "mBDevice::DoRead(): found slave address");
236 std::stringstream errstr;
237 errstr << "Invalid ip address" << rTr. FileLine();
238 throw Exception( "mbDevice:Read", errstr.str(), 52);
245 if(token. IsBegin( "RemoteImage")) {
247 while(!rTr. Eos( "RemoteImage")) {
251 if(!rtoken. IsBegin( "Outputs")) {
252 std::stringstream errstr;
253 errstr << "invalid io range" << rTr. FileLine();
254 throw Exception( "mbDevice:Read", errstr.str(), 52);
263 std::stringstream errstr;
264 errstr << "missing remote address" << rTr. FileLine();
265 throw Exception( "mbDevice:Read", errstr.str(), 52);
276 std::stringstream errstr;
277 errstr << "image size must not exceed 2000 bits" << rTr. FileLine();
278 throw Exception( "mbDevice:Read", errstr.str(), 52);
303 mSlaveSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
305 std::stringstream errstr;
306 errstr << "Modbus fatal network error (cannot open server socket)";
307 throw Exception( "mbDevice::Start", errstr.str(), 553);
310 faudes_setsockopt( mSlaveSocket,SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
312 struct sockaddr_in slaveaddress;
313 memset(&slaveaddress, 0, sizeof(slaveaddress));
314 slaveaddress.sin_family = AF_INET;
315 slaveaddress.sin_addr.s_addr = htonl(INADDR_ANY);
318 if(bind( mSlaveSocket, ( struct sockaddr *) &slaveaddress, sizeof(slaveaddress)) <0) {
319 std::stringstream errstr;
320 errstr << "Modbus fatal network error (cannot bind socket)";
321 throw Exception( "nDevice::Start", errstr.str(), 553);
325 std::stringstream errstr;
326 errstr << "Simplenet fatal network error (cannot listen from socket)";
327 throw Exception( "mbDevice::Start", errstr.str(), 553);
353 FD_DH( "mbDevice::Stop(): closing slave socket");
358 FD_DH( "mbDevice::Stop(): done");
364#define MB_SETINT(p,v) { mMessage[p] = ((v)>>8); mMessage[p+1] = ((v) & 0xff); }
365#define MB_GETINT(p) ( ( mMessage[p] << 8) + ((int) mMessage[p+1]) )
366#define MB_SETBYTE(p,v) { mMessage[p] = (v);}
367#define MB_GETBYTE(p) ( mMessage[p] )
381 int avail= select( mSlaveSocket+1, &mysocks, NULL, NULL, &tv);
384 FD_DH( "mbDevice::MbFlushBuffers(): flush recv buffer");
388 FD_DH( "mbDevice::MbFlushBuffers(): flush recv buffer: fatal error?");
391 FD_DHV( "mbDevice::MbFlushBuffers(): ok");
431 int avail=select(mysocks_max+1, &mysocks, NULL, NULL, &tv);
434 if(avail<=0) return -1;
440 FD_DH( "mbDevice::MbReceiveResponse(): invalid MBAB header (size mismatch)");
455 FD_DH( "mbDevice::MbReceiveRequest(): invalid MBAB header (size mismatch)");
471 int rc=send(mastersock, mMessage+from, left, 0);
488 if(ctimer< 1000000) return;
493 int slavesock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
495 FD_DH( "mbDevice::LoopCallBack(): connection to slave failed: cannot create socket");
499 unsigned long int slaveinaddr = INADDR_NONE;
500 if(slaveinaddr==INADDR_NONE) {
501 FD_DHV( "mbDevice::LoopCallBack(): connecting to remote slave: using provided address literaly");
504 if(slaveinaddr==INADDR_NONE) {
505 struct hostent *host;
508 FD_DHV( "mbDevice::LooCallBack(): connecting to remote slave: retrieve address by name-lookup");
509 slaveinaddr = *( unsigned long int*) host->h_addr;
512 if(slaveinaddr==INADDR_NONE) {
513 FD_DH( "mbDevice::DoLooCallBack():: connection to slave failed: no valid address " << mSlaveAddress. Ip());
514 faudes_closesocket(slavesock);
518 struct sockaddr_in slaveaddress;
519 memset(&slaveaddress, 0, sizeof(slaveaddress));
520 slaveaddress.sin_family = AF_INET;
521 slaveaddress.sin_addr.s_addr=slaveinaddr;
524 int rc = faudes_setsocket_nonblocking(slavesock, true);
526 FD_DH( "mbDevice::LoopCallBack():: connection to slave failed: socker error A1");
527 faudes_closesocket(slavesock);
531 int rcc= connect(slavesock, ( struct sockaddr*) &slaveaddress, sizeof(slaveaddress));
535 if(errno!=EINPROGRESS) {
536 FD_DH( "mbDevice::LoopCallBack(): connection to slave failed: system errno " << errno);
538 FD_DH( "mbDevice::LoopCallBack(): connecting to slave: wait for slave to accept");
545 FD_SET(slavesock, &mysocks);
546 rcc= select(slavesock+1, NULL, &mysocks, NULL, &tv);
548 if(rcc<0) FD_DH( "mbDevice::LoopCallBack(): connection to slave failed: timeout");
554 int lerr = WSAGetLastError();
555 if(lerr!=WSAEWOULDBLOCK) {
556 FD_DH( "mbDevice::LoopCallBack(): connection to slave failed: system errno " << lerr);
558 FD_DH( "mbDevice::LoopCallBack(): connecting to slave: wait for slave to accept");
565 FD_SET(slavesock, &mysocks);
566 rcc= select(slavesock+1, NULL, &mysocks, NULL, &tv);
568 if(rcc<0) FD_DH( "mbDevice::LoopCallBack(): connection to slave failed: timeout");
574 FD_DH( "mbDevice::LoopCallBack(): connection to slave failed: slave unreachable");
575 faudes_closesocket(slavesock);
579 if(faudes_getsocket_error(slavesock)<0) {
580 FD_DH( "mbDevice::LoopCallBack(): connection to slave failed: socket error A2");
581 faudes_closesocket(slavesock);
585 rc = faudes_setsocket_nonblocking(slavesock, false);
587 FD_DH( "mbDevice::LoopCallBack():: connection to slave failed: socket error A3");
588 faudes_closesocket(slavesock);
592 FD_DH( "mbDevice::LoopCallBack(): connected to remote slave: using socket #" << slavesock);
607 int avail = select( mSlaveSocket+1, &mysocks, NULL, NULL, &tv);
612 FD_DH( "mbDevice::LoopCallBack(): accepting remote master to connect");
613 struct sockaddr_in masteraddr;
614 socklen_t masteraddr_len = sizeof(masteraddr);
615 int mastersock=accept( mSlaveSocket, ( struct sockaddr *) &masteraddr, &masteraddr_len );
617 FD_DH( "mbDevice::LoopCallback(): failed to accept incomming connection");
628 FD_DHV( "mbDevice::DoLooCallBack(): update image from remote slave");
639 FD_DHV( "mbDevice::LoopCallBack(): sending read request");
641 FD_DH( "mbDevice::LoopCallBack(): sending read request to slave: failed");
647 FD_DHV( "mbDevice::LoopCallBack(): read response");
649 FD_DH( "mbDevice::LoopCallBack(): reading reply to read request from slave: failed");
658 FD_DHV( "mbDevice::LoopCallBack(): input image received");
667 addr++; count--; shft = shft <<1;
668 if(shft==0x100) { shft=0x01; data= MB_GETBYTE(++src);};
671 FD_DH( "mbDevice::LoopCallBack(): received error when reading inputs");
682 int bcount= (ior. mCount-1)/8 +1;
690 if( mpImage[addr]) data |= shft;
691 addr++; count--; shft = shft <<1;
692 if(shft==0x100) { shft=0x01; MB_SETBYTE(dst,data); data=0x00; dst++;}
697 FD_DHV( "mbDevice::LoopCallBack(): sending write request");
699 FD_DHV( "mbDevice::LoopCallBack(): sending write failed");
706 FD_DH( "mbDevice::LoopCallBack(): reading reply to write request from slave: failed");
712 FD_DH( "mbDevice::LoopCallBack(): received error response on write request");
728 if(mastersock<0) continue;
729 FD_SET(mastersock, &mysocks);
730 if(mysocks_max< mastersock) mysocks_max=mastersock;
737 int avail=select(mysocks_max+1, &mysocks, NULL, NULL, &tv);
743 if(mastersock<0) continue;
744 if(!FD_ISSET(mastersock, &mysocks)) continue;
745 FD_DHV( "mbDevice::LoopCallback(): received message on sock " << mastersock);
747 FD_DH( "mbDevice::LoopCallback(): receive error on sock " << mastersock);
748 faudes_closesocket(mastersock);
757 if((fnct==0x01) || (fnct==0x02)) {
758 FD_DHV( "mbDevice::LoopCallback(): coil-read or input read request");
761 int bcount= ((count-1)/8+1);
762 FD_DHV( "mbDevice::LoopCallback(): address range: @" << addr << " #" << count);
766 if(count>2000) errcode=0x02;
774 if( mpImage[addr]) data |= shft;
775 addr++; count--; shft = shft <<1;
776 if(shft==0x100) { shft=0x01; MB_SETBYTE(dst,data); dst++; data=0x00;}
785 if((fnct==0x03) || (fnct==0x04)) {
786 FD_DHV( "mbDevice::LoopCallback(): register or holding register read request");
789 FD_DHV( "mbDevice::LoopCallback(): address range: @" << addr << " #" << count);
802 for(;count>0; count--) {
805 for(;src< mImageSize && shft!=0x100; src++, shft = shft << 1)
806 if( mpImage[src]) lbyte |= shft;
809 for(;src< mImageSize && shft!=0x100; src++, shft = shft << 1)
810 if( mpImage[src]) hbyte |= shft;
818 FD_DHV( "mbDevice::LoopCallback(): write single coil request");
821 FD_DHV( "mbDevice::LoopCallback(): write single coil request: " << addr << " to " << val);
833 FD_DHV( "mbDevice::LoopCallback(): write holding register request");
836 FD_DHV( "mbDevice::LoopCallback(): set @" << addr << " to " << val);
845 int hbyte= (val >> 8);
846 int lbyte= (val & 0xff);
848 for(shft=0x01; shft!=0x100; shft = shft << 1, dst++)
849 mpImage[dst] = (( lbyte & shft) != 0);
850 for(shft=0x01; shft!=0x100; shft = shft << 1, dst++)
851 mpImage[dst] = (( hbyte & shft) != 0);
858 FD_DHV( "mbDevice::LoopCallback(): write multiple coils request");
862 FD_DHV( "mbDevice::LoopCallback(): address range: @" << addr << " #" << count << "(" << bcount << ")");
866 if( (bcount < ((count-1)/8+1)) || ( mMessageLen < 6+bcount) ) errcode=0x03;
874 if(shft==0x100) { shft=0x01; data= MB_GETBYTE(src);src++;};
876 addr++; count--; shft = shft <<1;
884 FD_DHV( "mbDevice::LoopCallback(): write multiple holding registers request");
888 FD_DHV( "mbDevice::LoopCallback(): address range: @" << addr << " #" << count << "(" << bcount << ")");
893 if( bcount != 2* count)
900 for(;count>0;count--) {
904 for(shft=0x01; shft!=0x100; shft = shft << 1, dst++)
905 mpImage[dst] = (( lbyte & shft) != 0);
906 for(shft=0x01; shft!=0x100; shft = shft << 1, dst++)
907 mpImage[dst] = (( hbyte & shft) != 0);
920 FD_DH( "mbDevice::LoopCallback(): sending error reply, code " << errcode);
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
std::string IpColonPort(void) const
std::string Ip(void) const
std::string FileLine(void) const
bool Eos(const std::string &rLabel)
void ReadEnd(const std::string &rLabel)
void ReadBegin(const std::string &rLabel)
void WriteEnd(const std::string &rLabel)
void WriteBegin(const std::string &rLabel)
const std::string & StringValue(void) const
Int AttributeIntegerValue(const std::string &name)
bool ExistsAttributeString(const std::string &name)
void SetEmpty(const std::string &rName)
bool ExistsAttributeInteger(const std::string &name)
void InsAttributeInteger(const std::string &name, Int value)
void InsAttributeString(const std::string &name, const std::string &value)
const std::string & AttributeStringValue(const std::string &name)
void DoReadPreface(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
virtual bool DoReadSignal(int bitaddr)
int MbSendResponse(int mastersock)
int MbReceiveRequest(int mastersock)
virtual void DoReadSignalsPost(void)
void SlaveAddress(const std::string &rAddr)
virtual void Compile(void)
int MbReceiveResponse(void)
virtual bool DoWriteSignalsPre(void)
void DoWritePreface(TokenWriter &rTw, const std::string &rLabel, const Type *pContext) const
std::vector< IoRange > mSlaveIoRanges
virtual void DoLoopCallback(void)
virtual void DoWriteSignal(int bitaddr, bool value)
virtual bool DoReadSignalsPre(void)
virtual void DoWriteSignalsPost(void)
int MbSendRequest(int id)
std::vector< int > mMasterSockets
void AppendRemoteInputs(int mbid, int mbaddr, int cnt, int fdaddr)
SimplenetAddress mSlaveAddress
void AppendRemoteOutputs(int mbid, int mbaddr, int cnt, int fdaddr)
virtual int CycleTime() const
virtual void DoReadPreface(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
void DoWritePreface(TokenWriter &rTw, const std::string &rLabel, const Type *pContext=0) const
std::map< int, EventSet > mOutputLevelIndexMap
virtual void Compile(void)
virtual DeviceState Status(void)
AutoRegisterType< mbDevice > gRtiRegisterSpiDevice("ModbusDevice")
libFAUDES 2.34e
--- 2026.03.16
--- c++ api documentaion by doxygen
|