Adafruit Fona 3g Library; How exactly does this work? - c++

I am trying to send a packet to a server over 3g and TCP connection. Below is a link to the .cpp and .h file I have found:
https://os.mbed.com/users/Nels885/code/Adafruit_FONA_3G/
More specifically, I am really confused on how TCPSend works under the Adafruit_FONA_3G class. I am trying to implement it but my code seems to get stuck at packet[0] = 0; under function bool Adafruit_FONA_3G::TCPsend(char *packet).
I have tried commenting out packet[0] = 0; and the code runs all the way through. I have also tried initializing char* packet[32]; before packet[0] = 0; and the code runs all the way through. I am assuming the function is not detecting the packet input.
Here is the specific function from the .cpp file:
bool Adafruit_FONA_3G::TCPsend(char *packet)
{
if (strlen(packet) > 0)
{
mySerial.printf("%s", packet);
//mySerial.printf("%s\r\n", packet);
readline();
packet[0] = 0;
return true;
}
else
return false;
}
Here is my main code:
#include "mbed.h"
#include "Adafruit_FONA.h"
#define FONA_RST D4
#define FONA_TX D1
#define FONA_RX D0
#define FONA_RI D7 //not used
char replybuffer[255];
Adafruit_FONA_3G fona(FONA_TX, FONA_RX, FONA_RST, FONA_RI);
Serial pc(USBTX, USBRX);
int main()
{
fona.TCPinitialize();
char Timeout[21];
fona.getTCPtimeout(Timeout);
char * Server = "52.14.99.26";
uint16_t Port = 10001;
fona.TCPconnect(Server,Port);
char *Packet = "Pick Up %";
fona.TCPsend(Packet);
fona.TCPclose();
}

Adafruit_FONA_3G::TCPsend() assumes that you pass it a writable buffer. You're passing a read-only buffer. So, replace
char *Packet = "Pick Up %";
with
char Packet[] = "Pick Up %";
The problem is really that your compiler allows you to initialize writable pointers with read-only values. This is a shortcoming of your compiler.

Related

No Matching Function Begin Multicast - Arduino/cpp

I was given a project to convert from ESP8266 to ESP32, and I'm definitely not a coder, but it needs to get done. So I was hoping I could get some guidance/help on how to solve this issue. I'm basically taking previous code from an old project using an ESP8266 WiFi module and converting it over to a more updated module using ESP32. Been compiling and troubleshooting code as I go the best I can, but this one has stumped me.
The error message I'm getting is "No matching function for call to 'WiFiUDP::beginMulticast(IPAddress, IPAddress&, const unsigned int&)'
There are several pages of code, but this is the .cpp file that is currently throwing up an error, and hoping it's able to be resolved with something on this page. Like I said, I'm not a coder, but I have the basics down. Any help on this would be greatly appreciated. Thanks!
#include "Switch.h"
#include <functional>
// Multicast declarations
IPAddress ipMulti(239, 255, 255, 250);
const unsigned int portMulti = 1900;
char packetBuffer[512];
#define MAX_SWITCHES 14
Switch switches[MAX_SWITCHES] = {};
int numOfSwitchs = 0;
//#define numOfSwitchs (sizeof(switches)/sizeof(Switch)) //array size
//<<constructor>>
UpnpBroadcastResponder::UpnpBroadcastResponder(){
}
//<<destructor>>
UpnpBroadcastResponder::~UpnpBroadcastResponder(){/*nothing to destruct*/}
bool UpnpBroadcastResponder::beginUdpMulticast(){
boolean state = false;
Serial.println("Begin multicast ..");
if(UDP.beginMulticast(WiFi.localIP(), ipMulti, portMulti)) {
Serial.print("Udp multicast server started at ");
Serial.print(ipMulti);
Serial.print(":");
Serial.println(portMulti);
state = true;
}
else{
Serial.println("Connection failed");
}
return state;
}
//Switch *ptrArray;
void UpnpBroadcastResponder::addDevice(Switch& device) {
Serial.print("Adding switch : ");
Serial.print(device.getAlexaInvokeName());
Serial.print(" index : ");
Serial.println(numOfSwitchs);
switches[numOfSwitchs] = device;
numOfSwitchs++;
}
void UpnpBroadcastResponder::serverLoop(){
int packetSize = UDP.parsePacket();
if (packetSize <= 0)
return;
IPAddress senderIP = UDP.remoteIP();
unsigned int senderPort = UDP.remotePort();
// read the packet into the buffer
UDP.read(packetBuffer, packetSize);
// check if this is a M-SEARCH for WeMo device
String request = String((char *)packetBuffer);
if(request.indexOf('M-SEARCH') > 0) {
if(request.indexOf("urn:Belkin:device:**") > 0) {
Serial.println("Got UDP Belkin Request..");
// int arrSize = sizeof(switchs) / sizeof(Switch);
for(int n = 0; n < numOfSwitchs; n++) {
Switch &sw = switches[n];
if (&sw != NULL) {
sw.respondToSearch(senderIP, senderPort);
}
}
}
}
}```
The Arduino UDP API as defined by the UDP base class in Arduino core has
uint8_t beginMulticast(IPAddress, uint16_t);
In esp8266 Arduino WiFi the UDP is modified and the first parameter of beginMulticast specifies the network interface to listen to. (Network interfaces are STA, SoftAP, Ethernet etc)
In esp32 Arduino WiFi library beginMulticast has only the standard parameters and listens on all network interfaces.
Your solution is to remove the first parameter in the beginMulticast call.

Adafruit Fona establishes connection with echo server, but doesn't send over any data

Using mbed OS and stm32 nucleo board with Adafruit Fona 3g, I am trying to send data to a server via 3g connection. I am using the .cpp file and .h file posted here: https://os.mbed.com/users/Nels885/code/Adafruit_FONA_3G/file/b18cfba4283a/
The code seems to get stuck on getTCPtimeout. I am having trouble figuring out why this is the case.
I have tried commenting out the getTCPtimeout function to see the results and the code runs through completely, but never establishes a connection with the server.
#include "mbed.h"
#include "Adafruit_FONA.h"
#define FONA_RST D4
#define FONA_TX D1
#define FONA_RX D0
#define FONA_RI D7 //not used
char replybuffer[255];
Adafruit_FONA_3G fona(FONA_TX, FONA_RX, FONA_RST, FONA_RI);
Serial pc(USBTX, USBRX);
int main()
{
fona.TCPinitialize();
pc.printf ("initialize \n");
char *Timeout = "10000000";
fona.getTCPtimeout(Timeout);
pc.printf ("timeout \n");
char * Server = "47.218.188.133";
uint16_t Port = 23;
fona.TCPconnect(Server,Port);
pc.printf ("connect \n");
char * Packet = "Pick Up %";
fona.TCPsend(Packet);
pc.printf ("send \n");
fona.TCPclose();
pc.printf ("close \n");
}
Edit: I was running the code and noticed that after fixing the above issue, the code would get stuck TCPSend function, specifically right before
packet[0] = 0;
which is shown down here:
bool Adafruit_FONA_3G::TCPsend(char *packet)
{
if (strlen(packet) > 0) {
mySerial.printf("%s", packet);
//mySerial.printf("%s\r\n", packet);
readline();
packet[0] = 0;
return true;
} else return false;
}
When commenting out the line, the code would run all the way through. I am still in the process of testing to see if the code still functions as intended, but my question is what exactly is the purpose of packet[0] = 0;?
Adafruit_FONA_3G::getTCPtimeout() assumes that you pass it a writable buffer of size > 20. You're passing a read-only buffer of smaller size. So, replace
char *Timeout = "10000000";
with
char Timeout[21];

How to receive strings from Arduino in C++?

Hey I have problems with receiving strings from Arduino. I am running on linux and I want to use C++ fotr that. I an easily send strings from C++ code to arduino. For that I use C++ code like this.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream arduino("/dev/ttyACM0");
arduino << "Led on\n";
arduino.close();
return 0;
}
So how can I receive strings from Arduino?
I'm not an Arduino expert, but from your code I concluded:
You are using a serial interface to send data
You should connect the serial interface to your computer (with a traditional serial cable, or USB)
Write a C++ app, that opens and received data from serial port. See this!
Find out from Arduino specs, what serial communication parameters are used by Arduino (stop bit, parity bits, baudrate etc) and use these parameters to configure the serial port in your C++ application!
Hope that helps!
Use boost.asio to communicate with a serial device and C++. It works like a charm and is pretty easy to use. See: http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/overview/serial_ports.html and this: Reading from serial port with Boost Asio
The folowing code waits for a response from an arduino. If the response contains "Done" it returns 1. If it didn't find it within the given timeout, it returns -1.
It should not prove that hard to change this code to fit your needs.
int Serial::waitForResponse()
{
const int buffSize = 1024;
char bufferChar[buffSize] = {'\0'};
int counter = 0;
std::string wholeAnswer = "";
int noDataTime = 0;
while(wholeAnswer.find("Done") == std::string::npos) //Done string was found.
{
if(noDataTime > 10000)
{
std::cout << "timeout" << std::endl;
return -1;
}
counter = read(this->hSerial, bufferChar, buffSize - 1);
if(counter > 0)
{
noDataTime = 0;
bufferChar[counter] = '\0';
wholeAnswer += std::string(bufferChar);
} else
{
noDataTime++;
usleep(1000);
}
}
if(!wholeAnswer.empty())
{
return 1;
} else
{
return -1;
}

XBee, external libraries and passing structures as arguments

I have very weird problem with a library I am creating. The library will be used to communicate between Arduino modules using XBee Series 1 modules. Library is very simple wrapper library around Arduino XBee library.
I have one function that reads received packet and sends it back. At the moment it is implemented as a simple "echo" service - the function just displays the data received and sends it back to per-defined address.
At the moment I have three versions of this function, out of which one is not working.
A function taking no arguments: void processPacket()
A function taking structure as a value as an argument: void processPacket(valuesStruct valuesStructData) - THIS VERSION OF THE FUNCTION IS NOT WORKING!
A function taking pointer to the structure as an argument: void processPacket(valuesStruct* valuesStructData)
At this moment I noticed strange behavior in the 2nd version of the function. I do nothing with the passed argument - the content of all three functions is the same. In 2nd case the function reads wrong values from received XBee packet. In the 1st and 3rd case the function performs correctly.
Code:
ExampleLib.h
#ifndef ExampleLib_h
#define ExampleLib_h
#include "Arduino.h"
#include <XBee.h>
#define ADDRESS_BROADCAST 0xffff
#define ADDRESS_PC 0x3333
typedef struct
{
int valA;
int valB;
int valC;
} valuesStruct;
class ExampleLib
{
public:
ExampleLib();
void setSerial(Stream &serial);
boolean tryReceivePacket();
void processPacket();
// THIS FUNCTION IS NOT WORKING!
void processPacket(valuesStruct valuesStructData);
void processPacket(valuesStruct* valuesStructData);
private:
XBee xbee;
Rx16Response rx16;
};
#endif
ExampleLib.cpp
The value read in line byte* packetData = rx16.getData(); is wrong when we trigger processPacket(valuesStruct valuesStructData) function. In other cases the behavior is correct.
#include "Arduino.h"
#include <XBee.h>
#include "ExampleLib.h"
ExampleLib::ExampleLib()
{
xbee = XBee();
rx16 = Rx16Response();
}
void ExampleLib::setSerial(Stream &serial)
{
xbee.setSerial(serial);
}
boolean ExampleLib::tryReceivePacket()
{
xbee.readPacket();
if (xbee.getResponse().isAvailable()) {
// got something
if (xbee.getResponse().getApiId() == RX_16_RESPONSE) {
// got a rx packet
xbee.getResponse().getRx16Response(rx16);
return true;
}
else {
return false;
}
}
else if (xbee.getResponse().isError()) {
//nss.print("Error reading packet. Error code: ");
//nss.println(xbee.getResponse().getErrorCode());
// or flash error led
return false;
}
return false;
}
void ExampleLib::processPacket()
{
byte* packetData = rx16.getData();
byte dataLength = rx16.getDataLength();
Serial.print("START L:");
Serial.println(dataLength);
for (int i = 0; i < dataLength; i++) {
Serial.print(packetData[i]);
Serial.print(" - ");
}
Serial.println("END");
//16-bit addressing: Enter address of remote XBee, typically the coordinator
Tx16Request tx = Tx16Request(ADDRESS_PC, packetData, sizeof(packetData));
xbee.send(tx);
}
void ExampleLib::processPacket(valuesStruct valuesStructData)
{
processPacket();
}
void ExampleLib::processPacket(valuesStruct* valuesStructData)
{
processPacket();
}
Arduino sketch
#include <XBee.h>
#include <ExampleLib.h>
ExampleLib exampleLibObj = ExampleLib();
void setup()
{
Serial.begin(9600);
exampleLibObj.setSerial(Serial);
}
void loop()
{
boolean isPacketReceived = exampleLibObj.tryReceivePacket();
if (isPacketReceived) {
// leave only one section, the rest should be commented
//Section 1: working
exampleLibObj.processPacket();
//Section 2: not working
// valuesStruct test;
// test.valA = 0;
// test.valB = 0;
// test.valC = 0;
// exampleLibObj.processPacket(test);
//Section 3: working
// valuesStruct* test;
// test->valA = 0;
// test->valB = 0;
// test->valC = 0;
// exampleLibObj.processPacket(test);
}
}
I am really puzzled why in this one case function is performing differently. Looking forward to any suggestions to that issue.
Thanks,
Michal
Are you sure it isn't your section 3 that's causing problems? Because you're declaring a pointer to a structure, but not allocating memory for that structure.
You'd typically write your code like this:
valuesStruct test;
test.valA = 0;
test.valB = 0;
test.valC = 0;
//Section 2: not working
exampleLibObj.processPacket(test);
//Section 3: working
exampleLibObj.processPacket(&test);
But you also wouldn't typically pass a structure to a function -- you'd pass a pointer to that structure. There really isn't a need for your second sample.

inotify notifies of a new file wrongly multiple times

Using inotify to monitor a directory for any new file created in the directory by adding a watch on the directory by
fd = inotify_init();
wd = inotify_add_watch(fd, "filename_with_path", IN_CLOSE_WRITE);
inotify_add_watch(fd, directory_name, IN_CLOSE_WRITE);
const int event_size = sizeof(struct inotify_event);
const int buf_len = 1024 * (event_size + FILENAME_MAX);
while(true) {
char buf[buf_len];
int no_of_events, count = 0;
no_of_events = read(fd, buf, buf_len);
while(count < no_of_events) {
struct inotify_event *event = (struct inotify_event *) &buf[count];
if (event->len) {
if (event->mask & IN_CLOSE_WRITE) {
if (!(event->mask & IN_ISDIR)) {
//It's here multiple times
}
}
}
count += event_size + event->len;
}
When I scp a file to the directory, this loops infinitely. What is the problem with this code ? It shows the same event name and event mask too. So , it shows that the event for the same, infinite times.
There are no break statements. If I find an event, I just print it and carry on waiting for another event on read(), which should be a blocking call. Instead, it starts looping infinitely. This means, read doesn't block it but returns the same value for one file infinitely.
This entire operation runs on a separate boost::thread.
EDIT:
Sorry all. The error I was getting was not because of the inotify but because of sqlite which was tricky to detect at first. I think I jumped the gun here. With further investigation, I did find that the inotify works perfectly well. But the error actually came from the sqlite command : ATTACH
That command was not a ready-only command as it was supposed to. It was writing some meta data to the file. So inotify gets notification again and again. Since they were happening so fast, it screwed up the application.I finally had to breakup the code to understand why.
Thanks everyone.
I don't see anything wrong with your code...I'm running basically the same thing and it's working fine. I'm wondering if there's a problem with the test, or some part of the code that's omitted. If you don't mind, let's see if we can remove any ambiguity.
Can you try this out (I know it's almost the same thing, but just humor me) and let me know the results of the exact test?
1) Put the following code into test.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/inotify.h>
int main (int argc, char *argv[])
{
char target[FILENAME_MAX];
int result;
int fd;
int wd; /* watch descriptor */
const int event_size = sizeof(struct inotify_event);
const int buf_len = 1024 * (event_size + FILENAME_MAX);
strcpy (target, ".");
fd = inotify_init();
if (fd < 0) {
printf ("Error: %s\n", strerror(errno));
return 1;
}
wd = inotify_add_watch (fd, target, IN_CLOSE_WRITE);
if (wd < 0) {
printf ("Error: %s\n", strerror(errno));
return 1;
}
while (1) {
char buff[buf_len];
int no_of_events, count = 0;
no_of_events = read (fd, buff, buf_len);
while (count < no_of_events) {
struct inotify_event *event = (struct inotify_event *)&buff[count];
if (event->len){
if (event->mask & IN_CLOSE_WRITE)
if(!(event->mask & IN_ISDIR)){
printf("%s opened for writing was closed\n", target);
fflush(stdout);
}
}
count += event_size + event->len;
}
}
return 0;
}
2) Compile it with gcc:
gcc test.c
3) kick it off in one window:
./a.out
4) in a second window from the same directory try this:
echo "hi" > blah.txt
Let me know if that works correctly to show output every time the file is written to and does not loop as your code does. If so, there's something important your omiting from your code. If not, then there's some difference in the systems.
Sorry for putting this in the "answer" section, but too much for a comment.
My guess is that read is returning -1 and since you dont ever try to fix the error, you get another error on the next call to read which also returns -1.