Skip to content

Instantly share code, notes, and snippets.

@sytone
Created November 4, 2015 01:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sytone/de62d298ffda246ee20d to your computer and use it in GitHub Desktop.
Save sytone/de62d298ffda246ee20d to your computer and use it in GitHub Desktop.
Arduino Code for Garage Node
/*
This proram is for a node that is always powered, do not
use this if you want a low powered node on your network.
This node will be subscribing and listening for MQTT
messages all the time and also sending out messages
when state changes occur.
*/
#include <RF24Mesh_config.h>
#include <RF24.h>
#include <SPI.h>
#include <RF24Mesh.h>
#include <RF24Network.h>
#include <stdlib.h>
//#include <printf.h>
#include <RF24Ethernet.h>
#include <PubSubClient.h>
#if !defined __arm__ && !defined __ARDUINO_X86__
#include <EEPROM.h>
#endif
/*
* Comment this line out when you are deploying the
* code for the last time.
*/
#define DEBUG
/* Configure the node properties here
* NOTE: This assumes all nodes, Gateway and MQTT brokers are in same subnet.
*/
#define HA_NODE_NETWORK_ID 5 // 5-253
#define HA_NODE_NETWORK_GW_ID 2 // 5-253
#define HA_NODE_NETWORK_MQTT_ID 2 // 5-253
/* General networking configuration */
#define HA_NODE_NETWORK_OCT_ONE 10
#define HA_NODE_NETWORK_OCT_TWO 10
#define HA_NODE_NETWORK_OCT_THREE 2
#define HS_NODE_MESH_CONNECTIVITY 30000 // Time in ms between mesh connectivity checks.
// macros from DateTime.h
/* Useful Constants */
#define SECS_PER_MIN (60UL)
#define SECS_PER_HOUR (3600UL)
#define SECS_PER_DAY (SECS_PER_HOUR * 24L)
/* Useful Macros for getting elapsed time */
#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN)
#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN)
#define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR)
#define elapsedDays(_time_) ( _time_ / SECS_PER_DAY)
#define RELAY_ON 0
#define RELAY_OFF 1
#define RELAY_1 4
#define RELAY_2 5
#define SWITCH_1 2
#define SWITCH_2 3
#define DOOR_1_STATE "HOME/Garage/Door1/STATE"
#define DOOR_2_STATE "HOME/Garage/Door2/STATE"
#define DOOR_1_CMD "HOME/Garage/Door1/CMD"
#define DOOR_2_CMD "HOME/Garage/Door2/CMD"
#define DOOR_STATE_POLL_FREQUENCY 10000
#define HEARTBEAT_PIN 10
#define TEMP_SENSOR 5
#define GARAGE_TEMP "HOME/Garage/Temperature"
/*
* Configure the radio CE & CS pins
* If you used the guides at http://www.sytone.com these should match your
* configuration on the Arduino.
*/
RF24 radio(7, 8);
RF24Network network(radio);
RF24Mesh mesh(radio, network);
RF24EthernetClass RF24Ethernet(radio, network, mesh);
IPAddress mqttServer(HA_NODE_NETWORK_OCT_ONE, HA_NODE_NETWORK_OCT_TWO, HA_NODE_NETWORK_OCT_THREE, HA_NODE_NETWORK_MQTT_ID);
// RF24 Version
EthernetClient ethClient;
PubSubClient mqttClient(ethClient);
// Internal vars
uint32_t counter = 0;
uint32_t reqTimer = 0;
long mesh_timer = 0;
long doorOpenTimer = 0;
char mqttClientId[10];
long relaytest = 0;
boolean relayFlip = 0;
void setup()
{
digitalWrite(RELAY_1, RELAY_OFF);
digitalWrite(RELAY_2, RELAY_OFF);
pinMode(RELAY_1, OUTPUT);
pinMode(RELAY_2, OUTPUT);
digitalWrite(RELAY_1, RELAY_OFF);
digitalWrite(RELAY_2, RELAY_OFF);
pinMode(SWITCH_1, INPUT); // switchPin is an input
digitalWrite(SWITCH_1, HIGH); // Activate internal pullup resistor
pinMode(SWITCH_2, INPUT); // switchPin is an input
digitalWrite(SWITCH_2, HIGH); // Activate internal pullup resistor
pinMode(HEARTBEAT_PIN, OUTPUT); // switchPin is an input
pinMode(TEMP_SENSOR, INPUT);
Serial.begin(115200);
// Setup the Node Client ID
String mqttClientID = "HANODE";
mqttClientID += HA_NODE_NETWORK_ID;
mqttClientID.toCharArray(mqttClientId, 10);
publishNodeLog("Start");
IPAddress myIP(HA_NODE_NETWORK_OCT_ONE, HA_NODE_NETWORK_OCT_TWO, HA_NODE_NETWORK_OCT_THREE, HA_NODE_NETWORK_ID);
Ethernet.begin(myIP);
mesh.begin();
IPAddress gwIP(HA_NODE_NETWORK_OCT_ONE, HA_NODE_NETWORK_OCT_TWO, HA_NODE_NETWORK_OCT_THREE, HA_NODE_NETWORK_GW_ID);
Ethernet.set_gateway(gwIP);
mqttClient.setServer(mqttServer, 1883);
mqttClient.setCallback(callback);
#ifdef DEBUG
Serial.println(F("** Network Address"));
Serial.print(F(" NodeID: "));
Serial.print(mesh._nodeID);
Serial.print("\t");
Serial.print(F(" RF24Network Address: "));
Serial.println(mesh.mesh_address, OCT);
Serial.print(F(" MQTT Client: "));
Serial.print(mqttClientId);
Serial.print("\t");
Serial.print(F(" MQTT Address: "));
Serial.print(mqttClient.getIp(), OCT);
Serial.print(":");
Serial.println(mqttClient.getPort());
Serial.println();
Serial.println(F("**********************************"));
#endif
// Allow the hardware to sort itself out
delay(4000);
mesh_timer = millis();
doorOpenTimer = millis();
relaytest = millis();
}
void loop()
{
if (!mqttClient.connected()) {
reconnect();
}
mqttClient.loop();
// Optional: If the node needs to move around physically, or using failover nodes etc.,
// enable address renewal
if (millis() - mesh_timer > HS_NODE_MESH_CONNECTIVITY) { //Every 30 seconds, test mesh connectivity
mesh_timer = millis();
if (!mesh.checkConnection()) {
//refresh the network address
mesh.renewAddress();
publishNodeLog("Renewed Mesh Address.");
}
else {
publishNodeLog("Heartbeat");
digitalWrite(HEARTBEAT_PIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(250); // wait for a second
digitalWrite(HEARTBEAT_PIN, LOW); // turn the LED off by making the voltage LOW
float farh = ((((analogRead(TEMP_SENSOR) / 1024.0) * 5000) / 10) * 9) / 5 + 32;
char temp[6];
dtostrf(farh, 6, 4, temp);
publishMessage(GARAGE_TEMP, temp);
}
}
if (millis() - doorOpenTimer > DOOR_STATE_POLL_FREQUENCY) {
doorOpenTimer = millis();
if (digitalRead(SWITCH_1) == 0) {
publishMessage(DOOR_1_STATE, "OPEN");
}
else {
publishMessage(DOOR_1_STATE, "CLOSED");
}
if (digitalRead(SWITCH_2) == 0) {
publishMessage(DOOR_2_STATE, "OPEN");
}
else {
publishMessage(DOOR_2_STATE, "CLOSED");
}
}
}
void publishNodeLog(char* message) {
String nodeMessage = mqttClientId;
nodeMessage += ":";
nodeMessage += getTimeString();
nodeMessage += ":";
nodeMessage += message;
Serial.println(nodeMessage.c_str());
String mqttTopic = "HOME/Test/Mesh/";
mqttTopic += mqttClientId;
if (mqttClient.connected()) {
mqttClient.publish(mqttTopic.c_str(), nodeMessage.c_str());
}
}
void publishMessage(char *topic, char *message) {
if (mqttClient.connected()) {
mqttClient.publish(topic, message);
}
}
long lastCmdTimeForDoorOne = 0;
long lastCmdTimeForDoorTwo = 0;
void callback(char* topic, byte* payload, unsigned int length) {
String topicName = String(topic);
if (millis() - lastCmdTimeForDoorOne < 5000 && topicName == DOOR_1_CMD) { // Ignore messages for 5 seconds.
return;
}
if (millis() - lastCmdTimeForDoorTwo < 5000 && topicName == DOOR_2_CMD) { // Ignore messages for 5 seconds.
return;
}
if (topicName == DOOR_1_CMD) {
lastCmdTimeForDoorOne = millis();
digitalWrite(RELAY_1, RELAY_ON);// set the Relay ON
delay(2000); // wait for a second
digitalWrite(RELAY_1, RELAY_OFF);// set the Relay OFF
}
if (topicName == DOOR_2_CMD) {
lastCmdTimeForDoorTwo = millis();
digitalWrite(RELAY_2, RELAY_ON);// set the Relay ON
delay(2000); // wait for a second
digitalWrite(RELAY_2, RELAY_OFF);// set the Relay OFF
}
}
void reconnect() {
// Loop until we're reconnected
while (!mqttClient.connected()) {
publishNodeLog("Attempting MQTT connection...");
// If we are not connected to mesh MQTT connections will fail.
while (!mesh.checkConnection()) {
//refresh the network address
publishNodeLog("Mesh Client disconnected, attempting connection...");
mesh.renewAddress();
delay(2000);
}
if (!ethClient.connected()) {
publishNodeLog("Ethernet Client disconnected...");
}
// Attempt to connect
if (mqttClient.connect(mqttClientId)) {
// Once connected, publish an announcement...
publishNodeLog("Connected to network and MQTT");
// ... and resubscribe
mqttClient.subscribe(DOOR_1_CMD);
mqttClient.subscribe(DOOR_2_CMD);
}
else {
Serial.print("failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
String getTimeString() {
long milliseconds = millis() / 1000;
int days = elapsedDays(milliseconds);
int hours = numberOfHours(milliseconds);
int minutes = numberOfMinutes(milliseconds);
int seconds = numberOfSeconds(milliseconds);
String returnedTime;
returnedTime.concat(days);
returnedTime.concat(":");
returnedTime.concat(hours);
returnedTime.concat(":");
returnedTime.concat(minutes);
returnedTime.concat(":");
returnedTime.concat(seconds);
return returnedTime;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment