I am using NModbus in a C# project, to read & write Modbus data from/to a number of I/O devices. I am using the Modbus TCP/IP protocol (ModbusIpMaster etc..) in the program.
I have successfully communicated with the devices (through a Modbus gateway) and can use the default methods (e.g. common Modbus functions such as ReadHoldingRegisters, WriteCoils ), to access the data from the devices, and can write back to them. At the moment, all I can do are the default NModbus methods which expose commonly used Modbus codes (1, 2, 3, 4 etc..).
I have two difficulties:
1) The I/O devices' settings and extra information can be accessed under the Modbus code of 70 (0x46), and there are sub functions which I will need to use in order to read and/or write the settings.
For example, Func 07 (0x46), Sub func 6 (0x06), can be used to set the communications settings of a module. In this example there are 7 bytes of information to be sent which carry the settings (e.g. baud rate etc...)
NModbus does not have a specific method for this 'custom' function code (70). So, from what I understand, one needs to use the CustomMessage feature of NModbus. I have tried executing CustomMessage, and when using the common Modbus function codes (e.g. 1 or 2) I can achieve the same result as if I were using the default methods of NModbus (i.e. the CustomMessage is working so far).
When I try function codes other than the general ones (e.g. 1, 2, 3...) I do get all sorts of exceptions. Furthermore, I do not know how I should send the sub-function with the message!
When I added the subfunction just after the function code (e.g. 70 followed by 06), and the data is send through I get, exceptions. I really need help from experts in this field, please.
Here is a more obvious exception:
" Exception of type 'Modbus.SlaveException' was thrown. Function Code: 198 Exception Code: 3 - A value contained in the query data
field is not an allowable value for server (or slave). This indicates
a fault in the structure of the remainder of a complex request, such
as that the implied length is incorrect. It specifically does NOT mean
that a data item submitted for storage in a register has a value
outside the expectation of the application program, since the MODBUS
protocol is unaware of the significance of any particular value of any
particular register."
2) The second problem is sending ASCII RS-232 messages through Modbus, in order to control an RS-232 device which is connected to COM1 of a module which has the ability to convert Modbus messages. In other words, I am planning to communicate with the Modbus gateway, to send ASCII data to its COM1, which in turn translates data to RS-232 and then communicates with the RS-232 device. The translation is meant to occur internal to the gateway, so all I need to know is how on Earth I can send these messages through, which vary in length. I have no idea how that is possible, and where to start from.
Part 2 - NModbus allows you to create an ASCII master over a TCP or UDP client.
using (TcpClient client = new TcpClient("127.0.0.1", 502))
{
ModbusSerialMaster master = ModbusSerialMaster.CreateAscii(client);
// Use the master here
}
With regard to the first part of the question, NModbus is great for the basics, but it lacks a layer of abstraction that would allow it to be extended arbitrarily. My own experience of it ended when I found that it would require significant modification to add and make the GetServerId function to work, even though this is part of the specification for Modbus RTU. My solution was to re-implement it from the ground up, (which took me less time than getting the NModbus source to compile and run in the first place, due to it's dependency on third part libraries for logging, etc & missing extensions for IEnumerable classes).
Related
I'm currently learning how to use sockets on c#, and have a question regarding how the messages should be between the client and the server.
Currently i have a server application and a client application, and in each application i have some strings that are the commands. When, for example, the client needs the time from the server, i have a string like this:
public const string GET_TIME_COMMAND = "<GET_TIME_COMMAND>";
Then i have a if statement on the server, thats checks if the message sent from the client starts with that string and if so, it sends another message to the client with another command and with the time in a json string.
My question is, is this a good way to do it, and if not could you advise me on another way to go about this?
TCP
Keep in mind that TCP is a stream based connection. You may or may not get the complete command in one message. You may even get multiple commands in one read.
To solve this TCP messages usually have a unique start and stop sequence or byte that may not be part of the message.
(SomeCommand)
Where ( is the start and ) is the stop symbol.
An alternative way os to prepend a header to the actual message that contains the message length.
11 S O M E M E S S A G E
Where 11 is the message length and somemessage is the actual message. You'd usually transmit the length as a byte or ushort, not a string literal.
In both cases you have to read over and over until you have one complete message - then you can dispatch it into the application.
Also TCP is connection based. You have to connect to the remote site. The advantage is that TCP makes sure that all messages are sent in the very order you put them in. TCP will also automatically re-send lost packets and you don't have to worry about that.
UDP
In contrast to that UDP is a message/packet based, but it is not reliable. You may or may not get the message and have to re-send it in some cases. Also UDP doesn't have a notion of a "session". You would have to do that yourself if required.
The answer to your question depends on the protocol used. For TCP this won't work well with your current message format. You'd probably have to prepend a header.
You could use UDP, but then you may have to detect and re-send messages that got lost.
Introduction
We exchange income data with an external party. Each year income tax regulations change and a new message schema has to be implemented. Altogether we now have 8 different schema versions each of which are deployed in a separate 'year income tax' application and this amount increases by 1 each year.
Because we pay our hosting company per installed application, we want to decrease the amount of applications installed.
All these applications are functionally equal, which means we validate incoming messages, and forward valid messages into a specific MQSeries queue. Each invalid message is routed to a response queue. Each application has it's own 'valid' and 'invalid' message queues.
The plan
One generic application that processes all 8(+) messages. New schemas must be deployable without application changes or downtime for previous, running 'income year tax' flows.
So far...
I can receive multiple messages on the same BizTalk receive port (MessageType XmlDocument) and am able to validate these messages dynamically in an orchestration by calling a custom receive pipeline (XML Disassembler + XML Validator). Exceptions as well as valid messages are processed as prescribed. There are no references between the Schemas and the generic application, so schemas can be deployed without need to stop running processes. So far, so good.
The orchestration has 1 receive shape, and 2 send shapes (valid, invalid).
SSO contains the values for routing the 'valid' and 'invalid' messages to their correct queue. Based on the incoming messagetype SSO is questioned for the correct 'valid' or 'invalid' queuedefinition.
The problem
I have previously dealt with dynamic FTP, FILE, WCF and SMTP ports, which all worked flawlessly after supplying the adapter with the correct Context Properties. Even MSMQ seems to have a fairly straightforward approach on dynamically setting transport properties.
However, I cannot seem to find MQSeries MQMT ContextProperties to set the queuedefinition dynamically.
Microsoft does not provide much information on this, and extensive searches on the internet hasn't provided me with anything useful (examples) either.
I tried matching IBM's docs with Microsoft's, but altogether I am now stuck.
I would suggest to use MQSC adapter for IBM MQ integration. It is part of Host Integration Server MSI. It only requires MQ client to be installed on the server Vs MQ Server for Windows installation required by MQSeries adapter.
Set the OutboundTransportLocation property in following format mqsc://{channelName}/tcp/{server{({port})/{queuemanager}/{queuename}
TransportType = MQSC
Context Properties - Schema can be found within assembly MQSeriesEx.MQSPropertySchemaEx with namespace (http://schemas.microsoft.com/BizTalk/2003/mqs-properties).
There are only few context properties you would need to set if at all required.
Channel_HeartBeat
Channel_MaxMessageLength
Channel_UserId
Channel_Password
ConnectionTimeout
If additional properties are required than use MQSeries.MQSPropertySchema context properties.
Thanks Vikas for your suggestion.
I followed your directions and found it works!
However, I found it a little more complicated than needed as it required me configuring channel names for each flow.
The solution that best suited me was the one I had in mind all along, and it was right before me. My attempts failed because I made a fatal mistake by setting the outgoing message's properties where I should have set the dynamic send port's properties.
SendPort(Microsoft.XLANGs.BaseTypes.Address)="MQS://SERVER/QMANAGER/QUEUENAME";
I'm writting a small application that automatically connects to the correct serial port by sending a list of commands, and then waiting for a response back from the serial device (RF Transmitter). The serial port objects sends certain commands in decimal format, a reset, login and then a query command.
When the query command is sent, the device then replies back with a response - when this response is received I know I have the correct serial port connection.
All of this works fine, but sometimes I receive an error back from the device - Error 130: TX Queue Overflow. This error can be resolved by simply restarted the device (RF Transmitter), but the frequency of this error is just silly.
Am I correct in thinking that a TX Overflow error would be caused when the buffer on the hardware becomes full? I thought a simple DiscardInBuffer just after opening a connection to the device would fix this - but it doesn't.
When should I use the DiscardInBuffer, am I using it in the correct context?
-- Edit
After some more comments and thoughts, I've come to the conclusion that the SerialPort.DiscardInBuffer won't do anything for my current situation, rather I need to discard the buffer on the actual RF Device - Hence why inplugging it works.
You've sent too much data to the device, and its output queue has overflowed, meaning it is not able to forward the data as fast as you're providing it.
There's no method you can call on the SerialPort class to fix this, these are two completely different buffers we're talking about. Calling SerialPort.DiscardOutBuffer will only discard the output data pending for your serial port, not the device.
To temporarily fix the issue, the manual indicates that you can:
Use the command “reset txqueue” to clear the queue.
The better solution, however, is to prevent the issue and not flood the device with data. The exact way to do this will depend on your hardware.
One way might be to introduce some sort of CommandQueue class which has an associated SerialPort object to push the commands to the hardware. In this class, you could queue up commands to be sent, and send them out a configurable maximum rate. You would use a timer, and only send commands out if one hasn't been sent in the last X msec.
Another way would be to implement some sort of software flow control. It appears that your device supports querying the queue length with the "?STATE" command (page 13). It will respond with:
STATE x1/x2 x3 x4
x1: Number of datapackets in TX queue
x2: Size of TX queue
x3: Status byte (8 bit hexadecimal)
Normal state: status byte = 0
Bit 0 = 1: Error in transceiver
Bit 1 = 1: Error in EEPROM
x4: Current value of the dataset counter (number of last received and saved datapacket)
You could query this before attempting to send a data packet, and simply sleep while the queue is full.
Having written a lot of code to interface with finicky hardware (Serial, Ethernet, etc.) in C#, I can offer the following advice:
Implement an abstract class TN9000DeviceBase which has abstract methods for all of the commands supported by the device.
Derive a class TN9000SerialDevice : TN9000DeviceBase which executes the command using serial port.
This will allow you to come back and implement it via Ethernet when requirements change.
I have one application running on specific port. I dont have access to this application but i know what it does. Now this application is listening on one specific port and process the data coming on that port
Now i have been assigned the task on logging all the packets received on that port with all the data details. I have used the wireshark and can apply the filter to check the data coming on that specific port. So i assume here that i have been stuck in creating this kind of snipping program so i can get all the data packet details. I have search the stack overflow and come up with
Code project
Stack overflow
Now i have evalute the sample and can see that it gives me packets but it listens on all port of the system. Not on the specific port. Can someone help me to achieve my solution? Basically if i will listen to all port then there are lots of app/program running on server so it may get bottleneck. Thank you all.
In MJsniffer.MJsnifferForm class you have ParseData method - at first step it converts received bytes to IPHeader object, an then there a huge SWITCH-CASE on ProtocolType field. Inside that SWITCH there are TCPHeader or UDPHeader is created and added to TreeView on form - there you can filter packages by SourcePort/DestinationPort fields tcpHeader/udpHeader.
Also if you are already familiar with WireShark, then you can easly switch to Pcap.NET wrapper(they use same packet capturing library - WinPcap)
I'm writing a server application for an iPhone application im designing. iPhone app is written in C# (MonoTouch) and the server is written in C# too (.NET 4.0)
I'm using asynchronous sockets for the network layer. The server allows two or more iPhones ("devices") to connect to each other and be able to send data bi-directionally.
Depending on the incoming message, the server either processes the message itself , or relays the data through to the other device(s) in the same group as the sending device. It can make this decision by decoding the header of the packet first, and deciding what type of packet it is.
This is done by framing the stream in a way that the first 8 bytes are two integers, the length of the header and the length of the payload (which can be much larger than the header).
The server reads (asynchronously) from the socket the first 8 bytes so it has the lengths of the two sections. It then reads again, up to the total length of the header section.
It then deserializes the header, and based on the information within, can see if the remaining data (payload) should be forwarded onto another device, or is something that the server itself needs to work with.
If it needs to be forwarded onto another device, then the next step is to read data coming into the socket in chunks of say, 1024 bytes, and write these directly using an async send via another socket that is connected to the recipient device.
This reduces the memory requirements of the server, as i'm not loading in the entire packet into a buffer, then re-sending it down the wire to the recipient.
However, because of the nature of async sockets, I am not guaranteed to receive the entire payload in one read, so have to keep reading until I receive all the bytes. In the case of relaying onto its final destination, this means that i'm calling BeginSend() for each chunk of bytes I receive from the sender, and forwarding that chunk onto the recipient, one chunk at a time.
The issue with this is that because I am using async sockets, this leaves the possibility of another thread doing a similar operation with the same recipient (and therefore same final destination socket), and so it is likely that the chunks coming from both threads will get mixed up and corrupt all the data going to that recipient.
For example: If the first thread sends a chunk, and is waiting for the next chunk from the sender (so it can relay it onwards), the second thread could send one of its chunks of data, and corrupt the first thread's (and the second thread's for that matter) data.
As I write this, i'm just wondering is it as simple as just locking the socket object?! Would this be the correct option, or could this cause other issues (e.g.: issues with receiving data through the locked socket that's being sent BACK from the remote device?)
Thanks in advance!
I was facing a similar scenario a while back, I don't have the complete solution anymore, but here's pretty much what I did :
I didn't use sync sockets, decided to explore the async sockets in C# - fun ride
I don't allow multiple threads to share a single resource unless I really have to
My "packets" were containing information about size, index and total packet count for a message
My packet's 1st byte was unique to signify that it's a start of a message, I used 0xAA
My packets's last 2 bytes were a result of a CRC-CCITT checksum (ushort)
The objects that did the receiving bit contained a buffer with all received bytes. From that buffer I was extracting "complete" messages once the size was ok, and the checksum matched
The only "locking" I needed to do was in the temp buffer so I could safely analyze it's contents between write/read operations
Hope that helps a bit
Not sure where the problem is. Since you mentioned servers, I assume TCP, yes?
A phone needs to communicate some of your PDU to another phone. It connects as a client to the server on the other phone. A socket-pair is established. It sends the data off to the server socket. The socket-pair is unique - no other streams that might be happening between the two phones should interrupt this, (will slow it up, of course).
I don't see how async/sync sockets, assuming implemented correctly, should affect this, either should work OK.
Is there something I cannot see here?
BTW, Maciek's plan to bolster up the protocol by adding an 'AA' start byte is an excellent idea - protocols depending on sending just a length as the first element always seem to screw up eventually and result in a node trying to dequeue more bytes that there are atoms in the universe.
Rgds,
Martin
OK, now I understand the problem, (I completely misunderstood the topology of the OP network - I thought each phone was running a TCP server as well as client/s, but there is just one server on PC/whatever a-la-chatrooms). I don't see why you could not lock the socket class with a mutex, so serializing the messages. You could queue the messages to the socket, but this has the memory implications that you are trying to avoid.
You could dedicate a connection to supplying only instructions to the phone, eg 'open another socket connection to me and return this GUID - a message will then be streamed on the socket'. This uses up a socket-pair just for control and halves the capacity of your server :(
Are you stuck with the protocol you have described, or can you break your messages up into chunks with some ID in each chunk? You could then multiplex the messages onto one socket pair.
Another alternative, that again would require chunking the messages, is introduce a 'control message', (maybee a chunk with 55 at start instead of AA), that contains a message ID, (GUID?), that the phone uses to establish a second socket connection to the server, passes up the ID and is then sent the second message on the new socket connection.
Another, (getting bored yet?), way of persuading the phone to recognise that a new message might be waiting would be to close the server socket that the phone is receiving a message over. The phone could then connect up again, tell the server that it only got xxxx bytes of message ID yyyy. The server could then reply with an instruction to open another socket for new message zzzz and then resume sending message yyyy. This might require some buffering on the server to ensure no data gets lost during the 'break'. You might want to implement this kind of 'restart streaming after break' functionality anyway since phones tend to go under bridges/tunnels just as the last KB of a 360MB video file is being streamed :( I know that TCP should take care of dropped packets, but if the phone wireless layer decides to close the socket for whatever reason...
None of these solutions is particularly satisfying. Interested to see whay other ideas crop up..
Rgds,
Martin
Thanks for the help everyone, i've realised the simpliest approach is to use synchronous send commands on the client, or at least a send command that must complete before the next item is sent. Im handling this with my own send queue on the client, rather than various parts of the app just calling send() when they need to send something.