get the port no where gsm modem is connected using C# - c#

I am planning to send sms using a modem in C# from an asp.net application.As the project will be
integrated to another project it wont be having any field for user input to enter the com port.How can i get the port number where my modem in connected from C#.
Thanks,
Sagar.

To check that a modem is connected to particular port you can send AT command into this port.
This function below returns true if we found a modem on the current COM port:
private bool CheckExistingModemOnComPort(SerialPort serialPort)
{
if ((serialPort == null) || !serialPort.IsOpen)
return false;
// Commands for modem checking
string[] modemCommands = new string[] { "AT", // Check connected modem. After 'AT' command some modems autobaud their speed.
"ATQ0" }; // Switch on confirmations
serialPort.DtrEnable = true; // Set Data Terminal Ready (DTR) signal
serialPort.RtsEnable = true; // Set Request to Send (RTS) signal
string answer = "";
bool retOk = false;
for (int rtsInd = 0; rtsInd < 2; rtsInd++)
{
foreach (string command in modemCommands)
{
serialPort.Write(command + serialPort.NewLine);
retOk = false;
answer = "";
int timeout = (command == "AT") ? 10 : 20;
// Waiting for response 1-2 sec
for (int i = 0; i < timeout; i++)
{
Thread.Sleep(100);
answer += serialPort.ReadExisting();
if (answer.IndexOf("OK") >= 0)
{
retOk = true;
break;
}
}
}
// If got responses, we found a modem
if (retOk)
return true;
// Trying to execute the commands without RTS
serialPort.RtsEnable = false;
}
return false;
}
On the next stage we can collect some data from the modem.
ATQ0 - switch on confirmations (receive OK on each request)
ATE0 - switch on echo
ATI - get modem details
ATI3 - get extended modem details (not all modems supports this command)

Related

C# Modbus: ReadHoldingRegisters not consistent in returning ouput

I'm trying to search for a modbus that is connected to a serial port on my device and run some commands against it. However it seems to be that it is rather inconsistent at reading the holding registers. I'm using the NModbus4 library.
I have a thread running every second that checks for available serial ports and tries to get a connection:
// === Check if port is open, start connecting procedure if closed
if (!(serialPort.IsOpen))
{
List<string> portnames = new List<string>();
foreach (string s in SerialPort.GetPortNames())
{
portnames.Add(s); // COM3
}
// === Loop through the listed ports and try to connect
foreach (string portname in portnames)
{
if (!(serialPort.IsOpen))
{
try
{
serialPort.PortName = portname;
serialPort.BaudRate = 57600;
serialPort.DataBits = 8;
serialPort.Parity = Parity.None;
serialPort.StopBits = StopBits.Two;
serialPort.Open();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
// === Check again after connecting procedure if the port is open
if (serialPort.IsOpen)
{
// === Check number of open ports
if (SerialPort.GetPortNames().Count() != 0)
{
// === Check if master is defined
if (master == null)
{
// === Define master
master = ModbusSerialMaster.CreateRtu(serialPort);
}
// === If master is already defined
if (master != null)
{
int parameterID = this.readParameterSetID();
if (parameterID != 0)
{
if (!desk_devices.Contains(parameterID))
{
desk_devices.Add(parameterID);
newDevice = true;
}
}
}
} else
{
// === No serial ports available, close the opened serial port
serialPort.Close();
}
}
The readParameterSetID function is as following:
private int readParameterSetID()
{
int parameterSetID = 0;
if (mutex)
{
Console.WriteLine("---Poll overrun----");
}
mutex = true;
if (serialPort.IsOpen)
{
if (master != null)
{
try
{
ushort[] holding_register = master.ReadHoldingRegisters(1, 107, 1); // Fails here
for (int i = 0; i < 1; i++)
{
int tmpStart = Convert.ToInt32(107 + i);
String tempStart = Convert.ToString(tmpStart, 16);
int tmpReg = Convert.ToInt32(holding_register[i]);
String tempReg = Convert.ToString(tmpReg, 16);
parameterSetID = holding_register[i];
}
} catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
mutex = false;
return parameterSetID;
}
Now the weird thing happening here is that the readParameterSetID function should return a 7 or a 0 when executed correctly. However sometimes it just stops after reading the holding registers. mutex will stay true and nothing gets returned. When I reboot the application it either works or the same thing happens again.
I don't know why it's working in 50% of the situations and the other 50% returns nothing. I've tried to redefine the master if the function readParameterSetID fails, however I noticed that once every couple second the master will be reset resulting in commands further down the line not being send.
I'd love to know why this is happening or a way to fix this and read the holding registers without the communication failing.

Connecting to NI USB to 232/4 failure

Currently trying to send basic messages through an NI USB-232/4 to a power supply. While connecting with my code, the messages will not get sent through, and the PORT led remains red/orange.
When connecting with the power supply's code, messages can be received perfectly fine, the PORT led turns green. The power supply reacts to commands given.
When connecting the supplied program trough virtual serial ports to a terminal, the messages sent are identical to the messages my program is sending. When input directly from a terminal window to the power supply, the commands work fine. Again, the port led turns green while connecting through the terminal.
The serial settings, as far as I can tell, are identical to those that both the supplied program and the terminal are using. However, the power supply refuses to accept the messages.
public Serial(){
ThreadSafe.serialVoltage.Enqueue("*IDN?");
ThreadSafe.serialVoltage.Enqueue("SYST:REM\n");
ThreadSafe.serialVoltage.Enqueue("INST SECO");
ThreadSafe.serialVoltage.Enqueue("OUTP 1");
ThreadSafe.serialVoltage.Enqueue("VOLT 9V");
}
public void ListenForVoltageChange()
{
string result;
_serialPort = new System.IO.Ports.SerialPort();
OpenPort();
Thread.Sleep(1000);
while (true) {
if (!ThreadSafe.serialVoltage.IsEmpty) {
ThreadSafe.serialVoltage.TryDequeue(out result);
Debug.WriteLine(result);
_serialPort.WriteLine(result);
}
Thread.Sleep(1000);
}
}
public bool OpenPort()
{
Debug.WriteLine("Port Open");
Debug.WriteLine(_serialPort.IsOpen);
if (!_serialPort.IsOpen)
{
_serialPort.PortName = "COM4";
_serialPort.BaudRate = 9600;
_serialPort.Parity = System.IO.Ports.Parity.None;
_serialPort.DataBits = 8;
_serialPort.StopBits = System.IO.Ports.StopBits.One;
_serialPort.RtsEnable = false;
_serialPort.Handshake = System.IO.Ports.Handshake.None;
_serialPort.ReadTimeout = 500;
_serialPort.WriteTimeout = 500;
try
{ _serialPort.Open(); }
catch { return false; }
}
return true;
}

C# UdpSocket starts receiving after send and stops receiving after a few packages

I'm trying to receive data via an UdpSocket from a multicast address.
The Socket doesn't receive data, before I sent data over the socket. After sending, i can receive a few packages, and then i have to send again, before I can receive more packages. Packages meanwhile sent from other hosts are lost.
I think, it isn't a firewall issue like here: C# UDP Socket doesn't receive data until after data is sent because whireshark receives all packages. Can somebody explain me this behavior?
class Program
{
private static UdpClient _mdnsSocket;
private static IPEndPoint _mdnsGroup;
private static IPEndPoint _localEp;
static void Main(string[] args)
{
var interfaces = NetworkInterface.GetAllNetworkInterfaces()
.Where(i => i.OperationalStatus == OperationalStatus.Up)
.ToArray();
for (int i = 0; i < interfaces.Length; ++i)
{
var interf = interfaces[i];
Console.WriteLine("{0}) Name: {1}", i, interf.Name);
}
Console.WriteLine();
do
{
int i;
Console.Write("Interface: ");
var line = Console.ReadLine();
if (int.TryParse(line, out i) && i < interfaces.Length)
{
var addr = interfaces[i].GetIPProperties()
.UnicastAddresses.FirstOrDefault(a => a.Address.AddressFamily == AddressFamily.InterNetwork);
if (addr != null)
{
_localEp = new IPEndPoint(addr.Address, 5353);
Console.WriteLine("Choosen IP: {0}", _localEp);
}
}
} while (_localEp == null);
_mdnsGroup = new IPEndPoint(IPAddress.Parse("224.0.0.251"), 5353);
_mdnsSocket = new UdpClient();
_mdnsSocket.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_mdnsSocket.ExclusiveAddressUse = false;
_mdnsSocket.Client.Bind(_localEp);
_mdnsSocket.JoinMulticastGroup(_mdnsGroup.Address, _localEp.Address);
BeginReceive();
Console.WriteLine("1 to switch to multicast mode (default)");
Console.WriteLine("2 to switch to unicast mode");
Console.WriteLine("s for sending a message");
Console.WriteLine("ESC for exit");
ConsoleKey key;
IPEndPoint ip = _mdnsGroup;
IPEndPoint unicastip = null;
var mode = "multicast";
do
{
Console.Write("1/2/s/ESC: ");
key = Console.ReadKey().Key;
Console.WriteLine();
switch (key)
{
case ConsoleKey.D1:
ip = _mdnsGroup;
Console.WriteLine("Switched to multicast mode");
mode = "multicast";
break;
case ConsoleKey.D2:
Console.Write("Enter new IP (leave empty to use {0}):", unicastip);
var input = Console.ReadLine();
if (string.IsNullOrEmpty(input))
{
if (unicastip == null)
{
Console.WriteLine("error: no last ip!");
break;
}
ip = unicastip;
Console.WriteLine("Switched to unicast mode");
mode = "unicast";
}
else
{
unicastip = new IPEndPoint(IPAddress.Parse(input), 5353);
ip = unicastip;
Console.WriteLine("Switched to unicast mode");
mode = "unicast";
}
break;
case ConsoleKey.S:
var msg = string.Format("Hello from PC via {0}", mode);
var bytes = Encoding.ASCII.GetBytes(msg);
Console.WriteLine("Sending to {0}", ip);
_mdnsSocket.Send(bytes, bytes.Length, ip);
break;
}
} while (key != ConsoleKey.Escape);
_mdnsSocket.Close();
}
private static void BeginReceive()
{
Console.WriteLine("BeginReceive");
_mdnsSocket.BeginReceive(ReceiveCallback, _mdnsSocket);
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
var ep = new IPEndPoint(IPAddress.Any, _mdnsGroup.Port);
var data = _mdnsSocket.EndReceive(ar, ref ep);
var message = Encoding.ASCII.GetString(data);
Console.WriteLine(message);
}
finally
{
BeginReceive();
}
}
}
After all it seems it was a firewall issue. When I allow incoming UPD on Port 5353 explicitly, it's working (Why ever allowing all incoming UPD Traffic for the respective program doesn't work). I now explain the behavior described in the question with the so called hole punching mechanism. Please correct me when I'm wrong.
Same problem here, but firewall didn't fixed it. I'm using Windows 10 PRO.
There is another undesired effect I have found: broadcasted messages are not being received, but straight IP messages are.
The only workaround I've found was to add a timer that sends an empty byte array in broadcast every 10 seconds, so the communication is maintained well enough.
The problem is that there are always useless messages transferred to the network, not so heavy, but far from optimal.
Closing the socket and starting again fixes also the problem, but it's slower, and forces the GC to run.
I'm using the same UDP class on Unity (Mono) and Visual Studio applications, but this "effect" only happens under Unity applications.
This only happens on IPV4 sockets, IPV6 sockets seems to never stop listening.
I'm sure this is some kind of "Stop using IPV4 broadcast" feature in new OS's, because Windows 7 works just fine.
Hope it helps.

Reconnecting to COM after lost connection

I cannot reconnect to COM port after device on the other end abruptly drops connection.
I can connect again only if I close and re-open the application.
Here is my connection function:
public bool connectTurboPump()
{
try
{
if (TPumpSerialPort != null && TPumpSerialPort.IsOpen == true)
return true;
DataRow dr = tblTPump.Rows[0];
Types.Connection TPumpConnection = new Types.Connection();
TPumpConnection.PORT = dr["port"].ToString();
TPumpConnection.BAUD_RATE = Convert.ToInt32(dr["baud"]);
TPumpConnection.PARITY = (Parity)Enum.Parse(typeof(Parity), dr["parity"].ToString(), true);
TPumpConnection.DATA_BITS = Convert.ToInt32(dr["dataBits"]);
TPumpConnection.STOP_BITS = (StopBits)Enum.Parse(typeof(StopBits), dr["stopBits"].ToString(), true);
TPumpConnection.HANDSHAKE = (Handshake)Enum.Parse(typeof(Handshake), dr["handshake"].ToString(), true);
TPumpSerialPort = new SerialPort(TPumpConnection.PORT, TPumpConnection.BAUD_RATE, TPumpConnection.PARITY, TPumpConnection.DATA_BITS, TPumpConnection.STOP_BITS);
TPumpSerialPort.Handshake = TPumpConnection.HANDSHAKE;
TPumpSerialPort.Open();
TPumpSerialPort.NewLine = "\r";
TPumpSerialPort.ReadTimeout = 10000;
TPumpSerialPort.WriteTimeout = 10000;
if (TPumpSerialPort.IsOpen != true)
return false;
return true;
}
catch { return false; }
}
And here is my re-connection function:
public bool reconnectTurboPump(int attempts = 3)
{
try
{
if (TPumpSerialPort != null && TPumpSerialPort.IsOpen == true)
{
TPumpSerialPort.Close();
TPumpSerialPort.Dispose();
}
int i = 1;
while (true)
{
Log(string.Format("Reconnecting Turbo Pump attempt {0}", i));
if (connectTurboPump())
break;
if (i == attempts)
return false;
i++;
}
return true;
}
catch (Exception ex)
{
Log(string.Format("Could not reconnect to Turbo Pump: {0}", ex.Message));
return false;
}
}
Would really appreciate if someone could help.
Thank you.
This doesn't make much sense if this is a true serial port connection. There is no "connected" state, serial ports are very simple devices that have no underlying protocol that establishes a connection.
If this is actually a USB device that emulates a serial port then you'll indeed have this kind of problem. The driver that emulates the serial port invariably gets very sulky when you unplug the USB connector while the port is in use. There actually is a connection protocol for USB devices, the negotiation is done by the driver. They most typically make the port just disappear, this tends to give user code a heart-attack from which it can't recover. Behavior is very unpredictable and varies from one driver to another. There is no cure for this, glue the connector to the port and never assume that unplugging it will solve any problems in your code, even though that's the only thing you can do with USB.
Following Thomas' advice I've changed reconnection script to the following. Now in testing.
public bool reconnectTurboPump(int attempts = 3)
{
try
{
//if (TPumpSerialPort != null && TPumpSerialPort.IsOpen == true)
if (TPumpSerialPort != null)
{
TPumpSerialPort.Close();
TPumpSerialPort.Dispose();
}
int i = 1;
while (true)
{
Log(string.Format("Reconnecting Turbo Pump attempt {0}", i));
Thread.Sleep(2000);
if (connectTurboPump())
break;
if (i == attempts)
return false;
i++;
}
return true;
}
catch (Exception ex)
{
Log(string.Format("Could not reconnect to Turbo Pump: {0}", ex.Message));
return false;
}
}

Find gsm modem port in c#

I want to loop through the available ports:
System.IO.Ports.SerialPort.GetPortNames()
to find if a port is used by a gsm modem.
Any idea please.
What I did in my application for one similar task:
To check that a modem is connected to particular port you can send AT command into this port.
This function below returns true if we found a modem on the current COM port:
private bool CheckExistingModemOnComPort(SerialPort serialPort)
{
if ((serialPort == null) || !serialPort.IsOpen)
return false;
// Commands for modem checking
string[] modemCommands = new string[] { "AT", // Check connected modem. After 'AT' command some modems autobaud their speed.
"ATQ0" }; // Switch on confirmations
serialPort.DtrEnable = true; // Set Data Terminal Ready (DTR) signal
serialPort.RtsEnable = true; // Set Request to Send (RTS) signal
string answer = "";
bool retOk = false;
for (int rtsInd = 0; rtsInd < 2; rtsInd++)
{
foreach (string command in modemCommands)
{
serialPort.Write(command + serialPort.NewLine);
retOk = false;
answer = "";
int timeout = (command == "AT") ? 10 : 20;
// Waiting for response 1-2 sec
for (int i = 0; i < timeout; i++)
{
Thread.Sleep(100);
answer += serialPort.ReadExisting();
if (answer.IndexOf("OK") >= 0)
{
retOk = true;
break;
}
}
}
// If got responses, we found a modem
if (retOk)
return true;
// Trying to execute the commands without RTS
serialPort.RtsEnable = false;
}
return false;
}
On the next stage we can collect some data from the modem.
I used the following commands:
ATQ0 - switch on confirmations (receive OK on each request)
ATE0 - switch on echo
ATI - get modem details
ATI3 - get extended modem details (not all modems supports this command)
// Check each Availble COM port
foreach (string l_sport in l_available_ports)
{
GlobalVars.g_serialport = GlobalFunc.OpenPort(l_sport, Convert.ToInt32(this.cboBaudRate.Text), Convert.ToInt32(this.cboDataBits.Text), Convert.ToInt32(this.txtReadTimeOut.Text), Convert.ToInt32(this.txtWriteTimeOut.Text));
if (GlobalVars.g_serialport.IsOpen)
{
GlobalVars.g_serialport.WriteLine("AT\r");
Thread.Sleep(500);
string l_response = GlobalVars.g_serialport.ReadExisting();
if (l_response.IndexOf("OK") >= 0)
{
GlobalVars.g_serialport.WriteLine("AT+CMGF=1\r");
Thread.Sleep(500);
string l_response1 = GlobalVars.g_serialport.ReadExisting();
if (l_response1.IndexOf("OK") >= 0)
{
GlobalVars.g_PhoneNo = txt_PhNum.Text;
MessageBox.Show("Connected Successfully", "Connection", MessageBoxButtons.OK, MessageBoxIcon.Information);
lblConnectionStatus.Text = "Phone Connected Successfully.";
btnOK.Enabled = false;
btnDisconnect.Enabled = true;
GlobalVars.g_serialport.WriteLine("AT+CGSN\r");
Thread.Sleep(500);
string l_imei = GlobalVars.g_serialport.ReadExisting();
Console.WriteLine("Modem IMEI:" + l_imei);
if (l_imei.IndexOf("OK", 1) > 0)
{
l_imei = l_imei.Replace("AT+CGSN\r\r\n", null);
l_imei = l_imei.Replace("\r\n\r\nOK\r\n", null);
lbl_ModemIMEI.Text = l_imei;
}
else
{
lblConnectionStatus.Text = "Phone Connected Successfully. Error reading IMEI.";
}
EnableSMSNotification(GlobalVars.g_serialport);
break;
}
else
{
Console.WriteLine("No AT+CMGF cmd response");
}
}
else
{
Console.WriteLine("No AT cmd response");
}
}
else
{
Console.WriteLine("No Phone At:" + l_sport);
}
}

Categories