From 809de53cc8037659b3c332079469be9e2243d469 Mon Sep 17 00:00:00 2001 From: Thomas Kunze Date: Mon, 9 Apr 2018 23:58:35 +0200 Subject: [PATCH] move more code from demo to knx-esp --- examples/knx-esp-demo.ino | 88 ++++++++++ examples/knx-esp-demo.xml | 133 ++++++++++++++ knx-esp.vcxitems | 119 +++++++------ knx-esp.vcxitems.filters | 324 ++++++++++++++++++++--------------- src/button.cpp | 25 +++ src/button.h | 4 + src/knx_facade.cpp | 42 +++++ src/knx_facade.h | 13 +- src/led.cpp | 28 +++ src/led.h | 3 + src/nowifistate.cpp | 35 ++++ src/nowifistate.h | 16 ++ src/programmingmodestate.cpp | 26 +++ src/programmingmodestate.h | 17 ++ src/runningstate.cpp | 40 +++++ src/runningstate.h | 20 +++ src/state.cpp | 53 ++++++ src/state.h | 29 ++++ src/wpsstate.cpp | 28 +++ src/wpsstate.h | 14 ++ 20 files changed, 865 insertions(+), 192 deletions(-) create mode 100644 examples/knx-esp-demo.ino create mode 100644 examples/knx-esp-demo.xml create mode 100644 src/button.cpp create mode 100644 src/button.h create mode 100644 src/led.cpp create mode 100644 src/led.h create mode 100644 src/nowifistate.cpp create mode 100644 src/nowifistate.h create mode 100644 src/programmingmodestate.cpp create mode 100644 src/programmingmodestate.h create mode 100644 src/runningstate.cpp create mode 100644 src/runningstate.h create mode 100644 src/state.cpp create mode 100644 src/state.h create mode 100644 src/wpsstate.cpp create mode 100644 src/wpsstate.h diff --git a/examples/knx-esp-demo.ino b/examples/knx-esp-demo.ino new file mode 100644 index 0000000..ce98407 --- /dev/null +++ b/examples/knx-esp-demo.ino @@ -0,0 +1,88 @@ +#include +#include "knx_esp.h" + +float currentValue = 0; +float maxValue = 0; +float minValue = RAND_MAX; +long lastsend = 0; + +GroupObject groupObjects[] +{ + GroupObject(2), + GroupObject(2), + GroupObject(2), + GroupObject(1) +}; + +GroupObject& goCurrent = groupObjects[0]; +GroupObject& goMax = groupObjects[1]; +GroupObject& goMin = groupObjects[2]; +GroupObject& goReset = groupObjects[3]; + +void measureTemp() +{ + long now = millis(); + if ((now - lastsend) < 2000) + return; + + lastsend = now; + int r = rand(); + currentValue = (r * 1.0) / (RAND_MAX * 1.0); + currentValue *= 100 * 100; + + goCurrent.objectWriteFloat(currentValue); + + if (currentValue > maxValue) + { + maxValue = currentValue; + goMax.objectWriteFloat(maxValue); + } + + if (currentValue < minValue) + { + minValue = currentValue; + goMin.objectWriteFloat(minValue); + } +} + +void resetCallback(GroupObject& go) +{ + if (go.objectReadBool()) + { + maxValue = 0; + minValue = 10000; + } +} + +void setup() +{ + Serial.begin(115200); + Serial.setDebugOutput(true); + + randomSeed(millis()); + + knx.registerGroupObjects(groupObjects, 4); + knx.readMemory(); + + goReset.updateHandler = resetCallback; + + if (knx.configured()) + { + Serial.printf("Timeout: %d\n", knx.paramByte(0)); + Serial.printf("Zykl. senden: %d\n", knx.paramByte(1)); + Serial.printf("Min/Max senden: %d\n", knx.paramByte(2)); + Serial.printf("Aenderung senden: %d\n", knx.paramByte(3)); + Serial.printf("Abgleich %d\n", knx.paramByte(4)); + } + + knx.start(); +} + +void loop() +{ + knx.loop(); + if (!knx.configured()) + return; + + measureTemp(); +} diff --git a/examples/knx-esp-demo.xml b/examples/knx-esp-demo.xml new file mode 100644 index 0000000..da93378 --- /dev/null +++ b/examples/knx-esp-demo.xml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/knx-esp.vcxitems b/knx-esp.vcxitems index caaa10d..2b91085 100644 --- a/knx-esp.vcxitems +++ b/knx-esp.vcxitems @@ -15,62 +15,75 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/knx-esp.vcxitems.filters b/knx-esp.vcxitems.filters index 3cf624e..e304b22 100644 --- a/knx-esp.vcxitems.filters +++ b/knx-esp.vcxitems.filters @@ -9,168 +9,216 @@ {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - + + {0ee56052-c43f-46b9-ab25-f805ed81e840} + + + {e0ae5c46-92be-4bc5-bcae-4e831818010c} + - - Header Files - - + Header Files - + Header Files - + Header Files - + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + + Header Files\knx + + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - + Header Files + + + Source Files + + + Source Files + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files\knx + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + \ No newline at end of file diff --git a/src/button.cpp b/src/button.cpp new file mode 100644 index 0000000..e5a719b --- /dev/null +++ b/src/button.cpp @@ -0,0 +1,25 @@ +#include "button.h" +#include "state.h" +#include "knx_facade.h" + +unsigned long buttonTimestamp = 0; +void buttonUp() +{ + if (millis() - buttonTimestamp > 1000) + { + Serial.println("long button press"); + currentState->longButtonPress(); + } + else + { + Serial.println("short button press"); + currentState->shortButtonPress(); + } + attachInterrupt(knx.buttonPin(), buttonDown, FALLING); +} + +void buttonDown() +{ + buttonTimestamp = millis(); + attachInterrupt(knx.buttonPin(), buttonUp, RISING); +} \ No newline at end of file diff --git a/src/button.h b/src/button.h new file mode 100644 index 0000000..1c32762 --- /dev/null +++ b/src/button.h @@ -0,0 +1,4 @@ +#pragma once + +void buttonDown(); +void buttonUp(); \ No newline at end of file diff --git a/src/knx_facade.cpp b/src/knx_facade.cpp index a7c7e88..89a6e7a 100644 --- a/src/knx_facade.cpp +++ b/src/knx_facade.cpp @@ -1,4 +1,8 @@ #include "knx_facade.h" +#include "state.h" +#include "button.h" +#include "led.h" +#include "nowifistate.h" KnxFacade knx; @@ -32,12 +36,38 @@ bool KnxFacade::configured() return _bau.configured(); } +uint32_t KnxFacade::ledPin() +{ + return _ledPin; +} + +void KnxFacade::ledPin(uint32_t value) +{ + _ledPin = value; +} + +uint32_t KnxFacade::buttonPin() +{ + return _buttonPin; +} + +void KnxFacade::buttonPin(uint32_t value) +{ + _buttonPin = value; +} + void KnxFacade::readMemory() { _bau.readMemory(); } void KnxFacade::loop() +{ + if (currentState) + currentState->loop(); +} + +void KnxFacade::knxLoop() { _bau.loop(); } @@ -72,6 +102,18 @@ void KnxFacade::version(uint16_t value) _bau.deviceObject().version(value); } +void KnxFacade::start() +{ + pinMode(_ledPin, OUTPUT); + + pinMode(_buttonPin, INPUT); + attachInterrupt(_buttonPin, buttonDown, FALLING); + + switchToSate(noWifiState); + checkStates(); + _ticker.attach_ms(100, doLed); +} + uint8_t* KnxFacade::paramData(uint32_t addr) { if (!_bau.configured()) diff --git a/src/knx_facade.h b/src/knx_facade.h index 4d4ab69..ce90334 100644 --- a/src/knx_facade.h +++ b/src/knx_facade.h @@ -1,8 +1,10 @@ #pragma once - +#include #include "esp_platform.h" #include "knx/bau57B0.h" +class RunningState; + class KnxFacade { public: @@ -12,14 +14,20 @@ public: bool progMode(); void progMode(bool value); bool configured(); + uint32_t ledPin(); + void ledPin(uint32_t value); + uint32_t buttonPin(); + void buttonPin(uint32_t value); void readMemory(); void loop(); + void knxLoop(); void registerGroupObjects(GroupObject* groupObjects, uint16_t count); void manufacturerId(uint16_t value); void bauNumber(uint32_t value); void orderNumber(const char* value); void hardwareType(uint8_t* value); void version(uint16_t value); + void start(); uint8_t* paramData(uint32_t addr); uint8_t paramByte(uint32_t addr); uint16_t paramWord(uint32_t addr); @@ -27,6 +35,9 @@ public: private: EspPlatform _platform; Bau57B0 _bau; + uint32_t _ledPin = 16; + uint32_t _buttonPin = 0; + Ticker _ticker; }; extern KnxFacade knx; \ No newline at end of file diff --git a/src/led.cpp b/src/led.cpp new file mode 100644 index 0000000..e1a66a6 --- /dev/null +++ b/src/led.cpp @@ -0,0 +1,28 @@ +#include "led.h" +#include "knx_facade.h" +#include "state.h" + +void doLed() +{ + if (!currentState) + return; + + if (!currentState->ledOn()) + { + digitalWrite(knx.ledPin(), HIGH); + return; + } + + unsigned int period = currentState->blinkPeriod(); + + if (!currentState->ledBlink() || period == 0) + { + digitalWrite(knx.ledPin(), LOW); + return; + } + + if ((millis() % period) > (period / 2)) + digitalWrite(knx.ledPin(), HIGH); + else + digitalWrite(knx.ledPin(), LOW); +} \ No newline at end of file diff --git a/src/led.h b/src/led.h new file mode 100644 index 0000000..985759a --- /dev/null +++ b/src/led.h @@ -0,0 +1,3 @@ +#pragma once + +void doLed(); \ No newline at end of file diff --git a/src/nowifistate.cpp b/src/nowifistate.cpp new file mode 100644 index 0000000..ddb6073 --- /dev/null +++ b/src/nowifistate.cpp @@ -0,0 +1,35 @@ +#include + +#include "nowifistate.h" +#include "wpsstate.h" +#include "runningstate.h" + +NoWifiState noWifiState = NoWifiState(); + +void NoWifiState::shortButtonPress() +{ + switchToSate(wpsState); +} + +void NoWifiState::longButtonPress() +{ + switchToSate(wpsState); +} + +void NoWifiState::enterState() +{ + WiFi.mode(WIFI_STA); + WiFi.begin("", ""); + while (WiFi.status() == WL_DISCONNECTED) + { + delay(500); + Serial.print("."); + } + + wl_status_t status = WiFi.status(); + if (status == WL_CONNECTED) + { + Serial.printf("\nConnected successful to SSID '%s'\n", WiFi.SSID().c_str()); + switchToSate(runningState); + } +} \ No newline at end of file diff --git a/src/nowifistate.h b/src/nowifistate.h new file mode 100644 index 0000000..f15d46e --- /dev/null +++ b/src/nowifistate.h @@ -0,0 +1,16 @@ +#pragma once + +#include "state.h" + +class NoWifiState : public State +{ +public: + NoWifiState() : State(true, false, 0) + {} + virtual void shortButtonPress(); + virtual void longButtonPress(); + virtual void enterState(); + virtual const char* name() { return "NoWifi"; } +}; + +extern NoWifiState noWifiState; \ No newline at end of file diff --git a/src/programmingmodestate.cpp b/src/programmingmodestate.cpp new file mode 100644 index 0000000..be52139 --- /dev/null +++ b/src/programmingmodestate.cpp @@ -0,0 +1,26 @@ +#include "programmingmodestate.h" +#include "runningstate.h" +#include "knx_facade.h" + +ProgramModeState programModeState = ProgramModeState(); + +void ProgramModeState::enterState() +{ + knx.progMode(true); +} + +void ProgramModeState::leaveState() +{ + knx.progMode(false); +} + +void ProgramModeState::shortButtonPress() +{ + switchToSate(runningState); +} + +void ProgramModeState::loop() +{ + State::loop(); + knx.knxLoop(); +} diff --git a/src/programmingmodestate.h b/src/programmingmodestate.h new file mode 100644 index 0000000..489fc8b --- /dev/null +++ b/src/programmingmodestate.h @@ -0,0 +1,17 @@ +#pragma once + +#include "state.h" + +class ProgramModeState : public State +{ +public: + ProgramModeState() : State(true, true, 200) + {} + virtual void enterState(); + virtual void leaveState(); + virtual void shortButtonPress(); + virtual void loop(); + virtual const char* name() { return "ProgramMode"; } +}; + +extern ProgramModeState programModeState; \ No newline at end of file diff --git a/src/runningstate.cpp b/src/runningstate.cpp new file mode 100644 index 0000000..a13cc80 --- /dev/null +++ b/src/runningstate.cpp @@ -0,0 +1,40 @@ +#include "runningstate.h" +#include "programmingmodestate.h" +#include "wpsstate.h" +#include "knx_facade.h" + +RunningState runningState = RunningState(); + +void RunningState::shortButtonPress() +{ + switchToSate(programModeState); +} + +void RunningState::longButtonPress() +{ + switchToSate(wpsState); +} + +void RunningState::enterState() +{ + if (_initialized) + return; + + knx.enabled(true); + _initialized = true; +} + +void RunningState::leaveState() +{ + if (nextState != &programModeState) + { + _initialized = false; + knx.enabled(false); + } +} + +void RunningState::loop() +{ + State::loop(); + knx.knxLoop(); +} diff --git a/src/runningstate.h b/src/runningstate.h new file mode 100644 index 0000000..374fb97 --- /dev/null +++ b/src/runningstate.h @@ -0,0 +1,20 @@ +#pragma once + +#include "state.h" + +class RunningState : public State +{ +public: + RunningState() : State(false, false, 0) + {} + virtual void shortButtonPress(); + virtual void longButtonPress(); + virtual void enterState(); + virtual void leaveState(); + virtual void loop(); + virtual const char* name() { return "Running"; } +private: + bool _initialized = false; +}; + +extern RunningState runningState; \ No newline at end of file diff --git a/src/state.cpp b/src/state.cpp new file mode 100644 index 0000000..bffae1d --- /dev/null +++ b/src/state.cpp @@ -0,0 +1,53 @@ +#include "state.h" +#include "Arduino.h" + +State* volatile currentState = 0; +State* volatile nextState = 0; + +void switchToSate(State& state) +{ + nextState = &state; +} + +void checkStates() +{ + if (!nextState) + return; + + if (nextState == currentState) + return; + + if (currentState) + { + printf("Leave %s\n", currentState->name()); + currentState->leaveState(); + } + + currentState = nextState; + + if (currentState) + { + printf("Enter %s\n", currentState->name()); + currentState->enterState(); + } +} + +bool State::ledOn() +{ + return _ledOn; +} + +bool State::ledBlink() +{ + return _ledBlink; +} + +unsigned int State::blinkPeriod() +{ + return _blinkPeriod; +} + +void State::loop() +{ + checkStates(); +} diff --git a/src/state.h b/src/state.h new file mode 100644 index 0000000..a8b77a9 --- /dev/null +++ b/src/state.h @@ -0,0 +1,29 @@ +#pragma once + +class State +{ +public: + State(bool led, bool blink, int period) : + _ledOn(led), _ledBlink(blink), _blinkPeriod(period) + {} + virtual ~State() {} + bool ledOn(); + bool ledBlink(); + unsigned int blinkPeriod(); + virtual void shortButtonPress() {} + virtual void longButtonPress() {} + virtual void enterState() {} + virtual void leaveState() {} + virtual void loop(); + virtual const char* name() = 0; +private: + bool _ledOn; + bool _ledBlink; + int _blinkPeriod; +}; + +void switchToSate(State& state); +void checkStates(); + +extern State* volatile currentState; +extern State* volatile nextState; \ No newline at end of file diff --git a/src/wpsstate.cpp b/src/wpsstate.cpp new file mode 100644 index 0000000..7c395a6 --- /dev/null +++ b/src/wpsstate.cpp @@ -0,0 +1,28 @@ +#include + +#include "wpsstate.h" +#include "runningstate.h" +#include "nowifistate.h" + +WpsState wpsState = WpsState(); + +void WpsState::enterState() +{ + //invalidate old wifi settings first + WiFi.begin("fobar", "a12"); + Serial.println("WPS config start"); + bool wpsSuccess = WiFi.beginWPSConfig(); + if (wpsSuccess) { + String newSSID = WiFi.SSID(); + if (newSSID.length() > 0) + { + Serial.printf("WPS finished. Connected successfull to SSID '%s'\n", newSSID.c_str()); + switchToSate(runningState); + } + else + { + Serial.printf("WPS failed."); + switchToSate(noWifiState); + } + } +} diff --git a/src/wpsstate.h b/src/wpsstate.h new file mode 100644 index 0000000..5460bb4 --- /dev/null +++ b/src/wpsstate.h @@ -0,0 +1,14 @@ +#pragma once + +#include "state.h" + +class WpsState : public State +{ +public: + WpsState() : State(true, true, 400) + {} + virtual void enterState(); + virtual const char* name() { return "Wps"; } +}; + +extern WpsState wpsState;