Hello!
I'm having trouble with HTTP requests I'm making from my DigiX to a python-based web-server. I've had trouble with it working for a few hours and then it drops out. I've tried a number of different ways of writing the post requests (manually with client.connect and client.print, then again with the client.post method) but I've not really had much luck improving it.
When I ran it as a CGI script behind nginx, I was getting "400 - Bad Request" errors interspersed with correctly formed requests. I've since set up the same web-server on my windows machine and run a packet-capture with WireShark (on the server side obviously).
It looks like occasionally I get AT commands in the network traffic. I see:
+++AA+E
AT+TCPDIS=off
AT+NETP
AT+NETP=TCP,CLIENT,80,192.168.0.8
AT+TCPDIS=On
AT+TCPLK
It seems likely that I'm leaking connections. I've tried using client.begin(9600, true) and plain old client.begin() and neither eradicate the issue.
Any help gratefully received! I'm trying to create an RF24Network based home sensor network, where the sensor nodes relay readings to a web-server, via the DigiX.
/*
This is a mix of my own work and heavily inspired by RF24 examples from maniacbug.
*/
#include <DigiFi.h>
#include <RF24.h>
#include <RF24Network.h>
#include <SPI.h>
#include "printf.h"
//#define DEBUG /* use this to turn on extra Serial debugging statements */
// DIGIFI SETUP
DigiFi wifi;
// ThingSpeak SETUP
//IPAddress server(192,168,0,202);
char server[] = "192.168.0.8";
uint16_t server_port = 80;
//char server[] = "api.thingspeak.com";
String tempAPIKey = "";
String energyAPIKey = "";
// Variable Setup
int failedCounter = 0;
// RF24 SETUP
// nRF24L01(+) radio attached using Getting Started board
RF24 radio(53,52);
// Network uses that radio
RF24Network network(radio);
// Address of our node
const uint16_t this_node = 0;
// decimal precision. Can't go higher than 2 decimal places
// otherwise we could get integer overflow (8-bit, 255 max value).
const uint8_t decimal_precision = 100;
// Structure of our payload
struct payload_t
{
uint16_t node_id;
uint8_t d_value;
uint8_t p_value;
uint16_t d_power;
};
//value type is:
// 0: temperature
// 1: power
// etc for more
String sensorData[] = {
"field1=0",
"field2=0",
};
String powerData[] = {
"field1=0",
"field2=0",
};
int led = 13;
void setup(void)
{
pinMode(led, OUTPUT);
Serial.begin(9600);
//DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal before continuing
//while(!Serial.available()){
// Serial.println("Enter any key to begin");
// delay(1000);
//}
// END DigiX trick
Serial.println("DigiX/R24Network/rx/ThingSpeak");
printf_begin();
Serial.println("printf begin");
SPI.begin();
Serial.println("SPI begin");
radio.setRetries(15,15);
radio.begin();
blink(2);
Serial.println("radio begin");
delay(2000);
network.begin(/*channel*/ 90, /*node address*/ this_node);
Serial.println("Awaiting data");
blink(3);
delay(2000);
// START turn on wifi
startDigiFi();
Serial.println("Connected to network");
// END turn on wifi
blink(4);
}
void loop(void)
{
// Pump the network regularly
network.update();
// Is there anything ready for us?
while ( network.available() )
{
// If so, grab it and print it out
RF24NetworkHeader header;
payload_t payload;
network.read(header,&payload,sizeof(payload));
kkprintf("Received temp: ");
float a = (float) payload.d_value;
float b = ((float) payload.p_value)/((float) decimal_precision);
float t = a + b;
kkprintf("%.2f Celsius | from Node: %u | with ID: %u\r\n",
t,
header.from_node,
header.id);
if (header.from_node < 3) {
//just switch whichever of the two readings we are supposed to be sending
//sensorData[header.from_node-1] = "field"+String(header.from_node)+"="+String(t);
String tData = "node_id="+String(header.from_node)+"&type=T&value="+String(t);
#ifdef DEBUG
Serial.print("Sending: ");
Serial.println(tData);
#endif /* DEBUG */
updateThingSpeak(tData, tempAPIKey);
}
if (header.from_node == 3) {
// Send temperature first
String tData = "node_id="+String(header.from_node)+"&type=T&value="+String(t);
#ifdef DEBUG
Serial.print("Sending: ");
Serial.println(tData);
#endif // DEBUG
updateThingSpeak(tData, energyAPIKey);
// Send power next
String tData2 = "node_id="+String(header.from_node)+"&type=P&value="+String((long)payload.d_power,DEC);
#ifdef DEBUG
Serial.print("Sending: ");
Serial.println(tData);
#endif // DEBUG
updateThingSpeak(tData2, energyAPIKey);
}
if (failedCounter > 3){ startDigiFi(); }
}
}
void blink(int times) {
for (int i=0;i < times;i++) {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(200); // wait for a 1/2 second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(200); // wait for a 1/2 second
}
}
void updateThingSpeak(String tsData, String apiKey)
{
blink(1);
if (wifi.post(server,"/data",tsData)) //"192.168.0.202"
{
Serial.println("POSTed");
#ifdef DEBUG
Serial.println();
Serial.println(wifi.body());
#endif
failedCounter = 0;
}
else
{
failedCounter++;
#ifdef DEBUG
Serial.println("Sending data to ThingSpeak failed ("+String(failedCounter, DEC)+")");
Serial.println();
#endif
}
blink(2);
}
void startDigiFi()
{
Serial.println("Connecting Arduino to network...");
Serial.println();
//wifi.stop();
delay(1000);
// Connect to network amd obtain an IP address using DHCP
wifi.begin(9600, true);
//wifi.begin();
//wifi.setDebug(true);
while (wifi.ready() != 1)
{
Serial.println("Connecting to network...");
delay(1000);
}
delay(1000);
}
PS - there's a certain amount of junk code in here left over from when I was trying to convert the thingspeak example. I'm not using thingspeak anymore, but a custom-written backend in python (web.py). It's pretty trivial, POST submits data, GET retrieves it and highcharts make it look pretty.