I have an escape room puzzle that I am creating with multiple Arduinos and Node Red for a back end. A lot of moving parts in the back end, and for the most part things are responding correctly. I have one arduino puzzle that is refusing to send Client.Connect commands to Node-red. I have checked my firewall to ensure that wasn't the problem. And no logs are in there showing a block. Using wireshark, I can see that the arduino mega is sending ARP broadcasts trying to find the Node-Red server. (Node Red located at 172.16.40.100, puzzle located at 172.16.40.111).
This is the entry I get in Wireshark
6 0.000000 de:ad:02:00:00:11 Broadcast ARP 60 Who has 172.16.40.100? Tell 172.16.40.111
The code to connect to Node-red is copy-paste across multiple puzzles that have some identical code segments, so the setup to Node-Red is copy/paste between sketches.
Here is the code:
#include <SPI.h>
#include <Ethernet.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <aREST.h>
#include <avr/wdt.h>
#define PIN 5;
#define debug
const byte chips = 1;
unsigned long delaytime = 100;
int randNumber;
//ship reed variables
int ship_sw[] = {0, 30, 32, 34, 36};
int ship_sw_reed[] = {0, 0, 0, 0, 0};
int ship_solved[] = {0, 0, 0, 0, 0};
int ship_override[] = {0, 0, 0, 0, 0};
int allSolved[] = {0, 1, 1, 1, 1};
int decryptSeqChar[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
String decryptSequence;
boolean resetTriggered = false;
bool solved = false;
int xloop = 0;
String nextGameCode = "";
bool gameCodeSent = false;
int gameStatus = 0; // 0=default, 1=startup. 2=start, 3=solved, 4=done, 5=shutdown
// aREST to NodeRed
int HTTP_PORT = 1880;
String HTTP_METHOD = "GET";
char HOST_NAME[] = "172.16.40.100";
String PATH_NAME = "/api";
String queryString = "";
// Create aREST instance
aREST rest = aREST();
// The MAC Address and IP for the game
byte mac[] = {
0xDE, 0xAD, 0x02, 0x00, 0x00, 0x11
};
IPAddress ip(172, 16, 40, 111);
EthernetServer server(80);
EthernetClient client;
// Create Reset function
void(* resetFunc) (void) = 0; //declare reset function @ address 0
void setup() {
// Open serial communications and wait for port to open:
#ifdef debug
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
#endif
// start the Ethernet connection:
Ethernet.begin(mac);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
#ifdef debug
Serial.println(F("Ethernet shield was not found. Sorry, can't run without hardware. :("));
#endif
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
#ifdef debug
Serial.println(F("Attempting to obtain IP from DHCP, stand by..."));
#endif
delay(1000);
if (Ethernet.begin(mac) == 0) {
// Failed to configure ethernet using DHCP, reverting to static IP
#ifdef debug
Serial.print(F("Failed to obtain DHCP address, reverting to "));
Serial.println(ip);
#endif
Ethernet.begin(mac, ip);
} else {
// Obtained DHCP address
#ifdef debug-.
Serial.print(F("Received IP: "));
Serial.println(Ethernet.localIP());
#endif
}
while (Ethernet.linkStatus() == LinkOFF) {
//Serial.println(F("Ethernet cable is not connected."));
delay(500);
}
if (client.connect(HOST_NAME, HTTP_PORT)) {
NodeRedUpdate("?game=battleship&action=startup");
gameStatus = 1;
} else {
Serial.println(F("Failed connecting to NodeRed Server"));
}
rest.function("favicon.ico", favIcon);
rest.function("gamePiece1", setGamePiece1);
rest.function("gamePiece2", setGamePiece2);
rest.function("gamePiece3", setGamePiece3);
rest.function("gamePiece4", setGamePiece4);
rest.function("gameState", setGameState);
rest.function("gameReset", setGameReset);
rest.function("giveCode", giveNextCode);
rest.function("api", returnAPI);
rest.set_id("011");
rest.set_name("Epicenter_Battleship");
delay(50);
// Ship Status
for (int x = 1; x < 5; x++) {
pinMode(ship_sw[x], INPUT);
if (digitalRead(ship_sw[x]) == 1) {
Serial.println("?game=battleship&action=ship" + String(x) + "&command=off");
NodeRedUpdate("?game=battleship&action=ship" + String(x) + "&command=off");
} else if (digitalRead(ship_sw[x]) == 0) {
Serial.println("?game=battleship&action=ship" + String(x) + "&command=on");
NodeRedUpdate("?game=battleship&action=ship" + String(x) + "&command=on");
}
#ifdef debug
Serial.print(F("Ship "));
Serial.print(x);
Serial.print(F(": "));
Serial.println(digitalRead(ship_sw[x]));
#endif
}
#ifdef debug
Serial.println(F("Ship switches initializied."));
Serial.println(F("Ready for REST API."));
#endif
}
void loop() {
EthernetClient client = server.available();
rest.handle(client);
//check if gameCode received
for (int x = 1; x < 5; x++) {
ship_sw_reed[x] = digitalRead(ship_sw[x]);
}
if (gameStatus = 2) {
while (solved == false) {
for (int x = 1; x < 5; x++) {
// If ship is placed and then goes untripped
if (ship_sw_reed[x] == 0 && ship_solved[x] == 1 && ship_override[x] == 0) {
ship_solved[x] = 0;
NodeRedUpdate("?game=battleship&action=ship" + String(x) + "&command=off");
#ifdef debug
Serial.print(F("Ship "));
Serial.print(x);
Serial.println(F(" is no longer solved."));
#endif
}
// If ship is placed and not solved
if ((ship_sw_reed[x] == 1 && ship_solved[x] == 0) || (ship_override[x] == 1 && ship_solved[x] == 0)) {
ship_solved[x] = 1;
NodeRedUpdate("?game=battleship&action=ship" + String(x) + "&command=on");
#ifdef debug
if (ship_override[x] == true) {
Serial.print(F("Override : "));
}
Serial.print(F("Ship "));
Serial.print(x);
Serial.println(F(" is now placed correctly."));
#endif
}
if (ship_solved[x] == 1) {
decryptSeqChar[x] = ((char) randomDecryptChar);
} else {
decryptSeqChar[x] = " ";
}
// If all ships are placed correctly.
if (array_cmp(ship_solved, allSolved, 5, 5) == true) {
NodeRedUpdate("?game=battleship&action=game&command=solved");
solved = true;
gameStatus = 3;
#ifdef debug
Serial.println(F("You WIN!!"));
Serial.println(decryptSequence);
#endif
}
}
break;
}
delay(100);
}
}
//----------------------------------------------------------
// REST COMMANDS
int setGameState(String gameState) {
if (gameState == "start") {
#ifdef debug
Serial.println(F("Remotely Triggered: Game Begin."));
#endif
gameStatus = 2;
NodeRedUpdate("?game=battleship&action=start");
} else if (gameState == "solved") {
#ifdef debug
Serial.println(F("Remotely Triggered: Game Solved."));
#endif
gameStatus = 3;
NodeRedUpdate("?game=battleship&action=solved");
} else if (gameState == "done") {
#ifdef debug
Serial.println(F("Remotely Triggered: Game Reset."));
#endif
gameStatus = 4;
NodeRedUpdate("?game=battleship&action=done");
}
}
void setGameReset() {
#ifdef debug
Serial.println(F("Remotely Triggered: Game Reset."));
#endif
gameStatus = 1;
resetFunc();
}
int giveNextCode(String GameCodeReceived) {
nextGameCode = GameCodeReceived;
gameCodeSent = true;
randomNumberShowing(50);
//updateDisplay();
#ifdef debug
Serial.print(F("Next Game Code received: "));
Serial.println(nextGameCode);
#endif
}
int setGamePiece1(String piecePlaced) {
if (piecePlaced == "yes") {
setGamePiece(1, true);
} else if (piecePlaced == "no") {
setGamePiece(1, false);
}
}
int setGamePiece2(String piecePlaced) {
if (piecePlaced == "yes") {
setGamePiece(2, true);
} else if (piecePlaced == "no") {
setGamePiece(2, false);
}
}
int setGamePiece3(String piecePlaced) {
if (piecePlaced == "yes") {
setGamePiece(3, true);
} else if (piecePlaced == "no") {
setGamePiece(3, false);
}
}
int setGamePiece4(String piecePlaced) {
if (piecePlaced == "yes") {
setGamePiece(4, true);
} else if (piecePlaced == "no") {
setGamePiece(4, false);
}
}
int setGamePiece(int gamePiece, bool piecePlaced) {
#ifdef debug
Serial.print(F("Game piece "));
Serial.print(gamePiece);
Serial.println(F(" called for."));
#endif
#ifdef debug
Serial.print(F("Remotely Triggered : Game piece "));
Serial.print(gamePiece);
#endif
if (piecePlaced == true) {
#ifdef debug
Serial.println(F(" placed correctly."));
#endif
ship_override[gamePiece] = 1;
} else if (piecePlaced == false) {
#ifdef debug
Serial.println(F(" not placed correctly."));
#endif
ship_override[gamePiece] = 0;
}
return 001;
}
int returnAPI(String apiString) {
#ifdef debug
Serial.println(F("API received."));
#endif
}
int favIcon() { // fixes browser double call of functions
}
int randomDecryptChar() {
randNumber = random(0, 9);
return randNumber;
}
void randomNumberShowing(int totalRuns) {
xloop = 0;
while (xloop <= totalRuns)
{
for (int z = 1; z < 9; z++) {
decryptSeqChar[z] = (randomDecryptChar());
}
Serial.print(decryptSeqChar[1]);
Serial.print(decryptSeqChar[2]);
Serial.print(decryptSeqChar[3]);
Serial.println(decryptSeqChar[4]);
delay(50);
xloop++;
}
}
boolean array_cmp(int *a, int *b, int len_a, int len_b) {
int n;
// if their lengths are different, return false
if (len_a != len_b) return false;
// test each element to be the same. if not, return false
for (n = 0; n < len_a; n++) if (a[n] != b[n]) return false;
//ok, if we have not returned yet, they are equal :)
return true;
}
int NodeRedUpdate(String query) {
if (client.connect(HOST_NAME, HTTP_PORT)) {
Serial.println(HTTP_METHOD + " " + PATH_NAME + query + " HTTP / 1.1");
client.println(HTTP_METHOD + " " + PATH_NAME + query + " HTTP / 1.1");
client.println("Host : " + String(HOST_NAME));
client.println(F("Connection : close"));
client.println();
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.print(c);
}
}
client.stop();
//Serial.println(F("disconnected"));
} else {
Serial.println(F("connection failed"));
}
}
Any ideas? I am trying to send it commands to the aRest of 172.16.40.111/gameState=start. Which it does not then send a reply message back to Node-Red. (all api calls from Node-Red to arduinos are followed up with a return api call from the arduino acknowledging the call and triggering the next steps in Node-Red.