How to send an HTTP GET using AT firmware over serial connection? - arduino

So I am using the Arduino Uno and the ESP8266 module. I am trying to get the module to send an HTTP get request using the AT serial firmware however I am not quite able to do so. The project gets data from a sensor and sends it in real time using the Pubnub Service by posting the data to the pubnub rest API.
I have the function:
void sendSerialCommand(String cmd, int t) {
int i=0;
while(1) {
Serial.println(cmd);
client.println(cmd);
while(client.available()) {
if(client.find("OK"))
i=8;
}
delay(t);
if(i>5)
break;
i++;
}
if(i==8)
Serial.println("OK");
else
Serial.println("Error");
}
Using this function, I set up a connection with the server as :
sendSerialCommand("AT+CIPMUX=1",100);
sendSerialCommand("AT+CIPSTART=0,\"TCP\",\"" + pubnubIP + "\",80",1000);
Serial.println("Established connection with DashBoard Servers.....");
Then I try:
sendSerialCommand("AT+CIPSEND=0," + String(getRequestLength) + "," + "http://" + pubnubIP + "/publish/<publish-key>/<sub-key>/0/water/0/<data>", 1000);
(I have put in the values for the publish and sub key in the actual code.)
The getRequestLength is the length of the data to be sent.
When I run the code, the output says wait..... and the the connection just closes. Could anyone please tell me the correct Syntax or method of sending the data?

Related

file downloading issue over gsm module and esp32

I am trying to download 1.4 mb file using tinygsm library, and for that i am using FileDownload example. However my device downloads 96,000 bytes and then stops.
After debugging the program i found out that client.connected() condition is turning false and that is why i am not be able to download the file further.
Hardware being used is esp32 and sim800c module.
I am sharing the code snippet below, Please guide me resolving this issue.
TinyGsmClientSecure client(modemGSM);
if (client.connect(host, port)) {
SerialDebug.println("connected");
// Make a HTTP GET request:
SerialDebug.println("Performing HTTP GET request...");
client.print(String("GET ") + path + " HTTP/1.1\r\n");
client.print(String("Host: ") + host + "\r\n");
client.print("Connection: close\r\n\r\n");
client.println();
}else {
SerialDebug.println("connection failed");
return;
}
while (client.connected() && millis() - timeout < 10000L) {
while (client.available()) {
char c = client.read();
readBytes++;
if(readBytes % 1000 == 0)
SerialDebug.println(readBytes);
timeout = millis();
}
}
The connection can break. You should monitor it and try to reconnect.
You also should use HTTP Get request with Range header in order to resume the download.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests#single_part_ranges

Chromebook BLE characteristic notifications issue

I am developing a packaged app for chromebook. I am using BLE APIs to communicate with BLE devices. One of the modes of communication is request-response. Request is sent on a write characteristic and its response is received on another read characteristic. If multiple consecutive requests elicit same response then the notification is received only once.
For example consider request data bytes are [2, 5, 0] and its response is [3, 5, 0]. If I send [2,5,0] multiple times to the BLE device, and the device sends its response same number of times, in the chromebook app I see the characteristic notification only once.
Notification listener function:
chrome.bluetoothLowEnergy.onCharacteristicValueChanged.addListener(function (chrc) {
logger.info("char value changed " + chrc.uuid + " value " + chrc.value.byteLength + " address " + chrc.service.deviceAddress);
var data = new Uint8Array(chrc.value);
logger.info("Got char data " + data);
});
Char write function:
var myBytes = new Uint8Array([50, 20, 1]);
chrome.bluetoothLowEnergy.writeCharacteristicValue(charToWrite.instanceId, myBytes.buffer, function () {
if (chrome.runtime.lastError) {
logger.error("Failed to write value: " + chrome.runtime.lastError.message);
return;
}
logger.info("First char write done");
chrome.bluetoothLowEnergy.writeCharacteristicValue( charToWrite.instanceId, myBytes.buffer, function () {
if (chrome.runtime.lastError) {
logger.error("Failed to write value: " + chrome.runtime.lastError.message);
return;
}
logger.info("Second char write done");
});
});
In above example, the notification response for second char write is never received (since the command is the same, the response is also the same).
If I send another command which elicits different response, then notification is received correctly.
Same BLE communication works fine on other platforms like Windows, MacOS. Thus we know that there is no device side issue. Chromebook seems to suppress notifications if same data is received on characteristic again and again.
I could not find a way in chromebook BLE API to change this behavior.
Has anybody else also seen this issue?

esp8266 http client example

Hi I have used esp8266 module http client example and my code is exactly like the sample code.
This is a part of my code:
if (httpCode > 0) {
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = http.getString();
if(payload=="text") {
digitalWrite(LED_BUILTIN, HIGH);
} else {
digitalWrite(LED_BUILTIN, LOW);
}
}
}
I can't compare my variable with my text and the LED_BUILTIN is always on. I am sure it can get the text of the http client page because I can send it to Arduino nano with softwareserial.
Actually when i want to send it to arduino nano it gives me an error : no matching function for call to HardwareSerial::write(String&)
i could fix the error with this sample code
String mystring= http.getString();
char* buf = (char*) malloc(sizeof(char)*myString.length()+1);
myString.toCharArray(buf, myString.length()+1);
Serial.write(buf);
free(buf);
but esp8266 module can't compare payload with my text
If the LED was turned on, then the compare method was definitely work. Try to send different String from the server, your LED should be turned off. And also, when you got problems like this, try to print the "payload" to the serial monitor. At least, you could figure it out where the faulty is.
hope this help.

Arduino WiFly - ad hoc network setup

I'm currently working with an Arduino trying to build an ad hoc network to which a device can connect to and send web requests to. The problem I am currently having is that I can only set up one connection and then when that connection is terminated (with client.stop()), all subsequent connections are not picked up by the server, even a cURL command just sits there spinning. The first connection I start when I reset the server works fine, and I am able to talk to the server; but after that, the Arduino can no longer find new clients (even though it's trying with the library given).
I`m using the SparkFun library for the WiFly shield cloned from GitHub, along with an Arduino Uno.
My current code is based off their default example 'WiFly_AdHoc_Example', but I had to remove a few things to get the network to start up which might be the cause of this problem.
Here is the .ino file that I am running.
#include <SPI.h>
#include <WiFly.h>
//#include <SoftwareSerial.h>
//SoftwareSerial mySerial( 5, 4); //Part from example not used (see below)
WiFlyServer server(80); //Use telnet port instead, if debugging with telnet
void setup()
{
Serial.begin(9600);
//The code below is from the example, but when I run it the WiFly will hang
// on Wifly.begin(). Without it, the WiFly starts up fine.
//mySerial.begin(9600);
//WiFly.setUart(&mySerial); // Tell the WiFly library that we are not
// using the SPIUart
Serial.println("**************Starting WiFly**************");
// Enable Adhoc mod
WiFly.begin(true);
Serial.println("WiFly started, creating network.");
if (!WiFly.createAdHocNetwork("wifly"))
{
Serial.print("Failed to create ad hoc network.");
while (1)
{
// Hang on failure.
}
}
Serial.println("Network created");
Serial.print("IP: ");
Serial.println(WiFly.ip());
Serial.println("Starting Server...");
server.begin();
Serial.print("Server started, waiting for client.");
}
void loop()
{
delay(200);
WiFlyClient client = server.available();
if (client)
{
Serial.println("Client Found.");
// A string to store received commands
String current_command = "";
while (client.connected())
{
if (client.available())
{
//Gets a character from the sent request.
char c = client.read();
if (c=='#' || c=='\n') //End of extraneous output
{
current_command = "";
}
else if(c!= '\n')
{
current_command+=c;
}
if (current_command== "get")
{
// output the value of each analog input pin
for (int i = 0; i < 6; i++)
{
client.print("analog input ");
client.print(i);
client.print(" is ");
client.print(analogRead(i));
client.println("<br />");
}
}
else if(current_command== "hello")
{
client.println("Hello there, I'm still here.");
}
else if (current_command== "quit")
{
client.println("Goodbye...");
client.stop();
current_command == "";
break;
}
else if (current_command == "*OPEN*")
{
current_command == "";
}
}
}
// Give the web browser time to receive the data
delay(200);
// close the connection
client.stop();
}
}
This script is just a mini protocol I set up to test. Once connected with the wifly module you can send text such as "get" "hello" or "quit" and the wifly module should respond back.
Using Telnet I can successfully connect (the first time) and send commands to the Arduino including "quit" to terminate the connection (calls the client.stop() method). But when I try to reconnect though Telnet, it says the connection was successful, but on the Arduino it's still looping thinking the client is still false. What??
I know right, I'm getting mixed messages from Telnet vs Arduino. None of the commands work obviously since the Ardunio is still looping waiting for a client that evaluates to true. I'm going to take a look at WiFlyServer from the library I imported and see if I can dig up the problem, because somehow that server.available() method isn't finding new clients.
I am noticing a lot of TODO's in the library code....
So I found the reason for the problem. It was in the WiFlyServer.cpp file from the SparkFun library. The code that was causing the reconnect issue was in fact the server.availible() method. Right at the top of the method, there is a check:
// TODO: Ensure no active non-server client connection.
if (!WiFly.serverConnectionActive) {
activeClient._port = 0;
}
For some reason when I comment this out, I can connect and reconnect perfectly fine and everything works as it should. I will now dive into the library and see if I can fix this, I'm not exactly sure what this is doing, but it gets called when the server connection is not active and is somehow blocking subsequent connections. The problem with this solution is that the Arduino always thinks it has found a client since client and client.connected() evaluate to true even if one doesn't exist. Even client.available() evaluates to true right when the connection is terminated and the ghost "client" is found, but after that first run through the if-statement the ghost "client" is no longer available(). Even with this flaw it still picks up a new client when it comes along which is why it works.
How might I get to the root of this problem without using this commenting hack?
Are their any risks or future problems I might run into doing it this way?
What is the purpose of the block that I commented out in the first place?
Well, when you're calling client.stop(); how does the Arduino know whether the client has to start again?
Remember setup() executes only once.
Have you tried to include the following code in your loop to tell the Arduino to create the WiFly AdHoc network again? This may or may not work. I don't have one myself and haven't played with the Wifly shield but it's worth a try.
Remember to only ever execute the code once every time you need to connect again since it's sitting inside a loop that's always going to be running.
WiFly.begin(true);
Serial.println("WiFly started, creating network.");
if (!WiFly.createAdHocNetwork("wifly"))
{
Serial.print("Failed to create ad hoc network.");
while (1)
{
// Hang on failure.
}
}

Communicating a GPS/GPRS/GSM tracker with the server

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.

Resources