Problems with issuing at#httpsnd command over UART - c

I have a custom board that features a Telit LE910C1-EUX module communicating with an ESP32 processor through UART (the ESP32 module is programmed using the ESP-IDF v4.3.2 framework).
Here's the routine I have written to send commands to the Telit module:
esp_err_t TelitSerialCommand(const char* command) {
// Send command over UART
uart_write_bytes(UART_NUM_1, command, strlen(command));
if(uart_wait_tx_done(UART_NUM_1, 100) != ESP_OK) {
ESP_LOGE(TAG, "Could not send Telit command");
return ESP_ERR_TIMEOUT;
}
// Wait for two seconds
vTaskDelay(2000/portTICK_RATE_MS);
return ESP_OK;
}
While here's the routine I have written to read the Telit's response:
esp_err_t TelitSerialRead(char* RxBuf, size_t length) {
// First, clean current string holding past message
strncpy(RxBuf, "", length);
// Check how many data bytes are present in UART buffer
esp_err_t status = uart_get_buffered_data_len(UART_NUM_1, &length);
if (status != ESP_OK) {
ESP_LOGE(TAG, "Could not get UART rx buffer size");
return status;
}
// Read those bytes
length = uart_read_bytes(UART_NUM_1, RxBuf, length, 100);
// Clean UART buffer
uart_flush(UART_NUM_1);
return ESP_OK;
}
With these two routines, I am able to send commands to the Telit module and read its responses. When it comes to performing a POST operation using at#httpsnd, however, it seems like the command doesn't get through.
Here's a list of commands I use:
at+cmee=2\r
at#sgact=1,1\r
at#httpcfg=0,"www.httpbin.org",80,0,,,0\r
at#httpsnd=0,0,"/post",15,"application/json"\r
After prompting the latter command, the Telit should reply with >>> signaling that it's ready to read serial data; what I get instead is the same command I issue, as if it was not terminated and the module was currently waiting for the \r symbol. I finally get the >>> reply after another AT command is sent, but I am sure that the at#httpsnd command is terminated with the carriage return, so I am not sure why the Telit behaves like this. If I communicate with the Telit using minicom through USB (hence bypassing the ESP32 mcu) then all the commands above work. I can ping the 8.8.8.8 server so I know I have network connection, and the GET command AT#HTTPQRY=0,0,"/get"\r works just fine.
Have you ever dealt with a similar problem? Any help would be appreciated!

Turns out I had to disable the rs232 flow control by issuing the command AT&K0

Related

Send probe requests without waiting for an answer in C

for a project I am working on, I have to regularly send probe requests (~ 10 every 10 ms) for a chosen SSID.
Currently I am doing this with the following code:
char *args[] = {"iwlist", INTERFACE, "scan", "essid", ssid, (char *) NULL};
runQuietlyNonblocking(args);
where runQuietlyNonblocking runs the command in args with execvp and fork without waiting for the new thread to finish.
But since iwlist scan waits for probe answers and this takes more time than I need to create new probe requests, the probe requests get send but I got about 10000 threads after about half an hour and the program crashes due to memory shortage.
I am working on a raspberry pi with raspbian lite installed.
Is there a better way to send probe requests without the need to wait for an answer? Can i send probe requests manually or tell iwlist not to look for responses?
There are a few options. As far as I know popen() with "w" parameter does not wait for command execution, though it forks the process and pclose() will wait until command executes. system() just waits for command execution, but you might try feeding it to shell like this
system("iwlist wlan0 scan &")
That is, if you are stuck with iwlist.
As an alternative you can try using wpa_supplicant. It has a "scan" interface and "scan_results", first one sends request while the later gives out results.
for (;;)
{
FILE *fp = popen ("wpa_cli -i wlan0 scan", "w");
if (fp)
pclose (fp);
sleep (1);
}
(implying wpa_supplicant is up and running).
Last but not least, there are drivers which allow doing background scanning with their own interfaces, have seen it on proprietary Redpine driver.

How to print response to AT commands in Arduino serial port?

I want to print the response to AT command. I'm sending AT command but I'm not getting any response in the Arduino serial port. It's giving -1 instead of OK.
#include "SoftwareSerial.h"
String ssid = "connectify-krish";
String password = "12345678";
String myword= "";
SoftwareSerial esp(10, 11);
void setup() {
Serial.begin(9600);
esp.begin(9600);
esp.write("AT");
Serial.println(esp.read());
}
void loop() {}
As already pointed out in the comments you are not terminating the AT command line, so the modem will never respond to this.
Make sure you read V.250 and learn the difference between an AT command and an AT command line. ATI is an AT command, and "ATI I I\r" is a command line invoking this command three times in a row. Notice by the way in this example that you will get just one single Final result code for all three of them, i.e. the Final result code is a response to a complete command line and not to individual command invocations.
Then after fixing the sending of the command you must implement proper handling of the response. This includes reading and parsing what the modem sends back as a response to the sent command line. See this answer for the code structure and implementation hints.
As you've been told, terminate your AT commands with a carriage return character \r. Also you current code will read only a byte of the response, and thats if the response has even arrived since you included no delay at all. To communicate with the ESP interactively with the Serial monitor, I'd recommend using this:
#include <SoftwareSerial.h>
SoftwareSerial esp(10, 11);
void setup(){
Serial.begin(9600);
esp.begin(9600);
}
void loop()
{
while (Serial.available()) // forward data from monitor to esp
esp.write(Serial.read());
while (esp.available()) // forward data from esp to monitor
Serial.write(esp.read());
}
This basically makes your Arduino a conduit for communication between your PC and the ESP. You can send commands to the ESP with the Serial monitor and get their results immediately. Its great for testing commands. Just remember to set the serial monitor to BOTH NL & CR; this will serve you well for commands as well as any HTTP requests you send, as it appends \r\n to everything you send.
If you do want to write a sketch to talk to the ESP, you must provide some delay after sending a command to wait for the module to process the command and respond. The delay varies depending on the command, at least 500ms. The usual procedure is to define a timeout period for each command, depending on how long its expected to take, after which you 'give up' if there's no response yet. There are lots of libraries on GitHub that involve talking to some device using AT commands; study them to learn their techniques.

The simplest bridge example won't work - Arduino Yun

I tried to modify the Temperature Web Panel example (found in arduino-1.5.6-rw/libraries/Bridge/examples/TemperatureWebPanel) for a light sensor. Unfortunately it seems even the simplest receive and transmit result over wifi doesn't work! I even commented out the working part to just send back some text to the browser as you can see, but I still see nothing in the browser:
#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>
// Listen on default port 5555, the webserver on the Yun
// will forward there all the HTTP requests for us.
YunServer server;
String startString;
long hits = 0;
void setup() {
Serial.begin(9600);
// For debugging, wait until the serial console is connected.
/*delay(4000);
while(!Serial);
Bridge.begin();
*/
// Bridge startup
pinMode(13, OUTPUT);
Bridge.begin();
digitalWrite(13, HIGH);
pinMode(A0, INPUT);
// Listen for incoming connection only from localhost
// (no one from the external network could connect)
server.listenOnLocalhost();
server.begin();
// get the time that this sketch started:
Process startTime;
startTime.runShellCommand("date");
while (startTime.available()) {
char c = startTime.read();
startString += c;
}
Serial.println("yeah\n");
Serial.println(startTime);
}
void loop() {
// Get clients coming from server
Serial.println("a\n");
YunClient client = server.accept();
// There is a new client?
if (client) {
Serial.println("Client!\n");
// read the command
String command = client.readString();
client.print('(This should definitely be sent over bridge)');
/*command.trim(); //kill whitespace
Serial.println(command);
// is "temperature" command?
if (command == "temperature") {
// get the time from the server:
Process time;
time.runShellCommand("date");
String timeString = "";
while (time.available()) {
char c = time.read();
timeString += c;
}
Serial.println(timeString);
int sensorValue = analogRead(A0);
// convert the reading to millivolts:
client.print("Current time on the Yún: ");
client.println(timeString);
client.print("<br>Current value: ");
client.print(sensorValue);
client.print("<br>This sketch has been running since ");
client.print(startString);
client.print("<br>Hits so far: ");
client.print(hits);
}*/
// Close connection and free resources.
client.stop();
hits++;
}
delay(50); // Poll every 50ms
}
I see the "a" multiple times in the serial monitor, but never see anything in the arduino.local/arduino/temperature url, just a blank response.
Furthurmore, after awhile it seems the Yun was disconnecting from the network, not accessible over http or ssh. How does one debug an issue like this, considering ssh is the main way to communicate with this computer?
After debugging step by step on my own configuration, I found that the code never advanced past Bridge.begin().
Upon further investigation, I found that the default Bridge baud rate of 250000 no longer matched the kernel baud rate of 115200.
Changing to: Bridge.begin(115200) ... fixed the issue for me.
To determine your kernel speed, run cat /proc/cmdline from a terminal into your Yun
See this link for more info: https://groups.google.com/forum/#!msg/linino/-rSmpjX4UOM/Cnjv-uzrlfgJ
If this isn't your issue, consider adding debug information (ie.. Serial.print()) in the actual source files for Bridge.cpp, etc. Unfortunately, it appears that Arduino/Linino devs often make breaking changes and do not have the resources to update documentation, examples, etc.
If you are on Windows, don't use 'arduino.local', because Windows has problems to resolve this host.
Have you tried with the IP address ?
You must televerse your script through wifi, and not through serial (in arduino Ide you must change the port)
Have you created the path 'arduino/www/'
You need a micro SD card plugged in to your Yún with a folder named “arduino” at the root. Inside the “arduino” folder, there must be a directory called “www”. You need to upload the sketch via WiFi to transfer the contents of the local “www” folder. You cannot transfer files via USB. Once uploaded, you can open your favorite browser and go to http://arduino.local/sd/TemperatureWebPanel.
you must open http://YUNS_IP/sd/TemperatureWebPanel
if you are using the Yun Shield u need to comment out the Serial commands or remove all references to serial as the Bridge and the Serial port all share the same hardware serial. I faced the same problem there was no connection.
Replace serial.begin(115...) by Bridge.begin().

Server program is stuck at send

I am building a server client model in C. The clients connects to the server and they start exchanging data. However, the user can end the client at any time in the program, but the server is not notified about it. The server keeps sending that data even after the client is closed.
I was in the impression that send function will return -1 if the server is unable to send the data, but my server program just stuck at send
if((byteSent = send(new_fd, fileContents, strlen(fileContents), 0)) == -1){ //
the program just halts at the above line.
How do I overcome this problem?
//Code
exitT = 0;
//execution_count = 1;
for(i=0;i<execution_count;i++)
{
sleep(time_delay);
//getting the current time on the server machine
time_t t;
time(&t);
char *time=ctime(&t);
printf("The Execution time at server = %s\n",time);
system(exec_command);
/*Open the file, get file size, read the contents and close the file*/
// Open the file
fp = fopen(fileName,"r");
// Get File Size
fseek(fp,0,SEEK_END);
dataLength = ftell(fp);
rewind(fp);
fileContents = (char*)malloc(dataLength+1);
// Read File
fread(fileContents,1,dataLength,fp);
fileContents[dataLength] = '\0';
// Close file
fclose(fp);
printf("sockfd = %d \n",new_fd);
// send file length to client
rc=send(new_fd, &dataLength, sizeof(dataLength), 0) ;
printf("length of client data = %d \n",rc);
printf("sockfd = %d \n",new_fd);
// send time to client
rc=send(new_fd, time, strlen(time), 0) ;
printf("length of client time = %d \n",rc);
usleep(20000);
// Send file contents to Client
while(dataLength>0){
printf("sockfd = %d \n",new_fd);
if((byteSent = send(new_fd, fileContents, strlen(fileContents), 0)) == -1){
printf("bytes sent = %d \n",byteSent);
exitT = 1;
break;
}
dataLength-=byteSent;
}
//Delete the log file
sprintf(deleteCommand,"rm %s",fileName);
system(deleteCommand);
if(exitT == 1)
break;
}
bzero(fileName,sizeof(fileName));
bzero(exec_command,sizeof(exec_command));
bzero(deleteCommand,sizeof(deleteCommand));
//decClientNum();
kill(parent_id,SIGALRM);
close(new_fd); // parent doesn't need this
printf("STATUS = CLOSED\n");
exit(0);
}
Thanks
I assume you are coding for a Linux or Posix system.
When a syscall like send fails it returns -1 and sets the errno; you very probably should use errno to find out why it failed.
You could use strace to find out which syscalls are done by your sever, or some other one. Of course, use also the gdb debugger.
You very probably need to multiplex inputs or outputs. The system calls doing that are poll, select (and related ppoll and pselect). Read e.g. the select_tut(2) man page.
You may want to use (or at least to study the source code of) existing event oriented libraries like libevent, libev etc.. (Both Gtk and Qt frameworks provide also their own, which might be used even outside of GUI applications).
I strongly suggest reading about advanced unix programming and unix network programing (and perhaps also about advanced linux programming).
maybe you're using a tcp protocol and the server is waiting for an ACK. Try using udp if you want your connection to be asynchronous.
From the man page: No indication of failure to deliver is implicit in a send(). Locally detected errors are indicated by a return value of -1.
Proably something like this might help: http://stefan.buettcher.org/cs/conn_closed.html
I think I am pretty late in the party, but I think this answer might help someone.
If space is not available at the sending socket to hold the message to be transmitted, and the socket file descriptor does not have O_NONBLOCK set, send() shall block until space is available.
When send() function gets stuck, there might be a situation like, TCP window size has become 0. It happens when the other end of the connection is not consuming received data.
There might be a scenario like this, the receiving end process is running by GDB and segfault occurred.
The TCP connection remains established.
Data is being send continuously.
The receiver end is not consuming it.
Consequently the receiver TCP window size will keep decreasing and you can send data till it is greater than zero. Once it becomes 0, send() function will get stuck forever.
As the situation mentioned in the question is not a scenario of closed connection. When a process writes something on a closed TCP connection, it receives a signal SIGPIPE. Default handler of SIGPIPE terminates the process. So, in a closed connection scenario if you are not using your own SIGPIPE handler then process should be terminated by default handler whenever something is written on the socket.

How can I get the telnet result using C / Objective C?

Here is a telnet site:
telnet://202.85.101.136:8604/
It is from Hong Kong public library, can I write some programme to get the string / result from the telnet service, and send the request from C / Objective C? thz u.
Sure its possible. Telnet is a pretty simple protocol, you simply need to open a TCP socket and connect it to that IP and Port. When you first connect, the telnet server will send some negotiation requests using the binary protocol defined in RFC854, to which your client is expected to respond. Once negotiation is completed you communicate by simply sending and receiving ASCII data, normally a line at a time.
For a simple "get some data from a host" telnet sessions where you aren't trying to have a real interactive session, it sometimes works to simply accept all the servers negotiation settings to avoid implementing the whole negotiation protocol. To do this, just look for the server to send you several 3-byte commands in the format of: 0xFF 0xFD xx, which is basically the server telling you "I want you to use option X", just respond to this with 0xFF 0xFB xx, which basically is just you agreeing to whatever the server is asking for. Then when you get passed negotiations, you just have to receive lines with a socket read and send commands with a socket write.
If you have a telnet program already on your system, you can use it to do all the connection work for you. Here's a program for gnu/Linux that you can use as a starting point.
It uses popen to execute the system's telnet command. Then it just reads all data from the pipe (stdout if you just executed the telnet command by itself from the shell) and prints it. When there's no more data to read, it exits.
You can send data to the server by opening the pipe in rw mode instead of r and then writing like you would any other file. You could conditionally do stuff like scan your input for Username: and then send a username string too, for instance.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
const char *cmd = "telnet 202.85.101.136 8604";
char buffer[256];
FILE *pipe = popen(cmd, "r");
if( !pipe ) { perror("popen"); exit(-1); }
while( fgets(buffer, sizeof(buffer), pipe) != NULL &&
!feof(pipe) )
{
if( ferror(pipe) ) { perror("fgets"); break; }
/* Here you do whatever you want with the data. */
printf("%s", buffer);
}
pclose(pipe);
return 0;
}
If you're using Windows, this link explains the alternative to popen.
There's also a program called Expect that can help you automate stuff like this.

Resources