From 549927090398b58cbf90aa5143af40859bfc3b50 Mon Sep 17 00:00:00 2001 From: Piotr Dobrowolski Date: Wed, 29 Jun 2016 17:00:22 +0200 Subject: [PATCH] Initial SpejsNode code --- common/common_config.h | 2 + master/test-client.py | 8 +--- spejsiot/SpejsNode.cpp | 79 +++++++++++++++++++++++++++++++ spejsiot/SpejsNode.h | 97 ++++++++++++++++++++++++++++++++++++++ switch/Makefile-user.mk | 30 +----------- switch/app/application.cpp | 68 +++++--------------------- 6 files changed, 193 insertions(+), 91 deletions(-) create mode 100644 spejsiot/SpejsNode.cpp create mode 100644 spejsiot/SpejsNode.h diff --git a/common/common_config.h b/common/common_config.h index 4b5d0ac..26b4f1a 100644 --- a/common/common_config.h +++ b/common/common_config.h @@ -11,6 +11,8 @@ #define MQTT_PORT 1883 #endif +#define TOPIC_PREFIX "iot/" + #define BTN_PIN 0 #define LED_PIN 2 diff --git a/master/test-client.py b/master/test-client.py index 284c05b..b079a3c 100644 --- a/master/test-client.py +++ b/master/test-client.py @@ -7,22 +7,16 @@ def on_connect(client, userdata, rc): print("Connected with result code "+str(rc)) # Subscribing in on_connect() means that if we lose the connection and # reconnect then subscriptions will be renewed. - client.subscribe("light/status") client.subscribe("#") client.publish("main/status/penisy", "dupa") # The callback for when a PUBLISH message is received from the server. def on_message(client, userdata, msg): - print(str(time.time())+" "+msg.topic+" "+str(msg.payload)) + print('%d %-20s %s' % (time.time(), msg.topic, msg.payload)) client = mqtt.Client("test-client-%d" % random.randint(100, 999)) client.on_connect = on_connect client.on_message = on_message client.connect("localhost", 1883, 60) - -# Blocking call that processes network traffic, dispatches callbacks and -# handles reconnecting. -# Other loop*() functions are available that give a threaded interface and a -# manual interface. client.loop_forever() diff --git a/spejsiot/SpejsNode.cpp b/spejsiot/SpejsNode.cpp new file mode 100644 index 0000000..54eeeab --- /dev/null +++ b/spejsiot/SpejsNode.cpp @@ -0,0 +1,79 @@ +#include + +void SpejsNode::init() { + deviceID = WifiStation.getMAC().substring(6, 12); + + Serial.begin(115200); + Serial.systemDebugOutput(false); // Debug output to serial + Serial.print("*** SpejsNode init, running on: "); + Serial.println(deviceID); + + WifiStation.config(WIFI_SSID, WIFI_PWD); + WifiStation.enable(true); + + WifiAccessPoint.enable(false); + + WifiStation.waitConnection( + ConnectionDelegate(&SpejsNode::onConnected, this), + 20, *[] { + Serial.println("Connection failed"); + }); +} + +void SpejsNode::keepAliveHandler() { + if(mqtt.getConnectionState() != eTCS_Connected) { + Serial.println("Reconnecting"); + onConnected(); + } +} + +void SpejsNode::onConnected() { + Serial.println("Connection successful"); + // "+deviceID+"/ + mqtt.setWill(TOPIC_PREFIX + deviceID + "/state", "offline", 1, true); + mqtt.connect("iot-" + deviceID); + + mqtt.subscribe(TOPIC_PREFIX + deviceID + "/control"); + + for(unsigned int i = 0 ; i < inputs.count() ; i++) { + mqtt.subscribe(TOPIC_PREFIX + deviceID + "/" + inputs.keyAt(i)); + } + + mqtt.publish(TOPIC_PREFIX + deviceID + "/state", "online"); + mqtt.publish(TOPIC_PREFIX + deviceID + "/type", deviceType); + + keepaliveTimer.initializeMs(10000, TimerDelegate(&SpejsNode::keepAliveHandler, this)).start(); +} + +bool SpejsNode::notify(String key, String value) { + if(mqtt.getConnectionState() == eTCS_Connected) { + mqtt.publish("iot/" + deviceID + "/" + key, value); + return true; + } + + return false; +} + +void SpejsNode::registerInput(String key, InputCallback callback) { + inputs[key] = callback; +} + +void SpejsNode::mqttCallback(String topic, String value) { + String devicePrefix = TOPIC_PREFIX + deviceID; + if(!topic.startsWith(devicePrefix)) { + Serial.println("ignoring"); + return; + } + + topic = topic.substring(devicePrefix.length() + 1); + + Serial.println(topic); + Serial.println(value); + + if(inputs.contains(topic)) { + Serial.println("dupa"); + inputs[topic](value); + } else { + Serial.println("default"); + } +} diff --git a/spejsiot/SpejsNode.h b/spejsiot/SpejsNode.h new file mode 100644 index 0000000..434bd3e --- /dev/null +++ b/spejsiot/SpejsNode.h @@ -0,0 +1,97 @@ +#include +#include +#include + +typedef void (*InputCallback)(String); + +class SpejsNode { +protected: + String deviceID; + String deviceType; + MqttClient mqtt; // (MQTT_BROKER, MQTT_PORT); + Timer keepaliveTimer; + + HashMap inputs; + + void onConnected(); + void startOTA(); + void keepAliveHandler(); + +public: + SpejsNode(String _deviceType) : + mqtt(MQTT_BROKER, MQTT_PORT, MqttStringSubscriptionCallback(&SpejsNode::mqttCallback, this)), + //*[](String topic, String message) { + // Serial.printf("*** message received @ %s:\n\t%s\n***\n", topic.c_str(), message.c_str()); + //}), + deviceType(_deviceType) + {}; + + void init(); + + //void registerInput(uint32_t gpio); + //void registerOutput(uint32_t gpio); + + bool notify(String key, String value); + void registerInput(String key, InputCallback cb); + void mqttCallback(String, String); +}; + +/* +MqttClient mqtt(MQTT_BROKER, MQTT_PORT, *[](String topic, String message) { + Serial.printf("*** message received @ %s:\n\t%s\n***\n", topic.c_str(), message.c_str()); +}); + +Timer keepaliveTimer; +String deviceName; + +void startMqttClient() +{ + Serial.println("*** Connecting to MQTT as " + deviceName); + + mqtt.setWill("main/status/" + deviceName, "offline", 1, true); + mqtt.connect(deviceName); + mqtt.publish("main/status/" + deviceName, "online"); + + keepaliveTimer.initializeMs(5000, *[] { + mqtt.publish("main/status/" + deviceName, "alive " + String(millis())); + }).start(); +} + +void init() +{ + deviceName = "switch-" + WifiStation.getMAC().substring(6, 12); + + Serial.begin(SERIAL_BAUD_RATE); // 115200 by default + Serial.systemDebugOutput(false); // Debug output to serial + + Serial.println("*** Starting " + deviceName + " ..."); + + WifiStation.config(WIFI_SSID, WIFI_PWD); + WifiStation.setIP(IPAddress(10, 5, 0, 39), IPAddress(255, 255, 255, 0), IPAddress(10, 5, 0, 1)); + WifiStation.enable(true); + + WifiAccessPoint.enable(false); + + + WifiStation.waitConnection(*[] { + Serial.println("*** Connection succeeded"); + startMqttClient(); + }, 20, *[] { + Serial.println("*** Connection failed"); + }); + + attachInterrupt(BTN_PIN, *[] { + static int lastSwitch = 0; + + // Debouncing + if(lastSwitch + 150 > millis()) { + Serial.println("--- debouncing"); + return; + } + lastSwitch = millis(); + + Serial.println("*** Button pressed"); + mqtt.publish("light/status", "toggle"); + }, FALLING); +} +*/ diff --git a/switch/Makefile-user.mk b/switch/Makefile-user.mk index 46f2ec6..e6daf21 100644 --- a/switch/Makefile-user.mk +++ b/switch/Makefile-user.mk @@ -1,31 +1,3 @@ -## Local build configuration -## Parameters configured here will override default and ENV values. -## Uncomment and change examples: - -#Add your source directories here separated by space -MODULES = app +MODULES = app ../spejsiot DISABLE_SPIFFS = 1 USER_CFLAGS = -I../common -## ESP_HOME sets the path where ESP tools and SDK are located. -## Windows: -# ESP_HOME = c:/Espressif - -## MacOS / Linux: -#ESP_HOME = /opt/esp-open-sdk - -## SMING_HOME sets the path where Sming framework is located. -## Windows: -# SMING_HOME = c:/tools/sming/Sming - -# MacOS / Linux -# SMING_HOME = /opt/sming/Sming - -## COM port parameter is reqruied to flash firmware correctly. -## Windows: -# COM_PORT = COM3 - -# MacOS / Linux: -# COM_PORT = /dev/tty.usbserial - -# Com port speed -# COM_SPEED = 115200 diff --git a/switch/app/application.cpp b/switch/app/application.cpp index 7665582..1a4ca53 100644 --- a/switch/app/application.cpp +++ b/switch/app/application.cpp @@ -1,60 +1,18 @@ -#include -#include -#include +#include -MqttClient mqtt(MQTT_BROKER, MQTT_PORT, *[](String topic, String message) { - Serial.printf("*** message received @ %s:\n\t%s\n***\n", topic.c_str(), message.c_str()); -}); +SpejsNode node("switch"); -Timer keepaliveTimer; -String deviceName; - -void startMqttClient() -{ - Serial.println("*** Connecting to MQTT as " + deviceName); - - mqtt.setWill("main/status/" + deviceName, "offline", 1, true); - mqtt.connect(deviceName); - mqtt.publish("main/status/" + deviceName, "online"); - - keepaliveTimer.initializeMs(5000, *[] { - mqtt.publish("main/status/" + deviceName, "alive " + String(millis())); - }).start(); -} - -void init() -{ - deviceName = "switch-" + WifiStation.getMAC().substring(6, 12); - - Serial.begin(SERIAL_BAUD_RATE); // 115200 by default - Serial.systemDebugOutput(false); // Debug output to serial - - Serial.println("*** Starting " + deviceName + " ..."); - - WifiStation.config(WIFI_SSID, WIFI_PWD); - WifiStation.enable(true); - - WifiAccessPoint.enable(false); - - - WifiStation.waitConnection(*[] { - Serial.println("*** Connection succeeded"); - startMqttClient(); - }, 20, *[] { - Serial.println("*** Connection failed"); +void init() { + node.init(); + node.registerInput("relay", *[](String value) { + Serial.println("handler"); + digitalWrite(5, value == "1" ? HIGH : LOW); }); - + pinMode(5, OUTPUT); + digitalWrite(5, LOW); attachInterrupt(BTN_PIN, *[] { - static int lastSwitch = 0; - - // Debouncing - if(lastSwitch + 150 > millis()) { - Serial.println("--- debouncing"); - return; - } - lastSwitch = millis(); - - Serial.println("*** Button pressed"); - mqtt.publish("light/status", "toggle"); - }, FALLING); + node.notify("btn", String(digitalRead(BTN_PIN))); + }, CHANGE); + //node.registerInputGPIO("btn", BTN_PIN); + //node.registerOutputGPIO("led", LED_PIN); }