I am currently looking for different possibilities to communicate with SCPI-compatible devices via C#. I've written my first code in LabWindows/CVI (language: C) via a COM interface and did it quite "manually" as I would say:
ComOpen(ComId, "Com1",....);
ComWrite("SYST:...\r");
ComRead(&value)`
Something like this. The problem was for me that I don't like pure C and the lack of OOP was just stupid since I have real objects that want to communicate. Dear National Instruments, why not use OOP to control objects?
Now somebody gave me the hint, that I should look into the global SCPI-documentation since there is more information than in the manual of the device. And I've found a .NET-compatible set of commands. For example,
IIviDCPwr Ivi.DCPwr.Create(String resourceName,
Boolean idQuery,
Boolean reset,
LockType lockType,
String accessKey,
String options);
to build up an object-oriented communication with SCPI-devices. Since I really like C# I want to try this in the next weeks.
But I really can not see the connection settings since resourceName only seems to be a name to free the regarded device afterwards and the other settings were used when the connection is already set. How can an instance of IIviDCPwr know which connection (TCP/IP, COM or GPIB) should be used?
I've only seen solutions for TCP/IP by using sockets. But I think this is not applicable to COM and GPIB?
Another solution would be to use the National Instruments VISA-package. But I don't like the idea of using a proprietary package provided by NI (I think after using CVI I feel a newly developed repulsion towards NI).
Can you provide code snippets or documentations to handle this problem? Have you made any experiences by using VISA? Can I use sockets for COM/GPIB-communication?
BTW: How to create new lines in code snippets? Neither enter nor Shift + Enter, \r, \n, \ works for me...
You can use the .NET SerialPort and Socket (without using VISA) to communicate with your devices, by using their read/write methods. About GPIB, your hardware should have a .NET driver, with similar methods.
Some example of how to communicate with device using SerialPort (with some pseudo-SCPI)
SerialPort port = new SerialPort("COM1", 9600);
port.Open();
port.WriteLine(":DEVICE:OUT 1"); //turn on
port.WriteLine(":DEVICE:MEAS:VOLT?"); //measure voltage
float v = float.Parse(port.ReadLine()); //reading from device
Console.WriteLine("The measured voltage is " + v );
Now you can create classes of your devices, where every instance would have his own protocol (SerialPort, Socket, GPIB), and methods
public class SomeDevice
{
private SerialPort _port;
public SomeDevice(string serialPortName)
{
// do the connection work...
}
public void SetVoltage(float voltage)
{
port.WriteLine(":VOLT " + voltage.ToSring("N2"));
}
public float GetVoltage()
{
port.WriteLine(":DEVICE:MEAS:VOLT?");
return float.Parse(port.ReadLine()); //reading from device
}
}
You can even improve your classes to have the ability to use any kind of connection (SerialPort, Socket, GPIB...) by creating an interface (lets say - GenConnection) of general connection (with the common read/write methods), and then create child of your connection types implementing this interface - then each of your devices would have only GenConnection instance without "knowing" which kind of connection it realy is (just overload the constructor for each kind of connection)
Few points to keep in mind:
The programming manual help avoiding common errors
Connection configuration (baud, parity ...)
End of line character, you should keep in mind to send and separate readings
with the device end of line - usually <CR> or <CR><LF> ("\r" or "\r\n" in C#).
The SerialPort's ReadLine & WriteLine is doing it for you using the specified SerialPort's NewLine property
You can play with your port and socket using TeraTerm to see everything as expected
Related
I'm using a C# Process to run the following Java code with the java command:
public class Test {
public static void main(String[] args) throws Exception {
Thread.sleep(2000);
System.out.print("Hello worl\nd 1!");
Thread.sleep(2000);
System.out.println("Hello world 2!");
}
}
I'm using the following code to listen to the output:
run.OutputDataReceived += (_, args) => { /* handle output */ };
run.Start();
run.BeginOutputReadLine();
Ideally, OutputDataReceived should be fired twice, with the coressponding values for args.Data:
"Hello worl\nd 1!"
"Hello world 2!\n"
Instead, the newlines are used to determine when OutputDataReceived is fired. This ends up giving 3 calls to the event, with the corresponding values to args.Data:
"Hello worl"
"d 1!Hello world 2!"
null
How would I run code to handle output according to my first scenario (each time stdout is updated) instead of what is currently happening/the second scenario (whenever stdout receives a new line)? In addition, how would I do the same for stderr as well?
For anyone else with this problem, you can use this solution described in this answer to get live output.
I think what you want is impossible, and this is by design.
These text streams ain’t made of discrete messages, it’s a continuous stream of bytes very similar to a TCP socket.
If you control both producing and consuming sides of the stream, you can workaround by implementing some framing protocol on top of that stream. An easy way which might be good enough for you —separate messages with double newlines. This way, on the C# side you can write code which reads lines accumulating in a buffer, search for double newlines, when found or end of stream raise an event to handle a complete message, and unless end of stream move the remaining portion of the buffer to the start of the buffer.
Another workaround is using some other IPC mechanism instead of standard output. On Windows, named pipes support PIPE_TYPE_MESSAGE flag which causes the pipe to preserve message boundaries. Similarly, Linux kernel supports SOCK_DGRAM for Unix domain sockets. In both cases, a common design pattern looks like that: 1. Generate unique pipe/socket name in the parent C# process, for instance by generating a new GUID and printing that GUID. 2. Create the pipe or socket of that name. 3. Pass that name to the child Java process through a command-line argument, or an environment variable. 4. In the Java process, connect the pipe/socket by the name, you then have a message oriented two way communication channel between your two processes.
I've received some C# code from a colleague for interacting with a cRIO device connected over ethernet. I'm trying to improve the code quality to make it a bit more comprehensible for future users, however I'm struggling a little bit to extract some relevant information from the API documentation. My main question is whether there would be problems caused in leaving a NetworkVariableManager in the Connected state?
Right now the code uses a class which looks something like
public class RIOVar<T>
{
public readonly string location;
public RIOVar(string location)
{
this.location = location;
}
public T Get()
{
using(NetworkVariableReader<T> reader = new NetworkVariableReader<T>(location) )
{
reader.Connect();
return reader.ReadData().GetValue()
}
}
public void Write(T value)
{
using(NetworkVariableWriter<T> writer = new NetworkVariableWriter<T>(location) )
{
writer.Connect();
writer.WriteValue(value);
}
}
}
The actual class does a lot more than this, but the part that actually communicates with the cRIO basically boils down to these two methods and the location data member.
What I'm wondering about is whether it would be better to instead have reader and writer as class members and Connect them in the constructor (at the point that they are constructed the connection should be posible), but what I don't know is if this would have some adverse effect on the way the computer and RIO communicate with each other (maybe a connected manager uses some resource or the program must maintain some sort of register...?) and therefore the approach here of having the manager connected only for the read/write operation is better design.
Keeping a variable connected keeps its backing resources in memory:
threads
sockets
data buffers
These resources are listed in the online help, but it's unclear to me if that list is complete:
NationalInstruments.NetworkVariable uses multiple threads to implement the reading and writing infrastructure. When reading or writing in a tight loop insert a Sleep call, passing 0, to allow a context switch to occur thereby giving the network variable threads time to execute.
... snip ...
NationalInstruments.NetworkVariable shares resources such as sockets and data buffers among connections that refer to the same network variable in the same program.
In my opinion, I'd expect better runtime performance by connecting/disconnecting as infrequently as possible. For example, when the network is reachable, connect; when it isn't, disconnect.
So just a bit of context I have 2 devices that communicate with each other by rs232 with RTS/CTS and i need to replace one of the devices with my own device and software.
I am trying to achieve this by using the System.IO.Ports.SerialPort library that from what i could gather online this library handles the handshaking by itself if we set the RtsEnable property to "true" and the Handshake property to "RequestToSend" but I am facing some issues receiving data from the device.
When testing my software i am not being able to receive anything from the device but if I change the wiring to simply work as a sniffer between the two original devices I can receive the data properly. From what I can gather it must be something I am doing wrong to handle the handshaking.
Here is the code i am trying:
stationPort = new SerialPort(stationPortNumber, baudRate, parity, dataBits, stopBits);
stationPort.RtsEnable = true;
stationPort.Handshake = Handshake.RequestToSend;
stationPort.DataReceived += StationPort_DataReceived;
stationPort.Open();
private static void StationPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] bytes = new byte[20];
stationPort.Read(bytes, 0, stationPort.BytesToRead);
string hexConvert = BitConverter.ToString(bytes);
Console.WriteLine("Station OUT >>> " + hexConvert);
}
I also double checked the wiring to make sure it was properly connected and also changed the converter because sometimes these are not wired properly so I chose a MOXA UPort 1150 which is more reliable.
With that being said, my question is what am I doing wrong with my implementation?
Am I supposed to do more to guarantee the handshaking?
Possibly, The equipment you are using may be half-duplex.
In that case, in order to communicate with the SerialPort class of C#, it is necessary to set Handshake to None and control the ON/OFF of the RTS signal by the application program itself.
The SerialPort class API does not have that function.
Handshake Enum
When using the communication function of Win32API, communication may be possible by setting the fRtsControl flag to RTS_CONTROL_TOGGLE in DCB.
DCB structure
RTS_CONTROL_TOGGLE 0x03
Specifies that the RTS line will be high if bytes are available for transmission. After all buffered bytes have been sent, the RTS line will be low.
In any case, you will need to check the communication specifications of the device.
However, even if you are not sure, it may be better to try the above control a little in C#.
You may also want to try #baddack's comment.
As noted, the fact that the DTR signal (DSR for the other party) is ON may be the basis for determining that communication is possible.
In connection with that, are the signal lines cross-connected?
Are TxD/RxD, RTS/CTS, DTR/DSR cross-connected to each other?
Also check what you need to do with these specifications for your equipment.
I want to extend my experience with the .NET framework and want to build a client/server application.
Actually, the client/server is a small Point Of Sale system but first, I want to focus on the communication between server and client.
In the future, I want to make it a WPF application but for now, I simply started with a console application.
2 functionalities:
client(s) receive(s) a dataset and every 15/30min an update with changed prices/new products
(So the code will be in a Async method with a Thread.sleep for 15/30 mins).
when closing the client application, sending a kind of a report (for example, an xml)
On the internet, I found lots of examples but i can't decide which one is the best/safest/performanced manner of working so i need some advice for which techniques i should implement.
CLIENT/SERVER
I want 1 server application that handles max 6 clients. I read that threads use a lot of mb and maybe a better way will be tasks with async/await functionallity.
Example with ASYNC/AWAIT
http://bsmadhu.wordpress.com/2012/09/29/simplify-asynchronous-programming-with-c-5-asyncawait/
Example with THREADS
mikeadev.net/2012/07/multi-threaded-tcp-server-in-csharp/
Example with SOCKETS
codereview.stackexchange.com/questions/5306/tcp-socket-server
This seems to be a great example of sockets, however, the revisioned code isn't working completely because not all the classes are included
msdn.microsoft.com/en-us/library/fx6588te(v=vs.110).aspx
This example of MSDN has a lot more with Buffersize and a signal for the end of a message. I don't know if this just an "old way" to do this because in my previous examples, they just send a string from the client to the server and that's it.
.NET FRAMEWORK REMOTING/ WCF
I found also something about the remoting part of .NET and WCF but don' know if I need to implement this because i think the example with Async/Await isn't bad.
SERIALIZED OBJECTS / DATASET / XML
What is the best way to send data between it? Juse an XML serializer or just binary?
Example with Dataset -> XML
stackoverflow.com/questions/8384014/convert-dataset-to-xml
Example with Remoting
akadia.com/services/dotnet_dataset_remoting.html
If I should use the Async/Await method, is it right to something like this in the serverapplication:
while(true)
{
string input = Console.ReadLine();
if(input == "products")
SendProductToClients(port);
if(input == "rapport")
{
string Example = Console.ReadLine();
}
}
Here are several things anyone writing a client/server application should consider:
Application layer packets may span multiple TCP packets.
Multiple application layer packets may be contained within a single TCP packet.
Encryption.
Authentication.
Lost and unresponsive clients.
Data serialization format.
Thread based or asynchronous socket readers.
Retrieving packets properly requires a wrapper protocol around your data. The protocol can be very simple. For example, it may be as simple as an integer that specifies the payload length. The snippet I have provided below was taken directly from the open source client/server application framework project DotNetOpenServer available on GitHub. Note this code is used by both the client and the server:
private byte[] buffer = new byte[8192];
private int payloadLength;
private int payloadPosition;
private MemoryStream packet = new MemoryStream();
private PacketReadTypes readState;
private Stream stream;
private void ReadCallback(IAsyncResult ar)
{
try
{
int available = stream.EndRead(ar);
int position = 0;
while (available > 0)
{
int lengthToRead;
if (readState == PacketReadTypes.Header)
{
lengthToRead = (int)packet.Position + available >= SessionLayerProtocol.HEADER_LENGTH ?
SessionLayerProtocol.HEADER_LENGTH - (int)packet.Position :
available;
packet.Write(buffer, position, lengthToRead);
position += lengthToRead;
available -= lengthToRead;
if (packet.Position >= SessionLayerProtocol.HEADER_LENGTH)
readState = PacketReadTypes.HeaderComplete;
}
if (readState == PacketReadTypes.HeaderComplete)
{
packet.Seek(0, SeekOrigin.Begin);
BinaryReader br = new BinaryReader(packet, Encoding.UTF8);
ushort protocolId = br.ReadUInt16();
if (protocolId != SessionLayerProtocol.PROTOCAL_IDENTIFIER)
throw new Exception(ErrorTypes.INVALID_PROTOCOL);
payloadLength = br.ReadInt32();
readState = PacketReadTypes.Payload;
}
if (readState == PacketReadTypes.Payload)
{
lengthToRead = available >= payloadLength - payloadPosition ?
payloadLength - payloadPosition :
available;
packet.Write(buffer, position, lengthToRead);
position += lengthToRead;
available -= lengthToRead;
payloadPosition += lengthToRead;
if (packet.Position >= SessionLayerProtocol.HEADER_LENGTH + payloadLength)
{
if (Logger.LogPackets)
Log(Level.Debug, "RECV: " + ToHexString(packet.ToArray(), 0, (int)packet.Length));
MemoryStream handlerMS = new MemoryStream(packet.ToArray());
handlerMS.Seek(SessionLayerProtocol.HEADER_LENGTH, SeekOrigin.Begin);
BinaryReader br = new BinaryReader(handlerMS, Encoding.UTF8);
if (!ThreadPool.QueueUserWorkItem(OnPacketReceivedThreadPoolCallback, br))
throw new Exception(ErrorTypes.NO_MORE_THREADS_AVAILABLE);
Reset();
}
}
}
stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(ReadCallback), null);
}
catch (ObjectDisposedException)
{
Close();
}
catch (Exception ex)
{
ConnectionLost(ex);
}
}
private void Reset()
{
readState = PacketReadTypes.Header;
packet = new MemoryStream();
payloadLength = 0;
payloadPosition = 0;
}
If you're transmitting point of sale information, it should be encrypted. I suggest TLS which is easily enabled on through .Net. The code is very simple and there are quite a few samples out there so for brevity I'm not going to show it here. If you are interested, you can find an example implementation in DotNetOpenServer.
All connections should be authenticated. There are many ways to accomplish this. I've use Windows Authentication (NTLM) as well as Basic. Although NTLM is powerful as well as automatic it is limited to specific platforms. Basic authentication simply passes a username and password after the socket has been encrypted. Basic authentication can still, however; authenticate the username/password combination against the local server or domain controller essentially impersonating NTLM. The latter method enables developers to easily create non-Windows client applications that run on iOS, Mac, Unix/Linux flavors as well as Java platforms (although some Java implementations support NTLM). Your server implementation should never allow application data to be transferred until after the session has been authenticated.
There are only a few things we can count on: taxes, networks failing and client applications hanging. It's just the nature of things. Your server should implement a method to clean up both lost and hung client sessions. I've accomplished this in many client/server frameworks through a keep-alive (AKA heartbeat) protocol. On the server side I implement a timer that is reset every time a client sends a packet, any packet. If the server doesn't receive a packet within the timeout, the session is closed. The keep-alive protocol is used to send packets when other application layer protocols are idle. Since your application only sends XML once every 15 minutes sending a keep-alive packet once a minute would able the server side to issue an alert to the administrator when a connection is lost prior to the 15 minute interval possibly enabling the IT department to resolve a network issue in a more timely fashion.
Next, data format. In your case XML is great. XML enables you to change up the payload however you want whenever you want. If you really need speed, then binary will always trump the bloated nature of string represented data.
Finally, as #NSFW already stated, threads or asynchronous doesn't really matter in your case. I've written servers that scale to 10000 connections based on threads as well as asynchronous callbacks. It's all really the same thing when it comes down to it. As #NSFW said, most of us are using asynchronous callbacks now and the latest server implementation I've written follows that model as well.
Threads are not terribly expensive, considering the amount of RAM available on modern systems, so I don't think it's helpful to optimize for a low thread count. Especially if we're talking about a difference between 1 thread and 2-5 threads. (With hundreds or thousands of threads, the cost of a thread starts to matter.)
But you do want to optimize for minimal blocking of whatever threads you do have. So for example instead of using Thread.Sleep to do work on 15 minute intervals, just set a timer, let the thread return, and trust the system to invoke your code 15 minutes later. And instead of blocking operations for reading or writing information over the network, use non-blocking operations.
The async/await pattern is the new hotness for asynchronous programming on .Net, and it is a big improvement over the Begin/End pattern that dates back to .Net 1.0. Code written with async/await is still using threads, it is just using features of C# and .Net to hide a lot of the complexity of threads from you - and for the most part, it hides the stuff that should be hidden, so that you can focus your attention on your application's features rather than the details of multi-threaded programming.
So my advice is to use the async/await approach for all of your IO (network and disk) and use timers for periodic chores like sending those updates you mentioned.
And about serialization...
One of the biggest advantages of XML over binary formats is that you can save your XML transmissions to disk and open them up using readily-available tools to confirm that the payload really contains the data that you thought would be in there. So I tend to avoid binary formats unless bandwidth is scarce - and even then, it's useful to develop most of the app using a text-friendly format like XML, and then switch to binary after the basic mechanism of sending and receiving data have been fleshed out.
So my vote is for XML.
And regarding your code example, well ther's no async/await in it...
But first, note that a typical simple TCP server will have a small loop that listens for incoming connections and starts a thread to hanadle each new connection. The code for the connection thread will then listen for incoming data, process it, and send an appropriate response. So the listen-for-new-connections code and the handle-a-single-connection code are completely separate.
So anyway, the connection thread code might look similar to what you wrote, but instead of just calling ReadLine you'd do something like "string line = await ReadLine();" The await keyword is approximately where your code lets one thread exit (after invoking ReadLine) and then resumes on another thread (when the result of ReadLine is available). Except that awaitable methods should have a name that ends with Async, for example ReadLineAsync. Reading a line of text from the network is not a bad idea, but you'll have to write ReadLineAsync yourself, building upon the existing network API.
I hope this helps.
I am using a program that talks to my COMM port, but I have made another program that I want to "sniff" the comm port messages and perform it's own actions against those messages in addition. Is this possible in .NET c#?
There are third party libraries/tools/products that expose the traffic f you are interested.
Here is one I used for serial port emulation - but I think it provides something you can use:
http://com0com.sourceforge.net/
If you have control over the first program that talks to you COMM port, why not change the program to pass data received from the port to the 2nd program of yours via remoting or any other type of IPC. Better still if you can write a proxy program that connected to the COMM port, and have 2 of the other program talk to this proxy to get the communication done.
Another idea is, if you need to sniff only incoming data, you can get a Y-cable (splitter) and connect to 2 COMM port, each program connects to each COMM port. But you need to make sure the 2nd program is not trying to transmit. In some cases you might need a splitter which only connects the RX pin for the 2nd output. Let me know if you need the diagram.
If you don't have 2 COMM, you can easily get a USB-Serial Converter for less than USD10.
It is possible to sniff traffic from the serial port
However there doesnt seem to be a "COMPortSniffer" Control
A valid technique used by sysinternals is presented there
It seems to rely on Win32 programming however, I dont think such a thing is possible directly with C#
the code project (http://www.codeproject.com/Articles/75770/Basic-serial-port-listening-application) that has a great tutorial on this.
It shows how to read data coming in from a serial port, and from that you should be able to read the data.
A short snippet:
void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int dataLength = _serialPort.BytesToRead;
byte[] data = new byte[dataLength];
int nbrDataRead = _serialPort.Read(data, 0, dataLength);
if (nbrDataRead == 0)
return;
// Send data to whom ever interested
if (NewSerialDataRecieved != null)
NewSerialDataRecieved(this, new SerialDataEventArgs(data));
}