Communicating a GPS/GPRS/GSM tracker with the server - gprs

I am developing a vehicle tracking system which uses GPS/GPRS/GSM. The tracking device I am currently using is GV100, a GPS/GPRS/GSM tracker from Quectel ([www.quectel.com][1].)
I am not able to establish connection between the device and the backend server. My question particularly is:
How do I send commands (AT Commands) to the device from the server?
How do I accept the response (reports and acknowledgement messages) from the device to save it in the database?
I sent command to the device with the MGV100 Manage Tool (Software provided by Quectel) via serial port. And I got acknowledgement SMS message on GSM enabled mobile telephone. Now, I want to send message from the server and accept reply on the server (not by SMS). I don’t know how to send command and receive the reply. I have no previous experience in developing such systems.
It would be great if I can get a sample code and setup procedures if it requires.
Where can I get a relevant tutorial for the case I mentioned?
Thanks jhonkola
To understand how server receives and send data to the device, I decided to first implement the communication between the client (currently my PC) and server. Though my ultimate goal is communicating with the device, currently I am trying to establish connection from my PC to the server. If I succeed in this, I will strive to communicate to server from the device which needs IP address and port number of server to send and receive data.
This is my assumption how to do it:
I can open a port on the server from .cs code so as to communicate
using TCP/UDP.
Client then can send and receive data via this
port.
I can save the data sent from the client on server's file
system and review it any time. (Am not storing the data in relational database because I don't want to bother about database issues now.)
This is how I tried to implement:
Server a C# Web Application:
When a button is clicked it opens a port and listens to client
protected void btnConnect_Click(object sender, EventArgs e)
{
try
{
continueListening = true;
while (continueListening)
{
int port=Int32.Parse(txtPort.Text);
lblOutput.Text = "Port is now " + port +". Waiting for connection";
TcpListener myList = new TcpListener(IPAddress.Parse(txtIpAddress.Text), port);
myList.Start();
Socket s = myList.AcceptSocket();
lblOutput.Text="Connection accepted from " + s.RemoteEndPoint;
byte[] b = new byte[100];
int k = s.Receive(b);
lblOutput.Text = ("Recieved...");
String obtainedText = "";
for (int i = 0; i < k; i++)
{
obtainedText = obtainedText + " " + (Convert.ToChar(b[i]));
}
writeToTextFile("C:/Users/MekAtIbex/Desktop/TESTED/RECIEVED.txt", obtainedText);
lblOutput.Text = obtainedText;
ASCIIEncoding asen = new ASCIIEncoding();
lblOutput.Text = lblOutput.Text +" "+ ("The string was recieved by the server.");
lblOutput.Text = lblOutput.Text +" "+ ("\r\nSent Acknowledgement");
}
Client: C# Windows application
private void btnSend_Click(object sender, EventArgs e)
{
try
{
TcpClient tcpClient = new TcpClient();
int port=Int32.Parse(txtPort.Text.Trim());
tcpClient.Connect(txtIpAddress.Text, port);
lblStatus.Text = ("Connected");
Stream stm = tcpClient.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] bytesToSend = asen.GetBytes(txtData.Text);
lblStatus.Text = ("Transmitting.....");
stm.Write(bytesToSend, 0, bytesToSend.Length);
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
for (int i = 0; i < k; i++)
{
txtaResponse.Text = txtaResponse.Text + "\n" + "Res... " + new DateTime() + " " + Convert.ToChar(bb[i]);
Console.Write(Convert.ToChar(bb[i]));
}
tcpClient.Close();
}
catch (Exception ex)
{
lblStatus.Text = ("Connected");
txtaRequest.Text = txtaRequest.Text + "\n" + "Err... " + new DateTime() + " " + ex.StackTrace;
}
}
My current questions are:
Is my assumption correct? If not how should I do it?
I have tried to save it using the above code but I didn't got the file.
What is the advantage and disadvantage of using UDP in comparison TCP for tracking applications?
I have browsed well, but I couldn't find a place for a good start. And, as I have no experience in such applications, I couldn't debug my application.

My current questions are:
Is my assumption correct? If not how should I do it?
Yes, your basic assumptions are correct. The server would open a listening port and then the client could connect to this port and drop off data as needed. You can have the server log this to a file for later review too.
I have tried to save it using the above code but I didn't got the
file.
Is the file already created? The method you have will fail if the file is not existent on the system.
What is the advantage and disadvantage of using UDP in comparison TCP
for tracking applications?
UPD is less expensive in terms of network setup. It is the "fast and dirty" method of communication. The downside is that you may not get every message properly delivered. In some applications, this just doesn't matter and the benefits are worth this cost.
Now a few things I'd change:
Change IPAddress.Parse(txtIpAddress.Text) to IPAddress.Any
This will allow your listener the broadest ability to catch incoming messages and will most likely not effect other systems (since this is essentially your first networking program).
You'll also want to make your listener spawn a thread to handle the file writing and then go back to listening. This is a very standard practice and allows for servers to handle multiple connections.

It is difficult to comprehensively answer this, as a good answer would require detailed knowledge about the product. I suggest that you contact the manufacturer / reseller for support.
A few general points:
Sending commands over network to the device requires that you are able to connect to the device from internet. This is not always easy over GSM network, as the operators may block all incoming traffic. The manufacturer may have provided solutions for this.
If you can connect to the device, the protocol that is used to give commands (assuming that such protocol is built-in) will also contain a mechanism to receive any responses.

Related

Monitor the "active state" of Biztalk send port service instance

Team,
My biztalk send port instance gets hung and stays in the active state for longer periods of time. I would like to monitor that send port active instance with the help of C#.
I intend to run a code which will check if the send port(passed as a parameter) is still in a running state or not. Can anyone help me with that piece of code ?
Use WMI MSBTS_ServiceInstance.ServiceStatus Property:
public static int GetRunningServiceInstanceCount()
{
int countofServiceInstances = 0;
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\MicrosoftBizTalkServer", "SELECT * FROM MSBTS_ServiceInstance WHERE ServiceStatus = 1 or ServiceStatus = 2");
countofServiceInstances = searcher.Get().Count;
return countofServiceInstances;
}
catch (ManagementException exWmi)
{
throw new System.Exception("An error occurred while querying for WMI data: " + exWmi.Message);
}
}
To get to your actual problem: The SFTP adapter in BizTalk 2016 has a great way of using the most recent version of the FTP code. This might solve stability issues.
Assuming from your BizTalk 2013 tag, you're probably not using the 2016 version, in that case double check you are at least at CU3 since that one solves a few critical SFTP bugs.

Spring Integration TCP. Get connection ID of the connected clients

I have a problem here with the dynamic TCP connection approach (Spring-IP Dynamic FTP Sample). When a message is received, I want to get the TCP connection details for the received message. this way I can keep track in my application of the sender sending that message. But in Service activator I am not able to get this detail.
Also need the connection details when my TCP client is connected to the server. This way if the server wants to initiate the communication, it will have the connection details.
For info my application has more than one TCP clients and servers.
Got an answer reply in another post from Mr. Gary Russell.
Answer
For normal request/reply processing, using an inbound gateway, the framework will take care of routing the service activator reply to the correct socket. It does this by using the connection id header.
If you need to provide arbitrary replies (e.g. more than one reply for a message, you have to use inbound and outbound channel adapters and your application is responsible for setting up the connection id header.
There are two ways to access the required header in a POJO invoked by a service activator:
public void foo(byte[] payload, #Header(IpHeaders.CONNECTION_ID) String connectionId) {
...
}
public void foo(Message<byte[]> message) {
String connectionId = message.getHeaders().get(...);
}
Then, when you send your replies, you need to set that header somehow.
EDIT
Below Is My Implementation
To get all the connected clients simply get the ServerConnectionFactory from the context and access the method .getConnectedClients(). It returns the list connectionIds for each connected client.
AbstractServerConnectionFactory connFactory = (AbstractServerConnectionFactory) appContext.getBean("server");
List<String> openConns = connFactory.getOpenConnectionIds();
As mentioned above in Gary's response, use this connectionId and set it in conneciton header while sending the message to a client. Sample code as follows.
MessageChannel serverOutAdapter = null;
try{
serverOutAdapter = (MessageChannel) appContext.getBean("toObAdapter");
}catch(Exception ex){
LOGGER.error(ex.getMessage());
throw ex;
}
if(null == serverOutAdapter){
throw new Exception("output channel not available");
}
AbstractServerConnectionFactory connFactory = (AbstractServerConnectionFactory) appContext.getBean("serverConnFactoryBeanId");
List<String> openConns = connFactory.getOpenConnectionIds();
if(null == openConns || openConns.size() == 0){
throw new Exception("No Client connection registered");
}
for (String connId: openConns) {
MessageBuilder<String> mb = MessageBuilder.withPayload(message).setHeader(IpHeaders.CONNECTION_ID, connId);
serverOutAdapter.send(mb.build());
}
Note 1: If u want to send messages from the server then be cautious to configure the server and client connection factories in a way that they do not time-out. i.e put so-keep-alive = true in client connection factory.
Note 2: If the server has to communicate with the client then make sure that the client connects to the server as soon as the context is loaded. Because Spring-IP client connection factory connects only when the first message is sent out. In order to connect client after context load, put client-mode="true" in tcp client context for the "tcp-outbound-channel-adapter".

smtp connection works in telnet but not in ASP -- same server, same credentials

I'm trying to send email from an ASP.NET using my SendGrid account. It works on my dev machine, but not in production, even though the credentials are the same. Likewise, in production I can connect to the SMTP server via telnet (using base64 encoded credentials), but the ASP site can't connect--I get error "Unauthenticated senders not allowed."
I've tried a mix of port numbers (25, 587, 465 -- my site is SSL). Using port 465 times out. 25 and 587 return respond immediately--but with the login error. This is really baffling because, like I say, it's the same credentials on dev machine and production.
I looked very briefly at Microsoft Network Monitor 3.4, but could not make heads or tails of it. I was hoping it would tell me the blow-by-blow commands being sent since I suspect the web site is doing something a little different from how telnet connects, but I don't know what.
Note I also asked my web host if outgoing traffic on these ports were blocked on production firewall, but they aren't.
Here's the actual code--like I say works fine on localhost, but SMTP connection fails in production
[AllowAnonymous]
[HttpPost]
public ActionResult ResetPasswordSend(string email)
{
List<string> userList = new List<string>();
try
{
string[] invalidChars = new string[] { ";", "," };
foreach (var invalidChar in invalidChars) if (email.Contains(invalidChar)) throw new Exception("Email contains invalid character.");
int count = 0;
// since emails are not unique, I must launch resets for all of them
var users = _db.HsProfile.Query("[Email]=#0", SqlDb.Params(email));
foreach (var profile in users)
{
count++;
userList.Add(profile.UserName);
var token = WebSecurity.GeneratePasswordResetToken(profile.UserName, 15);
WebMail.Send(profile.Email, "HumaneSolution.com Password Reset for user " + profile.UserName,
"You received this email because you or someone with your email address requested a password reset on HumaneSolution.com. " +
"If you didn't do this, then you don't need to take any action, and nothing will happen.\n\n" +
"To proceed with the password reset, click the link below within 15 minutes:\n\n" +
Url.BaseUrl("Account/EnterNewPassword/" + token) + "\n\n" +
"Sent to: " + email + " at " + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString() + "\n" +
"User name: " + profile.UserName);
}
if (count == 0) throw new Exception("Email " + email + " is not registered at HumaneSolution.com.");
}
catch (Exception exc)
{
ViewBag.Error = exc.Message;
}
return View(userList);
}
Based on suggestion from SendGrid, I re-wrote the email code so it does not use WebMail.Send but rather the SmtpClient and MailMessage objects explicitly. SendGrid says there might be some kind of timing problem in how ASP.NET loads credentials from the config file automatically. Here's exactly what they said:
Are you by chance storing your SendGrid credentials in a configuration file, separate from the code that connects to our SMTP server? The reason I ask is because I have seen rails and C# configurations like this receive the unauthenticated error due to the credentials not being passed at the correct time. Usually this is solved by moving the credentials directly in with the code instead of a separate configuration file. Give that a try and see if you notice a difference.<<
I didn't follow their advice completely -- i.e. I'm still using config file, but I'm loading the config values in subclasses of SmtpClient and MailMessage so I avoid hardcoding creds in my app. Anyway, it worked, all is well again.

Email using System.Net.Mail through Google Apps Timing out

I have a ASP.NET 4.0 web application, which the HR team uses to send out surveys to employees. Since we use a Google Apps, I am trying to send these survey emails through the Google Apps Account.
I have used the following settings to send out emails.
Host - smtp.gmail.com
Port - 587
EnableSsl=true
along with my username and password.
This is the code for sending out emails.
using (SmtpClient smtp = new SmtpClient())
{
smtp.Timeout = 0;
smtp.Send(message);
}
The settings are in the web.config and are read from there.
Now my issue..
The hr team selects multiple users to send the survey to. They could just select 1 or maybe up to 100 at a time to send out surveys. Since each survey link has to be different, I iterate the list of users and email them.
Now after the application send out a maximum of 12 emails, it stops sending out any more. The next email it tries to send it throws an error.
Message = The operation has timed out.
Status Code =GeneralFailure
Stack Trace = at System.Net.Mail.SmtpClient.Send(MailMessage message)
at ABC.Business.Mail.SendMail(MailMessage message, String& errorMessage)
Then onwards if I retry again it throws an error
Message = Failure sending mail.
Status Code =GeneralFailure
Stack Trace = at System.Net.Mail.SmtpClient.Send(MailMessage message)
at ABC.Business.Mail.SendMail(MailMessage message, String& errorMessage)
If its come to this state, the only way out is to retart IIS. If I restart IIS, it starts working fine again for the next 12 odd.
What could be the issue? Please help.
You shouldn't set the Timeout to zero.
Its default is 100,000mS (100 seconds), try to leave it at that at least.
System.Net.Mail only supports "Explicit SSL".
Explicit SSL
System.Net.Mail only supports "Explicit SSL". Explicit SSL starts as unencrypted on port 25, then issues a STARTDLS and switches to an Encrypted connection. See RFC 2228.
Explicit SLL would go something like: Connect on 25 -> StartTLS (starts to encrypt) -> authenticate -> send data
If the SMTP server expects SSL/TLS connection right from the start then this will not work.
Implicit SSL
There is no way to use Implicit SSL (SMTPS) with System.Net.Mail. Implicit SSL would have the entire connection is wrapped in an SSL layer. A specific port would be used (port 465 is common). There is no formal RFC covering Implicit SSL.
Implicit SLL would go something like: Start SSL (start encryption) -> Connect -> Authenticate -> send data
This is not considered a bug, it’s a feature request. There are two types of SSL authentication for SMTP, and we only support one (by design) – Explicit SSL.
Demo Code:
*
protected void Btn_SendMail_Click(object sender, EventArgs e)
{
try
{
var fromAddress = "xyz#gmail.com";
var toAddress = "abc#gmail.com";
const string fromPassword = "xxxxxxxx";
string subject = "Sending Demonstration";
string body = "From: " + txtFrom.Text + "\n";
var smtp = new System.Net.Mail.SmtpClient();
{
smtp.Host = "smtp.gmail.com";
smtp.Port = 25;
smtp.EnableSsl = true;
smtp.Credentials = new NetworkCredential(fromAddress, fromPassword);
}
smtp.Send(fromAddress, toAddress, subject, body);
Response.Write("<script language=javascript> alert('send')</script>");
}
catch (Exception ex)
{
txtBody.Text = ex.Message;
}
}
*
This Code Is Working Without Any Error!!!!
Chris, TimeOut makes ASP.NET application to wait for the request to perform before it shutting down automatically. So, If you give timeOut as zero, ASP.NET will not wait for the request to perform and it will throw error as operation has timed out.
TimeOut should be atleast 180 seconds.
Thanks.

HTTP Connection Parameters

I am using the HTTP Connection in the following way:
HttpConnection _httpConnection = null;
try {
_httpConnection = (HttpConnection)Connector.open(_url);
} catch(Exception e) { }
byte [] postDataBytes = _postData.getBytes();
_httpConnection.setRequestMethod(HttpConnection.POST);
_httpConnection.setRequestProperty("User-Agent","Profile/MIDP-2.0 Configuration/CLDC-1.0");
_httpConnection.setRequestProperty("Content-Language", "en-US");
_httpConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
_httpConnection.setRequestProperty("Connection", "close");
_httpConnection.setRequestProperty("Content-Length", Integer.toString(_postData.getBytes().length));
os = _httpConnection.openOutputStream();
os.write(postDataBytes);
os.flush();
This HTTP Connection requires parameters to successfully open. For example on a WIFI network, it requires the ";deviceside=true;interface=wifi" to be added to the URL.
The problem is for the EDGE connection. Each country requires different parameters to be added. For example in lebanon it requires ";deviceside=false" but in KSA if i add this parameter the connection will not open. In USA it needs different types of parametes. The question is how to establish an HTTP connection for all the countries with the same parameters. So that the application will successfully have an internet connection no matter where it is downloaded.
Welcome to the confusing world of network transports on BlackBerry! You will want to start with the article Connecting your BlackBerry - http and socket connections to the world.
Here is a simple example for "just give me a connection" (note, you will need to add appropriate error handling; also, myURL in the code below should have no connection descriptor info appended to it):
ConnectionFactory factory = new ConnectionFactory();
ConnectionDescriptor descriptor = factory.getConnection(myURL);
if (descriptor != null) {
_httpConnection = (HttpConnection) descriptor.getConnection();
...
}
Try using to use the method reffered in this link melick-rajee.blogspot.com and use it like
_url = "http://www.example.com";
_httpConnection = (HttpConnection)Connector.open(_url + getConnectionString());
You will have to sign the application to use this else the application will show exception.
To sign your application just go here Code Signing Keys
To use the connectionFactory, seems you need to set BisBOptions.
Try this:
connFact = new ConnectionFactory();
connFact.setTransportTypeOptions(TransportInfo.TRANSPORT_BIS_B,
new BisBOptions("mds-public"));

Resources