C# Visual Studio GPIB Commands - c#

What commands do you use to talk to a GPIB instrument in C#, visual studio?
I need to be able to write commands to the instrument and read the output.

I use Agilent IO Library Suite.
Here is a tutorial to use it on C#: I/O programming examples in C#
Nevertheless, in my company we had stability issues with the VISA-COM implementation, so we wrote our own wrapper around the visa32.dll (also part of the IO Library suite) using P/Invoke.
(Disclosure: I work in a company that make intense use of GPIB instruments)

I'm using National Instruments VISA and NI 488.2.
First make sure that you checked the VisaNS.NET API in the NI-VISA Setup, see the following figure:
Add a reference to NationalInstruments.VisaNS and NationalInstruments.Common to your project.
Create a MessageBasedSession, see the following code:
string resourceName = "GPIB0::20::INSTR"; // GPIB adapter 0, Instrument address 20
var visa = new NationalInstruments.VisaNS.MessageBasedSession(resourceName);
visa.Write("*IDN?"); // write to instrument
string res = visa.ReadString(); // read from instrument
A MessageBasedSession can be used to communicate with your instrument over GPIB, Ethernet or USB.
Update
Ivi.Visa superseded NationalInstruments.VisaNS. So you should add a reference only to Ivi.Visa to your project.
The example would look like that:
string resourceName = "GPIB0::20::INSTR"; // GPIB adapter 0, Instrument address 20
var visa = GlobalResourceManager.Open(resourceName) as IMessageBasedSession;
visa.RawIO.Write("*IDN?\n"); // write to instrument
string res = visa.RawIO.ReadString(); // read from instrument
The benefit of using Ivi.Visa is that it works with one of the following libraries:
National Instruments VISA
Keysight IO Libraries Suite
Rohde & Schwarz VISA

Send commands out the serial port.
See Microsoft's COM Port Example.

You should create an object with LangInt class first. Then use that object with GPIB methods.
Most common and used ones are(assuming you created an object named "dev");
dev.ibwrt(deviceHandle, "*IDN?", "*IDN?".Length);
dev.ibrd(deviceHandle, out Value, Arraysize);
These two can query the device. Or you can use them consecutively for example setting a generator's frequency and then it's amplitude.
Important part is before sending SCPI commands; you MUST initialize devices first. To do this use;
deviceHandle = ibdev(GPIBINDEX, GPIBADDRESS, SECONDARYADDRESS, TIMEOUT, EOTMODE, EOSMODE);
These parameters must declared first within the code. After initialization you can use every GPIB command with that device handles.
And of course you should add NationalInstruments.NI4882 and LangInt.dll to your project.

You can use NI Visa.
If you are using Vb or C# use Visa32.bas or Visa32.cs from the sample programs disk
int DefaultSessionId= 0;
int SessionId= 0;
int LastStatus = 0;
string Address = "GPIB0::6" ; //any address
//Session Open
LastStatus = visa32.viOpenDefaultRM(out DefaultSessionId);
//Connection Open
LastStatus = visa32.viOpen(DefaultSessionId, Address + "::INSTR", 0, 0, out sessionId);
LastStatus = visa32.viSetAttribute(SessionId, visa32.VI_ATTR_TERMCHAR, 13);// Set the termination character to carriage return (i.e., 13);
LastStatus = visa32.viSetAttribute(SessionId, visa32.VI_ATTR_TERMCHAR_EN, 1);// Set the flag to terminate when receiving a termination character
LastStatus = visa32.viSetAttribute(SessionId, visa32.VI_ATTR_TMO_VALUE, 2000);// Set timeout in milliseconds; set the timeout for your requirements
//Communication
LastStatus = visa32.viPrintf(SessionId, command + "\n");//device specific commands to write
StringBuilder message = new StringBuilder(2048);
LastStatus = visa32.viScanf(SessionId, "%2048t", message);//Readback
//Session and Connection Close
visa32.viClose(SessionId);
visa32.viClose(DefaultSessionId);
Reference

Related

Why is reading from IBM MQ queue extremely slow using .NET standard library? (unlike .NET)

I wrote a console app on .NET, to read without consuming the messages from an IBM MQ queue.
Worked perfect.
Now, I need to migrate that app into .NET Core. Can't figure out why it is extremely slow.
How it works:
target framework .NET Core 3.1
IBMMQDotNetClient NuGet package installed
created a helper class, static, with a static constructor where I initialise MQEnvironment properties like so:
MQEnvironment.CertificateLabel = "ibmwebsphere"; // this is the friendlyname on mmc certificate
MQEnvironment.SSLKeyRepository = "*SYSTEM";
added a method called Init where I initialise connection to MQManager like so:
Hashtable properties = new Hashtable();
properties.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
properties.Add(MQC.HOST_NAME_PROPERTY, hostName); // I read the hostName from a config file
properties.Add(MQC.PORT_PROPERTY, port); // I read the port from a config file
properties.Add(MQC.CHANNEL_PROPERTY, channelName); // I read the channel from a config file
properties.Add(MQC.SSL_CIPHER_SPEC_PROPERTY, cipherSpec); // I read the cipher spec from a config file, it's something like TLS_RSA_WITH_AES_256_CBC_SHA256
Then, I'm going to create a connection to the queue manager using the connection, and read messages one by one until coming to end of the queue.
var queueManager = new MQQueueManager(qm, properties); // I read the qm from a config file
var queue = queueManager.AccessQueue(queueName, MQC.MQOO_BROWSE + MQC.MQOO_FAIL_IF_QUIESCING); // I read the queueName from a config file
var mqGMO = new MQGetMessageOptions();
mqGMO.Options = MQC.MQGMO_FAIL_IF_QUIESCING + MQC.MQGMO_NO_WAIT + MQC.MQGMO_BROWSE_NEXT; mqGMO.MatchOptions = MQC.MQMO_NONE;
try {
while (true) {
MQMessage queueMessage = new MQMessage();
queue.Get(queueMessage, mqGMO); // code gets apparently stuck on this line,
// overprocessing, for many minutes until it gets to the next line,
// even though I mentioned "NO_WAIT" in the options.
// Note this only happens for .NET Core, but not in .NET framework.
var message = queueMessage.ReadString(queueMessage.MessageLength);
string fileName = message.Substring(0,3); // some processing here to extract some info from each message
}
}
catch(MQException ex)
{
if(err.ReasonCode.CompareTo(MQC.MQRC_NO_MSG_AVAILABLE) == 0)
{
// harmless exception to indicate there are no messages on the queue
}
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
Of course it would be preferable to use a listener, not sure how to do that yet, it would be part of optimising, but for now - why is working so slow on line:
queue.Get(queueMessage, mqGMO); // but, again, as mentioned, only with the amqmdnetstd.dll (.NET Core), because if I use amqmdnet.dll (.NET framework), it works super fast, and it's supposed to be the other way around.
I do need to use .NET Standard/Core because I will run this in Linux, currently testing in Windows.
Don't use the MQEnvironment class as it is not threaded safe. Also, don't mix and match between MQEnvironment class and using MQ HashTable. Put your SSL/TLS information as a property in the MQ HashTable.
i.e.
properties.Add(MQC.SSL_PEER_NAME_PROPERTY, "ibmwebsphere");
properties.Add(MQC.SSL_CERT_STORE_PROPERTY, "*SYSTEM");
There isn't enough of your code to test to see why it might be failing.
I wrote and posted a blog item called: IBM MQ For .NET Core Primer. In the blog post, I included a fully functioning C# MQ example (MQTest62L.cs) that was built and run using .NET Core v3.1 and everything worked perfectly (see very bottom of post). Hence, I would suggest you follow my instructions, download, compile and run MQTest62L.cs to see if the issue is your code or MQ Client library.
Note: I was using Windows 10 Pro, IBM MQ v9.2.0.0 and .NET Core v3.1.415.

How to release serial COM port from dll

I'm using .dll to in my code so i create object for that, in which .dll open the serial com port but after use it not release the comport. but in my application i want to open comport again but comport occupied by the .dll so it gives error.
please give the solution.
Your tags got it right - this is the Dispose pattern. The class you are looking for is propably SerialPort:
https://learn.microsoft.com/en-us/dotnet/api/system.io.ports.serialport
You should be using the using Syntax to make sure it is closed. C# 8 even has a new, simpler one for limited scope variables.
The tags confuse me a bit:
on the one hand, it can be beneficial to keep such a port open and use the DataReceived() event to react to incomming stuff. In that case the Dispose point depends on the Display technology used/kind of Application.
But you also got the ASP.Net tag. And keeping stuff open and ASP.Net do not mix that good. Nevermind the part where COm Ports are not usually controled from a Web Application.
As you said you are using it only for a single write operation, this is the slight modification to the sample code:
// Create a new SerialPort object with default settings.
//make a local variable for this
using (var _serialPort = new SerialPort()){
// Allow the user to set the appropriate properties.
_serialPort.PortName = SetPortName(_serialPort.PortName);
_serialPort.BaudRate = SetPortBaudRate(_serialPort.BaudRate);
_serialPort.Parity = SetPortParity(_serialPort.Parity);
_serialPort.DataBits = SetPortDataBits(_serialPort.DataBits);
_serialPort.StopBits = SetPortStopBits(_serialPort.StopBits);
_serialPort.Handshake = SetPortHandshake(_serialPort.Handshake);
// Set the read/write timeouts
_serialPort.ReadTimeout = 500;
_serialPort.WriteTimeout = 500;
_serialPort.Open();
//Do stuff with the open port
}
//using has it Disposed when you get here. Or otherwise leave the block

How to send data from C# to Python

How can i send this list to list in Python script? This is so big for sending as arguments. Thank you.
List<String> cefList= new List<String>();
for(int i=0; i<1000; i++){
cefList.Add("CEF:0|ArcSight|ArcSight|6.0.3.6664.0|agent:030|Agent [test] type [testalertng] started|Low|
eventId=1 mrt=1396328238973 categorySignificance=/Normal categoryBehavior=/Execute/Start
categoryDeviceGroup=/Application catdt=Security Mangement categoryOutcome=/Success
categoryObject=/Host/Application/Service art=1396328241038 cat=/Agent/Started
deviceSeverity=Warning rt=1396328238937 fileType=Agent
cs2=<Resource ID\="3DxKlG0UBABCAA0cXXAZIwA\=\="/> c6a4=fe80:0:0:0:495d:cc3c:db1a:de71
cs2Label=Configuration Resource c6a4Label=Agent
IPv6 Address ahost=SKEELES10 agt=888.99.100.1 agentZoneURI=/All Zones/ArcSight
System/Private Address Space
Zones/RFC1918: 888.99.0.0-888.200.255.255 av=6.0.3.6664.0 atz=Australia/Sydney
aid=3DxKlG0UBABCAA0cXXAZIwA\=\= at=testalertng dvchost=SKEELES10 dvc=888.99.100.1
deviceZoneURI=/All Zones/ArcSight System/Private Address Space Zones/RFC1918:
888.99.0.0-888.200.255.255 dtz=Australia/Sydney _cefVer=0.1");
}
Since your C# program runs the python script, I guess the easiest solution would be to redirect the standard input of the python process:
Process pyProc = Process.Start(
new ProcessStartInfo("python.exe", #"/path/to/the/script.py")
{
RedirectStandardInput = true,
UseShellExecute = false
}
);
for (int ii = 0; ii < 100; ++ii)
{
pyProc.StandardInput.WriteLine(string.Format("this is message # {0}", ii));
}
At the python script side, you just need to use built-in function raw_input like below (please note the function has been renamed to raw_input in 3.x):
while True:
data = raw_input()
print(data)
You need to serialize the data to a common format that is accessible from both C# and Python. For example - XML or JSON. I would recommend using JSON.
Then you have several options:
Use sockets to transfer the data.
Use http to transfer the data.
Write to a file from C# and read that file from Python
Sockets would probably be faster. Using http might be easier. With files, you will need to have some sort of scheduling or notification system to let your Python program know when you have written to the file.

PcapDotNet and Datalink type

I'm trying to manipulate some network captures (pcap format) using Pcap.net.
I'm opening the pcap file and creating the dumper with:
OfflinePacketDevice selectedDevice = new OfflinePacketDevice(pcapInFile);
using (PacketCommunicator PcapReader = selectedDevice.Open(655360, PacketDeviceOpenAttributes.Promiscuous, 1000))
{
PacketDumpFile PcapWriter = PcapReader.OpenDump(pcapOutFile);
PcapReader.ReceivePackets(count, PacketDispatcher);
}
And the PacketDispatcher would be something like:
private void PacketDispatcher(Packet packet)
{
// Manipulate the packet
PcapWriter.Dump(packet);
}
Everything is ok as far as the pcapInFile Datalink is ethernet type. But i have several captures without ethernet layer (rawip) and i have to build a new ethernet layer. In this kind of caps the datalink type is the same as the pcapInFile (raw ip) and i want to change it to ethernet...
If i store all the manipulated packets in a ienumerable and dump them with:
PacketDumpFile.Dump(pcapOutFile, new PcapDataLink(1), Packets.Count(), Packets);
It works fine... But, this is not very useful if you are dealing with files of several gigas...
Any idea?
Thanks!
Assuming the concern is about having all packets in RAM, you can create an IEnumerable that doesn't contain everything in RAM using yield.
This way as Dumper dumps packets it will call your method to populate the next item using yield.
Well, despite this is not an answer but a workaround, and since nobody wrote a better solution this is how a fixed it:
Use SharPcap instead of PcapDotNet, then you can declare a reader and a writer this way:
public CaptureFileReaderDevice PcapReader;
public CaptureFileWriterDevice PcapWriter;
PcapReader = new CaptureFileReaderDevice(fileIn);
PcapReader.OnPacketArrival += packetDispatcher;
PcapReader.Capture();
In the packetDispatcher function:
RawCapture raw = new RawCapture(LinkLayers.Ethernet, e.Packet.Timeval,RebuildNullLinkLayer(e, offset));
CaptureHandler.PcapWriter.Write(raw);
And in the RebuildNullLinkLayer function you can add the ethernet layer, modify whatever you want, etc...
Note that when you call the RawCapture Constructor you can choose the Link Layer (mi original issue with Pcap.Net...), so if you are parsing a RawIp capture, you can convert the packets to Ethernet.

MongoDB C# driver: connection string for sharding over replica set

I need to setup sharding over replica set as recommended in MongoDB reference for high availability & scalability. I have few questions about connection string and its behavior for C# driver in that scenario (code snippet below):
Is the connection string below looks right for connecting to mongos instances: mongos1, mongos2 & mongos3?
What happens to client if one of the mongos instance crashes? Will the failed call handled gracefully by retrying to second mongos instance? Does the client blacklist the failed mongos instance and try after sometime?
If I want to set readpreference, will the driver be aware of replica set existence and honor setting ReadPreference?
Code snippet:
MongoUrlBuilder bldr = new MongoUrlBuilder();
List<MongoServerAddress> servers = new List<MongoServerAddress>();
servers.Add(new MongoServerAddress("mongos1:27016"));
servers.Add(new MongoServerAddress("mongos2:27016"));
servers.Add(new MongoServerAddress("mongos3:27016"));
bldr.Username = "myuser";
bldr.Password = "mypwd";
bldr.Servers = servers;
bldr.DatabaseName = "mydb";
bldr.ReadPreference = ReadPreference.Primary;
var server = MongoServer.Create(bldr.ToMongoUrl());
1) Yes, this is just fine. Note that all of this could be put in an actual connection string as well. mongodb://myuser:mypwd#mongos1:27016,mongos2:27016,mongos3:27016/mydb/?readPreference=primary
2) The way your connection string is built, you'll be load balancing across the 3 mongos. If one goes down, then the other two will simply begin to receive more traffic. Errors, however, will happen and nothing gets retried automatically. You'll need to handle the errors and make decisions based on each query/write whether it is safe to retry.
3) The driver, when talking to a sharded system, will simply forward the read preference to mongos. Note that mongos version 2.2 had some difficulty with read preferences. I'd advise you to be on the 2.4 line.

Categories