Template
295 lines
7.5 KiB
Arduino
295 lines
7.5 KiB
Arduino
/*
|
|
ArduinoMqttClient - WiFi Simple Sender
|
|
|
|
This example code is in the public domain.
|
|
|
|
Feather M0
|
|
with Timer1 ISR driving events
|
|
|
|
*/
|
|
|
|
|
|
#define DEBUG false
|
|
|
|
#include <ArduinoMqttClient.h>
|
|
#include <Adafruit_SleepyDog.h>
|
|
|
|
#include <WiFi101.h>
|
|
|
|
#include "arduino_secrets.h"
|
|
/////// sensitive data in arduino_secrets.h
|
|
char ssid[] = SECRET_SSID;
|
|
char pass[] = SECRET_PASS;
|
|
char user[] = SECRET_USER;
|
|
char pw[] = SECRET_PW;
|
|
|
|
// wifi pins in use:
|
|
// WiFi.setPins(8,7,4,2); see setup()
|
|
|
|
#define LED_PIN 13
|
|
|
|
#define PUMP_PIN 12 // this is INT3
|
|
// PUMP_ON when LOW
|
|
|
|
#define FLOW_PIN 11 // this is INT0
|
|
// == water into the water heater = hot water demand when LOW
|
|
|
|
#define RATE 10 // Hz == 100mS
|
|
|
|
#define FLOWING digitalRead(FLOW_PIN)==LOW
|
|
#define NOTFLOWING digitalRead(FLOW_PIN)==HIGH
|
|
|
|
#define PUMPING digitalRead(PUMP_PIN)==LOW
|
|
#define NOTPUMPING digitalRead(PUMP_PIN)==HIGH
|
|
|
|
// Timer1_ISR functions:
|
|
void startTimer(int frequencyHz);
|
|
void setTimerFrequency(int frequencyHz);
|
|
void TC3_Handler();
|
|
|
|
bool isLEDOn = false;
|
|
bool notToggled = true;
|
|
|
|
|
|
// To connect with SSL/TLS:
|
|
// 1) Change WiFiClient to WiFiSSLClient.
|
|
// 2) Change port value from 1883 to 8883.
|
|
// 3) Change broker value to a server with a known SSL/TLS root certificate
|
|
// flashed in the WiFi module.
|
|
|
|
WiFiClient wifiClient;
|
|
MqttClient mqttClient(wifiClient);
|
|
|
|
const char broker[] = SERVER;
|
|
int port = 1883;
|
|
const char topic[] = "arduino/simple";
|
|
const char subtopic[] = "arduino/state";
|
|
|
|
volatile boolean intflag1 = false; // external interrupt1
|
|
volatile boolean intflag3 = false; // external interrupt3
|
|
|
|
volatile unsigned long ticktime = 0; // timer interrupt
|
|
volatile unsigned int ticknum = 0; // wifi checked when this is > wifiTick
|
|
|
|
unsigned long flowstarted = 0;
|
|
unsigned long flowstopped = 0;
|
|
unsigned long pumpstarted = 0;
|
|
unsigned long pumpstopped = 0;
|
|
|
|
|
|
const unsigned long interval = 10000; // 10 seconds
|
|
const unsigned long timestamp = 300000; // 300,000 ms = 5 min
|
|
// 600,000 ms = 10 min resulted in Client KV6KV_F8F005F0BEB9 has exceeded timeout, disconnecting.
|
|
unsigned long previousMillis = 0;
|
|
unsigned long lasttimestamp = 0;
|
|
|
|
const unsigned int wifiTick = 100; //(interval/RATE);
|
|
|
|
// external pin interrupt handlers
|
|
void flowchange() {
|
|
if (!intflag1) {
|
|
intflag1 = true;
|
|
}
|
|
}
|
|
|
|
void pumpchange() {
|
|
if (!intflag3) {
|
|
intflag3 = true;
|
|
}
|
|
}
|
|
|
|
|
|
// called from TC3 ISR...
|
|
void Tick(void) {
|
|
ticknum++;
|
|
ticktime++;
|
|
} // end Tick
|
|
|
|
void toggleLED(){
|
|
digitalWrite(LED_PIN, isLEDOn);
|
|
isLEDOn = !isLEDOn;
|
|
}
|
|
|
|
void setup() {
|
|
int counddownMS = Watchdog.enable(60000); // 60 seconds
|
|
WiFi.setPins(8,7,4,2);
|
|
pinMode(LED_PIN, OUTPUT);
|
|
pinMode(FLOW_PIN, INPUT_PULLUP);
|
|
pinMode(PUMP_PIN, INPUT_PULLUP);
|
|
attachInterrupt(FLOW_PIN, flowchange, CHANGE);
|
|
attachInterrupt(PUMP_PIN, pumpchange, CHANGE);
|
|
startTimer(RATE);
|
|
|
|
if (DEBUG) {
|
|
//Initialize serial and wait for port to open:
|
|
Serial.begin(9600);
|
|
while (!Serial) {
|
|
; // wait for serial port to connect. Needed for native USB port only
|
|
}
|
|
}
|
|
|
|
|
|
// attempt to connect to Wifi network:
|
|
if (DEBUG) Serial.print("Attempting to connect to WPA SSID: ");
|
|
if (DEBUG) Serial.println(ssid);
|
|
wifi_connect();
|
|
if (DEBUG) Serial.println("You're connected to the network");
|
|
if (DEBUG) Serial.println();
|
|
|
|
// You can provide a unique client ID, if not set the library uses Arduino-millis()
|
|
// Each client must have a unique client ID
|
|
mqttClient.setId(CLIENTID);
|
|
|
|
// You can provide a username and password for authentication
|
|
mqttClient.setUsernamePassword(SECRET_USER, SECRET_PW);
|
|
|
|
if (DEBUG) Serial.print("Attempting to connect to the MQTT broker: ");
|
|
if (DEBUG) Serial.println(broker);
|
|
|
|
mqtt_connect(); // first connect
|
|
|
|
if (DEBUG) Serial.println("You're connected to the MQTT broker!");
|
|
if (DEBUG) Serial.println();
|
|
mqttClient.subscribe(subtopic);
|
|
} // end of setup()
|
|
|
|
|
|
// loop is called repeatedly
|
|
void loop() {
|
|
unsigned long currentMillis = millis();
|
|
// 32bits = 4.295*10^6 seconds = 71.583*10^3 minutes = 1.193*10^3 hours = 49.71 days
|
|
|
|
/*
|
|
int messageSize = mqttClient.parseMessage();
|
|
|
|
// check incoming message
|
|
if (messageSize) {
|
|
if (DEBUG) Serial.print(mqttClient.messageTopic());
|
|
if (DEBUG) Serial.print(" : ");
|
|
while (mqttClient.available()) {
|
|
if (DEBUG) Serial.print((char)mqttClient.read());
|
|
}
|
|
if (DEBUG) Serial.println();
|
|
}
|
|
*/
|
|
|
|
// process flow interrupt
|
|
if (intflag1) {
|
|
mqtt_connect();
|
|
if (FLOWING) { // pin is LOW
|
|
flowstarted = WiFi.getTime();
|
|
mqttClient.beginMessage(topic);
|
|
mqttClient.print("start flow event@: ");
|
|
if (DEBUG) Serial.print(flowstarted);
|
|
if (DEBUG) Serial.println();
|
|
mqttClient.print(WiFi.getTime());
|
|
mqttClient.endMessage();
|
|
intflag1 = false;
|
|
} else { // pin is HIGH
|
|
flowstopped = WiFi.getTime();
|
|
mqttClient.beginMessage(topic);
|
|
mqttClient.print("stop flow event@: ");
|
|
if (DEBUG) Serial.print(flowstopped);
|
|
if (DEBUG) Serial.println();
|
|
mqttClient.print(WiFi.getTime());
|
|
mqttClient.endMessage();
|
|
intflag1 = false;
|
|
}
|
|
mqttClient.stop();
|
|
}
|
|
|
|
|
|
// process pump interrupt
|
|
if (intflag3) {
|
|
mqtt_connect();
|
|
if (PUMPING) { // pin is LOW
|
|
pumpstarted = WiFi.getTime();
|
|
mqttClient.beginMessage(topic);
|
|
mqttClient.print("start pump event@: ");
|
|
if (DEBUG) Serial.print(pumpstarted);
|
|
if (DEBUG) Serial.println();
|
|
mqttClient.print(WiFi.getTime());
|
|
mqttClient.endMessage();
|
|
intflag3 = false;
|
|
} else { // pin is HIGH
|
|
pumpstopped = WiFi.getTime();
|
|
mqttClient.beginMessage(topic);
|
|
mqttClient.print("stop pump event@: ");
|
|
if (DEBUG) Serial.print(pumpstopped);
|
|
if (DEBUG) Serial.println();
|
|
mqttClient.print(WiFi.getTime());
|
|
mqttClient.endMessage();
|
|
intflag3 = false;
|
|
}
|
|
mqttClient.stop();
|
|
}
|
|
|
|
|
|
// check wifi connection
|
|
if (ticknum >= wifiTick) { // every10 sec
|
|
ticknum = 0;
|
|
// attempt wifi reconnect if needed
|
|
// WiFi.status() =
|
|
// 3 ok WL_CONNECTED
|
|
// 6 disconnected wifi WL_DISCONNECTED
|
|
if (WiFi.status() == WL_DISCONNECTED) {
|
|
wifi_connect();
|
|
}
|
|
}
|
|
|
|
// blink LED @ 1Hz
|
|
if ((ticktime % 10) == 0) {
|
|
if (notToggled) { // ticks are every 100mS. only toggle ONCE
|
|
toggleLED();
|
|
notToggled = false;
|
|
}
|
|
} else {
|
|
notToggled = true;
|
|
}
|
|
|
|
|
|
|
|
// send tick timestamp to indicate operation with no water use
|
|
if (currentMillis - lasttimestamp >= timestamp) {
|
|
lasttimestamp = currentMillis;
|
|
mqtt_connect();
|
|
mqttClient.beginMessage(topic);
|
|
mqttClient.print("tick@: ");
|
|
mqttClient.print(WiFi.getTime());
|
|
mqttClient.endMessage();
|
|
mqttClient.stop();
|
|
if (DEBUG) Serial.println("tick");
|
|
}
|
|
|
|
Watchdog.reset();
|
|
} // loop()
|
|
|
|
|
|
void wifi_connect() {
|
|
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
|
|
// failed! retry until connected
|
|
if (DEBUG) Serial.print("!");
|
|
for (int i=0; i<20; i++){ // 2 sec delay with 10hz blink
|
|
delay(100);
|
|
toggleLED();
|
|
}
|
|
}
|
|
}
|
|
|
|
void mqtt_connect() {
|
|
while (!mqttClient.connected()) {
|
|
// not connected! retry until connected
|
|
if (DEBUG) Serial.print("+");
|
|
if (mqttClient.connect(broker, port)) {
|
|
if (DEBUG) Serial.println("connected");
|
|
} else {
|
|
if (DEBUG) Serial.print("MQTT connection failed! Error code = ");
|
|
if (DEBUG) Serial.println(mqttClient.connectError());
|
|
for (int i=0; i<10; i++){ // 2 sec delay with 5hz blink
|
|
delay(200);
|
|
toggleLED();
|
|
}
|
|
}
|
|
}
|
|
}
|