@Dave Good suggestion. I tried sending 2 packets a second instead of 5 and the results were pretty interesting. The same packet retransmission error happened the exact amount of time from the time the first packet was sent. So it still failed at 24 seconds but less than half the number of packets as before were successfully sent. (only about 50 instead of 120 during the 24 seconds) Does this seem to point to anything?
I have attached my Spark Core firmware as well as my related node js TCP/ UDP server app. Let me know if you have any questions regarding any of the code.
Thanks so much for all your help, really appreciate it!
Spark Core Firmware
//Magnetic Sensor Spark Core App
//Include header to disable cloud connectivity by default
#include "application.h"
#include "spark_disable_cloud.h"
TCPClient tcpclient; //Define TCP client object
UDP Udp; //Define UDP object
IPAddress serverIP; //Define Server IP address of IPAddress data type
int UDPport = 8000; //UDP port number
int TCPport = 9000; //TCP port number
bool receivedIP = false; //Boolean to indicate whether the IP has been recieved yet
unsigned long interval = 500; //Time interval between each transmit event (ms)
unsigned long previousMillis = 0; //Time of previous transmit event
byte array[32]; //Byte array to be transmitted to server over TCP connection
String coreID = String(1); //Spark Core ID number
String null = " "; //Null character
String xlabel = "x"; //X axis label
String ylabel = "y"; //Y axis label
String zlabel = "z"; //Z axis label
//Function to transmit Magnetic Field data from Spark Core pins
void transmit()
{
//If device is connected to TCP server, read and transmit data
if (tcpclient.connected())
{
//Assign current milliseconds passed since Spark Core turned on to currentMillis
unsigned long currentMillis = millis();
//If time passed since last transmit is larger or equal than interval, read and send data
if( currentMillis - previousMillis >= interval) {
//Assign current time to previous to reset interval counter
previousMillis = currentMillis;
//Read and scale pin voltage values
String xval = String((analogRead(A0)*3.3)/4095);
String yval = String((analogRead(A1)*3.3)/4095);
String zval = String((analogRead(A2)*3.3)/4095);
//Insert voltage readings into byte array
for(int i=0;i<7;i++)
{ array[i+5] = xval[i]; }
for(int i=0;i<7;i++)
{ array[i+15] = yval[i]; }
for(int i=0;i<7;i++)
{ array[i+25] = zval[i]; }
//Print status to Serial connection
Serial.println("Sending TCP packet");
//Transmit byte array
tcpclient.write(array,32);
}
}
else //If not connected to client, delay then attempt to reconnect
{
//Blink LED slowly to indicate trying to connect to TCP server (delay 4 seconds)
for(int i=0;i<2;i++)
{
digitalWrite(D7, HIGH); // Turn ON the LED
delay(1000); // Wait for 1000mS = 1 second
digitalWrite(D7, LOW); // Turn OFF the LED
delay(1000); // Wait for 1 second
}
//Print status to Serial connection
Serial.println("Attempting to connect to: ");
Serial.println(serverIP);
//Connect to TCP server at serverIP on port TCPport
tcpclient.connect(serverIP, TCPport);
}
}
//Function to listen for UDP packets with server IP broadcast by UDP server app
void UDPListen()
{
//Print status to Serial connection
Serial.println("UDP test executing");
//Blink LED fast to indicate waiting for UDP packet with IP (delay 4 seconds)
for(int i=0;i<10;i++)
{
digitalWrite(D7, HIGH); // Turn ON the LED
delay(100); // Wait for 200mS = .2 second
digitalWrite(D7, LOW); // Turn OFF the LED
delay(100); // Wait for .2 second
}
//Look for existance of UDP packet in Spark Core buffer
Udp.parsePacket();
//If remotePort of UDP packet received is the same as application
//UDP port, assign IP of remote connection to serverIP and set
//recievedIP boolean to true
if(Udp.remotePort() == UDPport)
{
serverIP = Udp.remoteIP();
receivedIP = true;
}
else //Else, close UDP connection and reopen it to continue listening
{
Udp.stop();
delay(100);
Udp.begin(UDPport);
}
}
//Initial setup (code run only once at startup)
void setup()
{
Serial.begin(9600); //Begin Serial connection to send status of Spark Core
Udp.begin(UDPport); //Listen for incoming UDP packets from UDP server
//Initialize Spark Core pins
pinMode(A0, INPUT);
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode(D7, OUTPUT);
//Assign byte array labels and spaces
array[0] = null[0];
array[1] = coreID[0];
array[2] = null[0];
array[3] = xlabel[0];
array[4] = null[0];
array[12] = null[0];
array[13] = ylabel[0];
array[14] = null[0];
array[22] = null[0];
array[23] = zlabel[0];
array[24] = null[0];
}
//Code to infinitely loop after setup has run
void loop()
{
//If device is connected to Wifi, listen for UDP packets then connect to TCP server
if (WiFi.status() == WIFI_ON) {
//If server IP address was received, transmit data, else listen for UDP packet
if(receivedIP)
{
transmit();
}
else
{
UDPListen();
}
}
}
Node.js TCP/ UDP application
//-----------------------------------------------------------------------------------------------------------------------
// UDP server that broadcasts UDP packet to network every 5 seconds
//Declare required variables
var dgram = require('dgram'); //Include datagram library
var testMessage = 'testmessage'; //Define testMessage variable (packet payload)
var broadcastAddress = '192.168.1.255'; //Define network broadcast IP address
var UDPPort = 8000; //Define UDP port
//Create UDP socket
var udp_socket = dgram.createSocket('udp4');
//Bind Socket on UDPport and set to broadcast packets
udp_socket.bind(UDPPort, '0.0.0.0', function() {
udp_socket.setBroadcast(true);
});
//Send UDP packet every 5 seconds
var udpInterval = setInterval(function () {
udp_socket.send(new Buffer(testMessage),
0,
testMessage.length,
UDPPort,
broadcastAddress
);
}, 5000);
//-----------------------------------------------------------------------------------------------------------------------
//TCP server to connect and communicate with Spark Core TCP client
//Declare required variables
var net = require('net'); //Include net library
var fs = require('fs'); //Include filestream library
var os = require('os') //Include OS library
var tcpPORT = 9000; //Define TCP server port
var crlf = new Buffer(2); //Create buffer to generate new line
crlf[0] = 0xD; //CR - Carriage return character
crlf[1] = 0xA; //LF - Line feed character
//-----------------------------------------------------------------------------------
//Get server IP address
var interfaces = os.networkInterfaces();
var serverip = [];
for (k in interfaces) {
for (k2 in interfaces[k]) {
var address = interfaces[k][k2];
if (address.family == 'IPv4' && !address.internal) {
serverip.push(address.address)
}
}
}
//-----------------------------------------------------------------------------------
//Get date and time for timestamp
function getDateTime() {
var date = new Date();
var hour = date.getHours();
hour = (hour < 10 ? "0" : "") + hour;
var min = date.getMinutes();
min = (min < 10 ? "0" : "") + min;
var sec = date.getSeconds();
sec = (sec < 10 ? "0" : "") + sec;
var mil = date.getMilliseconds();
mil = (mil < 10 ? "0" : "") + mil;
var year = date.getFullYear();
var month = date.getMonth() + 1;
month = (month < 10 ? "0" : "") + month;
var day = date.getDate();
day = (day < 10 ? "0" : "") + day;
return year + ":" + month + ":" + day + ":" + hour + ":" + min + ":" + sec + "." + mil;
}
//-----------------------------------------------------------------------------------
//Tell user what IP address and port the TCP server is listening on
console.log("TCP Server listening at " + serverip[0] + " : " + tcpPORT);
//Define server
var server = net.createServer(function (socket) {
var remoteaddress = socket.remoteAddress,
remoteport = socket.remotePort;
//Tell user when a device has connected to TCP server
console.log("CONNECTED: " + socket.remoteAddress + ":" + socket.remotePort);
//Read and store data when data event is triggered
socket.on('data', function (data) {
data = data.toString();
fs.appendFile("magdatacore1.txt", data + " at: " + getDateTime() + crlf);
});
}).listen(tcpPORT);
//-----------------------------------------------------------------------------------------------------------------------