From de0f498d04c084d9f98399e8307acdbfdd617792 Mon Sep 17 00:00:00 2001 From: Klaus Ahrenberg Date: Sun, 15 Oct 2023 08:58:09 +0200 Subject: [PATCH] 1.38 --- src/WAnalog.h | 50 ++++ src/WDevice.h | 10 +- src/WJson.h | 264 ++++++++------------ src/WJsonParser.h | 505 +++++++++++++++++---------------------- src/WNetwork.h | 110 ++++----- src/WOutput.h | 2 +- src/WPin.h | 54 ----- src/WProperty.h | 299 +++++++++++------------ src/WProps.h | 18 +- src/WSettings.h | 84 +++---- src/WSwitch.h | 4 +- src/WValue.h | 8 +- src/hw/PT2314.h | 222 +++++++++++++++++ src/hw/W2812.h | 6 +- src/hw/WHtu21D.h | 21 +- src/hw/WI2CTemperature.h | 48 ++++ src/hw/WSht30.h | 133 +++++++++++ 17 files changed, 1050 insertions(+), 788 deletions(-) create mode 100644 src/WAnalog.h delete mode 100644 src/WPin.h create mode 100644 src/hw/PT2314.h create mode 100644 src/hw/WI2CTemperature.h create mode 100644 src/hw/WSht30.h diff --git a/src/WAnalog.h b/src/WAnalog.h new file mode 100644 index 0000000..6dfb629 --- /dev/null +++ b/src/WAnalog.h @@ -0,0 +1,50 @@ +#ifndef W_ANALOG_INPUT_H +#define W_ANALOG_INPUT_H + +#include "WInput.h" + +class WAnalog : public WInput { + public: + WAnalog(int analogPin, int minimum = 0, int maximum = 100) : WInput(analogPin, INPUT) { + _minimum = minimum; + _maximum = maximum; + _analogMinimum = 0; + #ifdef ESP8266 + _analogMaximum = 1023; + #elif ESP32 + _analogMaximum = 4095; + #endif + } + + void loop(unsigned long now) { + if ((this->isInitialized()) && (hasProperty())) { + int ain = analogRead(pin()); + ain = constrain(ain, _analogMinimum, _analogMaximum); + ain = map(ain, _minimum, _maximum, _analogMinimum, _analogMaximum); + + switch (property()->type()) { + INTEGER: { + property()->asInt(ain); + break; + } + BYTE: { + property()->asByte(ain); + break; + } + DOUBLE: { + property()->asDouble(ain); + break; + } + } + } + } + + private: + int _analogMinimum; + int _analogMaximum; + int _minimum; + int _maximum; + +}; + +#endif \ No newline at end of file diff --git a/src/WDevice.h b/src/WDevice.h index 039aee9..c77478a 100644 --- a/src/WDevice.h +++ b/src/WDevice.h @@ -51,7 +51,7 @@ class WDevice { const char* type() { return _type; } void addProperty(WProperty* property) { - property->setDeviceNotification(std::bind(&WDevice::onPropertyChange, this)); + property->deviceNotification(std::bind(&WDevice::onPropertyChange, this)); _properties->add(property); } @@ -80,7 +80,7 @@ class WDevice { if (property->isVisible(visibility)) { property->toJsonValue(json, false); } - property->setUnChanged(); + property->changed(false); }); } @@ -136,7 +136,7 @@ class WDevice { virtual bool off() { return false; } virtual bool areAllPropertiesRequested() { - return (_properties->getIf([this](WProperty* p){return (!p->isRequested());}) == nullptr); + return (_properties->getIf([this](WProperty* p){return (!p->requested());}) == nullptr); } WPropertyVisibility visibility() { return _visibility; } @@ -167,9 +167,11 @@ class WDevice { unsigned long lastStateNotify() { return _lastStateNotify; } - void setLastStateNotify(unsigned long lastStateNotify) { _lastStateNotify = lastStateNotify; } + void lastStateNotify(unsigned long lastStateNotify) { _lastStateNotify = lastStateNotify; } unsigned long stateNotifyInterval() { return _stateNotifyInterval; } + + void stateNotifyInterval(unsigned long stateNotifyInterval) { _stateNotifyInterval = stateNotifyInterval; } bool needsWebThings() { bool result = false; diff --git a/src/WJson.h b/src/WJson.h index 1d8df4f..2826edc 100644 --- a/src/WJson.h +++ b/src/WJson.h @@ -14,7 +14,7 @@ const static char QUOTE = '\"'; class WJson { public: WJson(Print* stream) { - this->stream = stream; + _stream = stream; } WJson& beginObject() { @@ -22,300 +22,226 @@ class WJson { } WJson& beginObject(const char* name) { - if (!separatorAlreadyCalled) { - ifSeparator(); - separatorAlreadyCalled = true; + if (!_separatorAlreadyCalled) { + _ifSeparator(); + _separatorAlreadyCalled = true; } if (name != "") { memberName(name); } - stream->print(SBEGIN); - firstElement = true; + _stream->print(SBEGIN); + _firstElement = true; return *this; } WJson& memberName(const char *name) { if (name != nullptr) { string(name); - stream->print(DPOINT); + _stream->print(DPOINT); } return *this; } WJson& separator() { - stream->print(COMMA); + _stream->print(COMMA); return *this; } WJson& endObject() { - stream->print(SEND); + _stream->print(SEND); return *this; } WJson& beginArray() { - if (!separatorAlreadyCalled) { - ifSeparator(); + if (!_separatorAlreadyCalled) { + _ifSeparator(); } - firstElement = true; - stream->print(BBEGIN); + _firstElement = true; + _stream->print(BBEGIN); return *this; } WJson& beginArray(const char* name) { - if (!separatorAlreadyCalled) { - ifSeparator(); - separatorAlreadyCalled = true; + if (!_separatorAlreadyCalled) { + _ifSeparator(); + _separatorAlreadyCalled = true; } - firstElement = true; + _firstElement = true; memberName(name); - separatorAlreadyCalled = false; - stream->print(BBEGIN); + _separatorAlreadyCalled = false; + _stream->print(BBEGIN); return *this; } WJson& endArray() { - stream->print(BEND); + _stream->print(BEND); return *this; } WJson& propertyInteger(const char* name, int value) { - ifSeparator(); - separatorAlreadyCalled = true; + _ifSeparator(); + _separatorAlreadyCalled = true; memberName(name); numberInteger(value); - separatorAlreadyCalled = false; + _separatorAlreadyCalled = false; return *this; } WJson& propertyShort(const char* name, short value) { - ifSeparator(); - separatorAlreadyCalled = true; + _ifSeparator(); + _separatorAlreadyCalled = true; memberName(name); numberShort(value); - separatorAlreadyCalled = false; + _separatorAlreadyCalled = false; return *this; } WJson& propertyUnsignedLong(const char* name, unsigned long value) { - ifSeparator(); - separatorAlreadyCalled = true; + _ifSeparator(); + _separatorAlreadyCalled = true; memberName(name); numberUnsignedLong(value); - separatorAlreadyCalled = false; + _separatorAlreadyCalled = false; return *this; } WJson& propertyByte(const char* name, byte value) { - ifSeparator(); - separatorAlreadyCalled = true; + _ifSeparator(); + _separatorAlreadyCalled = true; memberName(name); numberByte(value); - separatorAlreadyCalled = false; + _separatorAlreadyCalled = false; return *this; } WJson& propertyByteArray(const char* name, byte length, byte* value) { - ifSeparator(); - separatorAlreadyCalled = true; + _ifSeparator(); + _separatorAlreadyCalled = true; memberName(name); numberByteArray(length, value); - separatorAlreadyCalled = false; + _separatorAlreadyCalled = false; return *this; } WJson& propertyDouble(const char* name, double value) { - ifSeparator(); - separatorAlreadyCalled = true; + _ifSeparator(); + _separatorAlreadyCalled = true; memberName(name); numberDouble(value); - separatorAlreadyCalled = false; + _separatorAlreadyCalled = false; return *this; } WJson& propertyBoolean(const char* name, bool value) { - ifSeparator(); - separatorAlreadyCalled = true; + _ifSeparator(); + _separatorAlreadyCalled = true; memberName(name); boolean(value); - separatorAlreadyCalled = false; + _separatorAlreadyCalled = false; return *this; - } - - WJson& propertyString(const char* name, const char *value) { - return propertyString(name, value, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); - } - - WJson& propertyString(const char* name, const char *value1, const char *value2) { - return propertyString(name, value1, value2, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); - } - - WJson& propertyString(const char* name, const char *value1, const char *value2, const char *value3) { - return propertyString(name, value1, value2, value3, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); - } - - WJson& propertyString(const char* name, const char *value1, const char *value2, const char *value3, const char *value4) { - return propertyString(name, value1, value2, value3, value4, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); - } - - WJson& propertyString(const char* name, const char *value1, const char *value2, const char *value3, const char *value4, const char *value5) { - return propertyString(name, value1, value2, value3, value4, value5, nullptr, nullptr, nullptr, nullptr, nullptr); - } - - WJson& propertyString(const char* name, const char *value1, const char *value2, const char *value3, const char *value4, const char *value5, const char *value6) { - return propertyString(name, value1, value2, value3, value4, value5, value6, nullptr, nullptr, nullptr, nullptr); - } - - WJson& propertyString(const char* name, const char *value1, const char *value2, const char *value3, const char *value4, const char *value5, const char *value6, const char *value7) { - return propertyString(name, value1, value2, value3, value4, value5, value6, value7, nullptr, nullptr, nullptr); - } + } - WJson& propertyString(const char* name, const char *value1, const char *value2, const char *value3, const char *value4, const char *value5, const char *value6, const char *value7, const char *value8) { - return propertyString(name, value1, value2, value3, value4, value5, value6, value7, value8, nullptr, nullptr); - } - - WJson& propertyString(const char* name, const char *value1, const char *value2, const char *value3, const char *value4, const char *value5, const char *value6, const char *value7, const char *value8, const char *value9) { - return propertyString(name, value1, value2, value3, value4, value5, value6, value7, value8, value9, nullptr); - } - - WJson& propertyString(const char* name, const char *value1, const char *value2, const char *value3, const char *value4, const char *value5, const char *value6, const char *value7, const char *value8, const char *value9, const char *value10) { - ifSeparator(); - separatorAlreadyCalled = true; + WJson& propertyString(const char* name, const char *value1 = nullptr, const char *value2 = nullptr, const char *value3 = nullptr, const char *value4 = nullptr, const char *value5 = nullptr, const char *value6 = nullptr, const char *value7 = nullptr, const char *value8 = nullptr, const char *value9 = nullptr, const char *value10 = nullptr) { + _ifSeparator(); + _separatorAlreadyCalled = true; memberName(name); string(value1, value2, value3, value4, value5, value6, value7, value8, value9, value10); - separatorAlreadyCalled = false; + _separatorAlreadyCalled = false; return *this; - } + } - WJson& string(const char *text) { - return string(text, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); - } - - WJson& string(const char *text1, const char *text2) { - return string(text1, text2, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); - } - - WJson& string(const char *text1, const char *text2, const char *text3) { - return string(text1, text2, text3, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); - } - - WJson& string(const char *text1, const char *text2, const char *text3, const char *text4) { - return string(text1, text2, text3, text4, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); - } - - WJson& string(const char *text1, const char *text2, const char *text3, const char *text4, const char *text5) { - return string(text1, text2, text3, text4, text5, nullptr, nullptr, nullptr, nullptr, nullptr); - } - - WJson& string(const char *text1, const char *text2, const char *text3, const char *text4, const char *text5, const char *text6) { - return string(text1, text2, text3, text4, text5, text6, nullptr, nullptr, nullptr, nullptr); - } - - WJson& string(const char *text1, const char *text2, const char *text3, const char *text4, const char *text5, const char *text6, const char *text7) { - return string(text1, text2, text3, text4, text5, text6, text7, nullptr, nullptr, nullptr); - } - - WJson& string(const char *text1, const char *text2, const char *text3, const char *text4, const char *text5, const char *text6, const char *text7, const char *text8) { - return string(text1, text2, text3, text4, text5, text6, text7, text8, nullptr, nullptr); - } - - WJson& string(const char *text1, const char *text2, const char *text3, const char *text4, const char *text5, const char *text6, const char *text7, const char *text8, const char *text9) { - return string(text1, text2, text3, text4, text5, text6, text7, text8, text9, nullptr); - } - - WJson& string(const char *text1, const char *text2, const char *text3, const char *text4, const char *text5, const char *text6, const char *text7, const char *text8, const char *text9, const char *text10) { - if (!separatorAlreadyCalled) - ifSeparator(); - stream->print(QUOTE); - if (text1 != nullptr) stream->print(text1); - if (text2 != nullptr) stream->print(text2); - if (text3 != nullptr) stream->print(text3); - if (text4 != nullptr) stream->print(text4); - if (text5 != nullptr) stream->print(text5); - if (text6 != nullptr) stream->print(text6); - if (text7 != nullptr) stream->print(text7); - if (text8 != nullptr) stream->print(text8); - if (text9 != nullptr) stream->print(text9); - if (text10 != nullptr) stream->print(text10); - stream->print(QUOTE); + WJson& string(const char *text1 = nullptr, const char *text2 = nullptr, const char *text3 = nullptr, const char *text4 = nullptr, const char *text5 = nullptr, const char *text6 = nullptr, const char *text7 = nullptr, const char *text8 = nullptr, const char *text9 = nullptr, const char *text10 = nullptr) { + if (!_separatorAlreadyCalled) + _ifSeparator(); + _stream->print(QUOTE); + if (text1 != nullptr) _stream->print(text1); + if (text2 != nullptr) _stream->print(text2); + if (text3 != nullptr) _stream->print(text3); + if (text4 != nullptr) _stream->print(text4); + if (text5 != nullptr) _stream->print(text5); + if (text6 != nullptr) _stream->print(text6); + if (text7 != nullptr) _stream->print(text7); + if (text8 != nullptr) _stream->print(text8); + if (text9 != nullptr) _stream->print(text9); + if (text10 != nullptr) _stream->print(text10); + _stream->print(QUOTE); return *this; } WJson& onlyString(const char *text1) { - if (text1 != nullptr) stream->print(text1); + if (text1 != nullptr) _stream->print(text1); return *this; } WJson& numberInteger(int number) { - if(!separatorAlreadyCalled) - ifSeparator(); - stream->print(number, DEC); + if(!_separatorAlreadyCalled) + _ifSeparator(); + _stream->print(number, DEC); return *this; } WJson& numberShort(short number) { - if (!separatorAlreadyCalled) - ifSeparator(); - stream->print(number, DEC); + if (!_separatorAlreadyCalled) + _ifSeparator(); + _stream->print(number, DEC); return *this; } WJson& numberUnsignedLong(unsigned long number) { - if (!separatorAlreadyCalled) - ifSeparator(); - stream->print(number, DEC); + if (!_separatorAlreadyCalled) + _ifSeparator(); + _stream->print(number, DEC); return *this; } WJson& numberByte(byte number) { - if (!separatorAlreadyCalled) - ifSeparator(); - stream->print(number, DEC); + if (!_separatorAlreadyCalled) + _ifSeparator(); + _stream->print(number, DEC); return *this; } WJson& numberByteArray(byte length, byte* value) { - if (!separatorAlreadyCalled) - ifSeparator(); - stream->print(BBEGIN); + if (!_separatorAlreadyCalled) + _ifSeparator(); + _stream->print(BBEGIN); for (byte i = 0; i < length; i++) { - if (i != 0) stream->print(COMMA); - stream->print(value[i], DEC); + if (i != 0) _stream->print(COMMA); + _stream->print(value[i], DEC); } - stream->print(BEND); + _stream->print(BEND); return *this; } WJson& numberDouble(double number) { - if (!separatorAlreadyCalled) - ifSeparator(); - stream->print(number); + if (!_separatorAlreadyCalled) + _ifSeparator(); + _stream->print(number); return *this; } WJson& null() { - ifSeparator(); - stream->print("null"); + _ifSeparator(); + _stream->print("null"); return *this; } WJson& boolean(bool value) { - if (!separatorAlreadyCalled) - ifSeparator(); - stream->print(value ? "true" : "false"); + if (!_separatorAlreadyCalled) + _ifSeparator(); + _stream->print(value ? "true" : "false"); return *this; } - int operator[](char*); - private: - Print* stream; - bool firstElement = true; - bool separatorAlreadyCalled = false; + Print* _stream; + bool _firstElement = true; + bool _separatorAlreadyCalled = false; - void ifSeparator() { - if (firstElement) { - firstElement = false; + void _ifSeparator() { + if (_firstElement) { + _firstElement = false; } else { separator(); } diff --git a/src/WJsonParser.h b/src/WJsonParser.h index 386ef3f..b81b973 100644 --- a/src/WJsonParser.h +++ b/src/WJsonParser.h @@ -31,38 +31,28 @@ class WJsonParser { public: typedef std::function TProcessKeyValueFunction; - WJsonParser() { - this->logging = false; - state = STATE_START_DOCUMENT; - bufferPos = 0; - unicodeEscapeBufferPos = 0; - unicodeBufferPos = 0; - characterCounter = 0; - kvFunction = nullptr; - } - - WJsonParser(bool logging) { - this->logging = logging; - state = STATE_START_DOCUMENT; - bufferPos = 0; - unicodeEscapeBufferPos = 0; - unicodeBufferPos = 0; - characterCounter = 0; - kvFunction = nullptr; + WJsonParser(bool logging = false) { + _logging = logging; + _state = STATE_START_DOCUMENT; + _bufferPos = 0; + _unicodeEscapeBufferPos = 0; + _unicodeBufferPos = 0; + _characterCounter = 0; + _kvFunction = nullptr; } void parse(const char *payload, TProcessKeyValueFunction kvFunction) { - this->kvFunction = kvFunction; + _kvFunction = kvFunction; for (int i = 0; i < strlen(payload); i++) { - parseChar(payload[i]); + _parseChar(payload[i]); } } WProperty* parse(const char *payload, WDevice *device) { - this->device = device; + _device = device; WProperty* result = nullptr; for (int i = 0; i < strlen(payload); i++) { - WProperty* p = parseChar(payload[i]); + WProperty* p = _parseChar(payload[i]); if (p != nullptr) { result = p; } @@ -71,79 +61,79 @@ class WJsonParser { } private: - int state; - int stack[20]; - int stackPos = 0; - bool doEmitWhitespace = false; - char buffer[BUFFER_MAX_LENGTH]; - int bufferPos = 0; - char unicodeEscapeBuffer[10]; - int unicodeEscapeBufferPos = 0; - char unicodeBuffer[10]; - int unicodeBufferPos = 0; - int characterCounter = 0; - int unicodeHighSurrogate = 0; - bool logging = false; - String currentKey; - WDevice *device = nullptr; - TProcessKeyValueFunction kvFunction; - - void log(String message) { - if (logging) { + int _state; + int _stack[20]; + int _stackPos = 0; + bool _doEmitWhitespace = false; + char _buffer[BUFFER_MAX_LENGTH]; + int _bufferPos = 0; + char _unicodeEscapeBuffer[10]; + int _unicodeEscapeBufferPos = 0; + char _unicodeBuffer[10]; + int _unicodeBufferPos = 0; + int _characterCounter = 0; + int _unicodeHighSurrogate = 0; + bool _logging = false; + String _currentKey; + WDevice* _device = nullptr; + TProcessKeyValueFunction _kvFunction; + + void _log(String message) { + if (_logging) { Serial.println(message); } } - WProperty* processKeyValue(const char* key, const char* value) { + WProperty* _processKeyValue(const char* key, const char* value) { WProperty* result = nullptr; - if (device != nullptr) { - result = device->getPropertyById(key); + if (_device != nullptr) { + result = _device->getPropertyById(key); if (result != nullptr) { if (!result->parse(value)) { result = nullptr; } } - } else if (kvFunction) { - kvFunction(key, value); + } else if (_kvFunction) { + _kvFunction(key, value); } return result; } - WProperty* parseChar(char c) { + WProperty* _parseChar(char c) { WProperty* result = nullptr; if ((c == ' ' || c == '\t' || c == '\n' || c == '\r') - && !(state == STATE_IN_STRING || state == STATE_UNICODE - || state == STATE_START_ESCAPE - || state == STATE_IN_NUMBER - || state == STATE_START_DOCUMENT)) { + && !(_state == STATE_IN_STRING || _state == STATE_UNICODE + || _state == STATE_START_ESCAPE + || _state == STATE_IN_NUMBER + || _state == STATE_START_DOCUMENT)) { return result; } - switch (state) { + switch (_state) { case STATE_IN_STRING: if (c == QUOTE) { - result = endString(); + result = _endString(); } else if (c == '\\') { - state = STATE_START_ESCAPE; + _state = STATE_START_ESCAPE; } else if ((c < 0x1f) || (c == 0x7f)) { //throw new RuntimeException("Unescaped control character encountered: " + c + " at position" + characterCounter); } else { - buffer[bufferPos] = c; - increaseBufferPointer(); + _buffer[_bufferPos] = c; + _increaseBufferPointer(); } break; case STATE_IN_ARRAY: if (c == BEND) { - endArray(); + _endArray(); } else { - startValue(c); + _startValue(c); } break; case STATE_IN_OBJECT: if (c == SEND) { - endObject(); + _endObject(); } else if (c == QUOTE) { - startKey(); + _startKey(); } else { //throw new RuntimeException("Start of string expected for object key. Instead got: " + c + " at position" + characterCounter); } @@ -152,40 +142,40 @@ class WJsonParser { if (c != DPOINT) { //throw new RuntimeException("Expected ':' after key. Instead got " + c + " at position" + characterCounter); } - state = STATE_AFTER_KEY; + _state = STATE_AFTER_KEY; break; case STATE_AFTER_KEY: - startValue(c); + _startValue(c); break; case STATE_START_ESCAPE: - processEscapeCharacters(c); + _processEscapeCharacters(c); break; case STATE_UNICODE: - processUnicodeCharacter(c); + _processUnicodeCharacter(c); break; case STATE_UNICODE_SURROGATE: - unicodeEscapeBuffer[unicodeEscapeBufferPos] = c; - unicodeEscapeBufferPos++; - if (unicodeEscapeBufferPos == 2) { - endUnicodeSurrogateInterstitial(); + _unicodeEscapeBuffer[_unicodeEscapeBufferPos] = c; + _unicodeEscapeBufferPos++; + if (_unicodeEscapeBufferPos == 2) { + _endUnicodeSurrogateInterstitial(); } break; case STATE_AFTER_VALUE: { // not safe for size == 0!!! - int within = stack[stackPos - 1]; + int within = _stack[_stackPos - 1]; if (within == STACK_OBJECT) { if (c == SEND) { - endObject(); + _endObject(); } else if (c == COMMA) { - state = STATE_IN_OBJECT; + _state = STATE_IN_OBJECT; } else { //throw new RuntimeException("Expected ',' or '}' while parsing object. Got: " + c + ". " + characterCounter); } } else if (within == STACK_ARRAY) { if (c == BEND) { - endArray(); + _endArray(); } else if (c == COMMA) { - state = STATE_IN_ARRAY; + _state = STATE_IN_ARRAY; } else { //throw new RuntimeException("Expected ',' or ']' while parsing array. Got: " + c + ". " + characterCounter); @@ -197,243 +187,211 @@ class WJsonParser { break; case STATE_IN_NUMBER: if (c >= '0' && c <= '9') { - buffer[bufferPos] = c; - increaseBufferPointer(); + _buffer[_bufferPos] = c; + _increaseBufferPointer(); } else if (c == '.') { - if (doesCharArrayContain(buffer, bufferPos, '.')) { + if (_doesCharArrayContain(_buffer, _bufferPos, '.')) { //throw new RuntimeException("Cannot have multiple decimal points in a number. " + characterCounter); - } else if (doesCharArrayContain(buffer, bufferPos, 'e')) { + } else if (_doesCharArrayContain(_buffer, _bufferPos, 'e')) { //throw new RuntimeException("Cannot have a decimal point in an exponent." + characterCounter); } - buffer[bufferPos] = c; - increaseBufferPointer(); + _buffer[_bufferPos] = c; + _increaseBufferPointer(); } else if (c == 'e' || c == 'E') { - if (doesCharArrayContain(buffer, bufferPos, 'e')) { + if (_doesCharArrayContain(_buffer, _bufferPos, 'e')) { //throw new RuntimeException("Cannot have multiple exponents in a number. " + characterCounter); } - buffer[bufferPos] = c; - increaseBufferPointer(); + _buffer[_bufferPos] = c; + _increaseBufferPointer(); } else if (c == '+' || c == '-') { - char last = buffer[bufferPos - 1]; + char last = _buffer[_bufferPos - 1]; if (!(last == 'e' || last == 'E')) { //throw new RuntimeException("Can only have '+' or '-' after the 'e' or 'E' in a number." + characterCounter); } - buffer[bufferPos] = c; - increaseBufferPointer(); + _buffer[_bufferPos] = c; + _increaseBufferPointer(); } else { - result = endNumber(); + result = _endNumber(); // we have consumed one beyond the end of the number - parseChar(c); + _parseChar(c); } break; case STATE_IN_TRUE: - buffer[bufferPos] = c; - increaseBufferPointer(); - if (bufferPos == 4) { - result = endTrue(); + _buffer[_bufferPos] = c; + _increaseBufferPointer(); + if (_bufferPos == 4) { + result = _endTrue(); } break; case STATE_IN_FALSE: - buffer[bufferPos] = c; - increaseBufferPointer(); - if (bufferPos == 5) { - result = endFalse(); + _buffer[_bufferPos] = c; + _increaseBufferPointer(); + if (_bufferPos == 5) { + result = _endFalse(); } break; case STATE_IN_NULL: - buffer[bufferPos] = c; - increaseBufferPointer(); - if (bufferPos == 4) { - endNull(); + _buffer[_bufferPos] = c; + _increaseBufferPointer(); + if (_bufferPos == 4) { + _endNull(); } break; case STATE_START_DOCUMENT: //myListener->startDocument(); if (c == BBEGIN) { - startArray(); + _startArray(); } else if (c == SBEGIN) { - startObject(); + _startObject(); } break; } - characterCounter++; + _characterCounter++; return result; } - void increaseBufferPointer() { - bufferPos = min(bufferPos + 1, BUFFER_MAX_LENGTH - 1); + void _increaseBufferPointer() { + _bufferPos = _min(_bufferPos + 1, BUFFER_MAX_LENGTH - 1); } - WProperty* endString() { + WProperty* _endString() { WProperty* result = nullptr; - int popped = stack[stackPos - 1]; - stackPos--; + int popped = _stack[_stackPos - 1]; + _stackPos--; if (popped == STACK_KEY) { - buffer[bufferPos] = '\0'; - currentKey = String(buffer); - state = STATE_END_KEY; + _buffer[_bufferPos] = '\0'; + _currentKey = String(_buffer); + _state = STATE_END_KEY; } else if (popped == STACK_STRING) { - if (currentKey != "") { - buffer[bufferPos] = '\0'; - result = processKeyValue(currentKey.c_str(), buffer); + if (_currentKey != "") { + _buffer[_bufferPos] = '\0'; + const char* v = _buffer; + result = _processKeyValue(_currentKey.c_str(), _buffer); } - //buffer[bufferPos] = '\0'; - //myListener->value(String(buffer)); - state = STATE_AFTER_VALUE; + _state = STATE_AFTER_VALUE; } else { // throw new ParsingError($this->_line_number, $this->_char_number, // "Unexpected end of string."); } - bufferPos = 0; + _bufferPos = 0; return result; } - void startValue(char c) { + void _startValue(char c) { if (c == '[') { - startArray(); + _startArray(); } else if (c == '{') { - startObject(); + _startObject(); } else if (c == '"') { - startString(); + _startString(); } else if (isDigit(c)) { - startNumber(c); + _startNumber(c); } else if ((c == 't') || (c == 'T')) { - state = STATE_IN_TRUE; - buffer[bufferPos] = c; - increaseBufferPointer(); + _state = STATE_IN_TRUE; + _buffer[_bufferPos] = c; + _increaseBufferPointer(); } else if ((c == 'f') || (c == 'F')) { - state = STATE_IN_FALSE; - buffer[bufferPos] = c; - increaseBufferPointer(); + _state = STATE_IN_FALSE; + _buffer[_bufferPos] = c; + _increaseBufferPointer(); } else if ((c == 'n') || (c == 'N')) { - state = STATE_IN_NULL; - buffer[bufferPos] = c; - increaseBufferPointer(); + _state = STATE_IN_NULL; + _buffer[_bufferPos] = c; + _increaseBufferPointer(); } else { // throw new ParsingError($this->_line_number, $this->_char_number, // "Unexpected character for value: ".$c); } } - bool isDigit(char c) { + bool _isDigit(char c) { // Only concerned with the first character in a number. return (c >= '0' && c <= '9') || c == '-'; } - void endArray() { - int popped = stack[stackPos - 1]; - stackPos--; + void _endArray() { + int popped = _stack[_stackPos - 1]; + _stackPos--; if (popped != STACK_ARRAY) { // throw new ParsingError($this->_line_number, $this->_char_number, // "Unexpected end of array encountered."); } - log("jsonParser->endArray()"); - state = STATE_AFTER_VALUE; - if (stackPos == 0) { - endDocument(); + _log("jsonParser->endArray()"); + _state = STATE_AFTER_VALUE; + if (_stackPos == 0) { + _endDocument(); } } - void startKey() { - stack[stackPos] = STACK_KEY; - stackPos++; - state = STATE_IN_STRING; + void _startKey() { + _stack[_stackPos] = STACK_KEY; + _stackPos++; + _state = STATE_IN_STRING; } - void endObject() { - int popped = stack[stackPos]; - stackPos--; + void _endObject() { + int popped = _stack[_stackPos]; + _stackPos--; if (popped != STACK_OBJECT) { // throw new ParsingError($this->_line_number, $this->_char_number, // "Unexpected end of object encountered."); } - log("jsonParser->endObject()"); - state = STATE_AFTER_VALUE; - if (stackPos == 0) { - endDocument(); + _log("jsonParser->endObject()"); + _state = STATE_AFTER_VALUE; + if (_stackPos == 0) { + _endDocument(); } } - void processEscapeCharacters(char c) { + void _processEscapeCharacters(char c) { if (c == '"') { - buffer[bufferPos] = '"'; - increaseBufferPointer(); + _buffer[_bufferPos] = '"'; + _increaseBufferPointer(); } else if (c == '\\') { - buffer[bufferPos] = '\\'; - increaseBufferPointer(); + _buffer[_bufferPos] = '\\'; + _increaseBufferPointer(); } else if (c == '/') { - buffer[bufferPos] = '/'; - increaseBufferPointer(); + _buffer[_bufferPos] = '/'; + _increaseBufferPointer(); } else if (c == 'b') { - buffer[bufferPos] = 0x08; - increaseBufferPointer(); + _buffer[_bufferPos] = 0x08; + _increaseBufferPointer(); } else if (c == 'f') { - buffer[bufferPos] = '\f'; - increaseBufferPointer(); + _buffer[_bufferPos] = '\f'; + _increaseBufferPointer(); } else if (c == 'n') { - buffer[bufferPos] = '\n'; - increaseBufferPointer(); + _buffer[_bufferPos] = '\n'; + _increaseBufferPointer(); } else if (c == 'r') { - buffer[bufferPos] = '\r'; - increaseBufferPointer(); + _buffer[_bufferPos] = '\r'; + _increaseBufferPointer(); } else if (c == 't') { - buffer[bufferPos] = '\t'; - increaseBufferPointer(); + _buffer[_bufferPos] = '\t'; + _increaseBufferPointer(); } else if (c == 'u') { - state = STATE_UNICODE; - } else { - // throw new ParsingError($this->_line_number, $this->_char_number, - // "Expected escaped character after backslash. Got: ".$c); + _state = STATE_UNICODE; } - if (state != STATE_UNICODE) { - state = STATE_IN_STRING; + if (_state != STATE_UNICODE) { + _state = STATE_IN_STRING; } } - void processUnicodeCharacter(char c) { - if (!isHexCharacter(c)) { - // throw new ParsingError($this->_line_number, $this->_char_number, - // "Expected hex character for escaped Unicode character. Unicode parsed: " - // . implode($this->_unicode_buffer) . " and got: ".$c); - } - - unicodeBuffer[unicodeBufferPos] = c; - unicodeBufferPos++; - - if (unicodeBufferPos == 4) { - int codepoint = getHexArrayAsDecimal(unicodeBuffer, - unicodeBufferPos); - endUnicodeCharacter(codepoint); - return; - /*if (codepoint >= 0xD800 && codepoint < 0xDC00) { - unicodeHighSurrogate = codepoint; - unicodeBufferPos = 0; - state = STATE_UNICODE_SURROGATE; - } else if (codepoint >= 0xDC00 && codepoint <= 0xDFFF) { - if (unicodeHighSurrogate == -1) { - // throw new ParsingError($this->_line_number, - // $this->_char_number, - // "Missing high surrogate for Unicode low surrogate."); - } - int combinedCodePoint = ((unicodeHighSurrogate - 0xD800) * 0x400) + (codepoint - 0xDC00) + 0x10000; - endUnicodeCharacter(combinedCodePoint); - } else if (unicodeHighSurrogate != -1) { - // throw new ParsingError($this->_line_number, - // $this->_char_number, - // "Invalid low surrogate following Unicode high surrogate."); - endUnicodeCharacter(codepoint); - } else { - endUnicodeCharacter(codepoint); - }*/ + void _processUnicodeCharacter(char c) { + _unicodeBuffer[_unicodeBufferPos] = c; + _unicodeBufferPos++; + if (_unicodeBufferPos == 4) { + int codepoint = _getHexArrayAsDecimal(_unicodeBuffer, _unicodeBufferPos); + _endUnicodeCharacter(codepoint); + return; } } - bool isHexCharacter(char c) { + bool _isHexCharacter(char c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } - int getHexArrayAsDecimal(char hexArray[], int length) { + int _getHexArrayAsDecimal(char hexArray[], int length) { int result = 0; for (int i = 0; i < length; i++) { char current = hexArray[length - i - 1]; @@ -450,7 +408,7 @@ class WJsonParser { return result; } - bool doesCharArrayContain(char myArray[], int length, char c) { + bool _doesCharArrayContain(char myArray[], int length, char c) { for (int i = 0; i < length; i++) { if (myArray[i] == c) { return true; @@ -459,30 +417,25 @@ class WJsonParser { return false; } - void endUnicodeSurrogateInterstitial() { - char unicodeEscape = unicodeEscapeBuffer[unicodeEscapeBufferPos - 1]; - if (unicodeEscape != 'u') { - // throw new ParsingError($this->_line_number, $this->_char_number, - // "Expected '\\u' following a Unicode high surrogate. Got: " . - // $unicode_escape); - } - unicodeBufferPos = 0; - unicodeEscapeBufferPos = 0; - state = STATE_UNICODE; + void _endUnicodeSurrogateInterstitial() { + char unicodeEscape = _unicodeEscapeBuffer[_unicodeEscapeBufferPos - 1]; + _unicodeBufferPos = 0; + _unicodeEscapeBufferPos = 0; + _state = STATE_UNICODE; } - WProperty* endNumber() { + WProperty* _endNumber() { WProperty* result = nullptr; - if (currentKey != "") { - buffer[bufferPos] = '\0'; - result = processKeyValue(currentKey.c_str(), buffer); + if (_currentKey != "") { + _buffer[_bufferPos] = '\0'; + result = _processKeyValue(_currentKey.c_str(), _buffer); } - bufferPos = 0; - state = STATE_AFTER_VALUE; + _bufferPos = 0; + _state = STATE_AFTER_VALUE; return result; } - int convertDecimalBufferToInt(char myArray[], int length) { + int _convertDecimalBufferToInt(char myArray[], int length) { int result = 0; for (int i = 0; i < length; i++) { char current = myArray[length - i - 1]; @@ -491,84 +444,76 @@ class WJsonParser { return result; } - void endDocument() { - //myListener->endDocument(); - state = STATE_DONE; + void _endDocument() { + _state = STATE_DONE; } - WProperty* endTrue() { + WProperty* _endTrue() { WProperty* result = nullptr; - if (currentKey != "") { - buffer[bufferPos] = '\0'; - //String value = String(buffer); - if (strcmp(buffer, "true") == 0) { - result = processKeyValue(currentKey.c_str(), "true"); + if (_currentKey != "") { + _buffer[_bufferPos] = '\0'; + if (strcmp(_buffer, "true") == 0) { + result = _processKeyValue(_currentKey.c_str(), "true"); } } - bufferPos = 0; - state = STATE_AFTER_VALUE; + _bufferPos = 0; + _state = STATE_AFTER_VALUE; return result; } - WProperty* endFalse() { + WProperty* _endFalse() { WProperty* result = nullptr; - if (currentKey != "") { - buffer[bufferPos] = '\0'; - //String value = String(buffer); - if (strcmp(buffer, "false") == 0) { - result = processKeyValue(currentKey.c_str(), "false"); + if (_currentKey != "") { + _buffer[_bufferPos] = '\0'; + if (strcmp(_buffer, "false") == 0) { + result = _processKeyValue(_currentKey.c_str(), "false"); } } - bufferPos = 0; - state = STATE_AFTER_VALUE; + _bufferPos = 0; + _state = STATE_AFTER_VALUE; return result; } - void endNull() { - buffer[bufferPos] = '\0'; - String value = String(buffer); - if (value.equals("null")) { - //myListener->value("null"); - } - bufferPos = 0; - state = STATE_AFTER_VALUE; + void _endNull() { + _buffer[_bufferPos] = '\0'; + String value = String(_buffer); + _bufferPos = 0; + _state = STATE_AFTER_VALUE; } - void startArray() { - //myListener->startArray(); - state = STATE_IN_ARRAY; - stack[stackPos] = STACK_ARRAY; - stackPos++; + void _startArray() { + _state = STATE_IN_ARRAY; + _stack[_stackPos] = STACK_ARRAY; + _stackPos++; } - void startObject() { - //myListener->startObject(); - state = STATE_IN_OBJECT; - stack[stackPos] = STACK_OBJECT; - stackPos++; + void _startObject() { + _state = STATE_IN_OBJECT; + _stack[_stackPos] = STACK_OBJECT; + _stackPos++; } - void startString() { - stack[stackPos] = STACK_STRING; - stackPos++; - state = STATE_IN_STRING; + void _startString() { + _stack[_stackPos] = STACK_STRING; + _stackPos++; + _state = STATE_IN_STRING; } - void startNumber(char c) { - state = STATE_IN_NUMBER; - buffer[bufferPos] = c; - increaseBufferPointer(); + void _startNumber(char c) { + _state = STATE_IN_NUMBER; + _buffer[_bufferPos] = c; + _increaseBufferPointer(); } - void endUnicodeCharacter(int codepoint) { - buffer[bufferPos] = convertCodepointToCharacter(codepoint); - increaseBufferPointer(); - unicodeBufferPos = 0; - unicodeHighSurrogate = -1; - state = STATE_IN_STRING; + void _endUnicodeCharacter(int codepoint) { + _buffer[_bufferPos] = _convertCodepointToCharacter(codepoint); + _increaseBufferPointer(); + _unicodeBufferPos = 0; + _unicodeHighSurrogate = -1; + _state = STATE_IN_STRING; } - char convertCodepointToCharacter(int num) { + char _convertCodepointToCharacter(int num) { if (num <= 0x7F) return (char) (num); return ' '; diff --git a/src/WNetwork.h b/src/WNetwork.h index aab8871..ab8f617 100644 --- a/src/WNetwork.h +++ b/src/WNetwork.h @@ -210,8 +210,8 @@ class WNetwork { if ((isWifiConnected()) && (isSupportingMqtt()) && (!_mqttClient->connected()) && ((_lastMqttConnect == 0) || (now - _lastMqttConnect > 300000)) && - (strcmp(getMqttServer(), "") != 0) && - (strcmp(getMqttPort(), "") != 0)) { + (strcmp(mqttServer(), "") != 0) && + (strcmp(mqttPort(), "") != 0)) { _mqttReconnect(); _lastMqttConnect = now; } @@ -313,9 +313,9 @@ class WNetwork { this->disconnectMqtt(); return false; } - } else { - if (strcmp(getMqttServer(), "") != 0) { - _wlog->notice(F("Can't send MQTT. Not connected to server: %s"), getMqttServer()); + } else { + if (strcmp(mqttServer(), "") != 0) { + _wlog->notice(F("Can't send MQTT. Not connected to server: %s"), mqttServer()); } return false; } @@ -440,7 +440,7 @@ class WNetwork { _supportsWebServer = supportsWebServer; } - bool isSupportingMqtt() { return _supportingMqtt->getBoolean(); } + bool isSupportingMqtt() { return _supportingMqtt->asBool(); } bool isInitialMqttSent() { return _initialMqttSent; } @@ -458,19 +458,19 @@ class WNetwork { const char *getPassword() { return _settings->getString("password"); } - const char *getMqttServer() { return _settings->getString("mqttServer"); } + const char *mqttServer() { return _settings->getString("mqttServer"); } - const char *getMqttPort() { return _settings->getString("mqttPort"); } + const char *mqttPort() { return _settings->getString("mqttPort"); } - const char *getMqttBaseTopic() { return _mqttBaseTopic->c_str(); } + const char* mqttBaseTopic() { return _mqttBaseTopic->c_str(); } - const char *getMqttSetTopic() { return _mqttSetTopic->c_str(); } + const char *mqttSetTopic() { return _mqttSetTopic->c_str(); } - const char *getMqttStateTopic() { return _mqttStateTopic->c_str(); } + const char *mqttStateTopic() { return _mqttStateTopic->c_str(); } - const char *getMqttUser() { return _settings->getString("mqttUser"); } + const char *mqttUser() { return _settings->getString("mqttUser"); } - const char *getMqttPassword() { return _settings->getString("mqttPassword"); } + const char *mqttPassword() { return _settings->getString("mqttPassword"); } void addDevice(WDevice *device) { _devices->add(device); @@ -580,7 +580,7 @@ class WNetwork { void _handleDeviceStateChange(WDevice *device, bool complete) { _wlog->notice(F("Device state changed -> send device state for device '%s'"), device->id()); - String topic = String(getMqttBaseTopic()) + SLASH + String(device->id()) + SLASH + String(getMqttStateTopic()); + String topic = String(mqttBaseTopic()) + SLASH + String(device->id()) + SLASH + String(mqttStateTopic()); _mqttSendDeviceState(topic, device, complete); } @@ -611,7 +611,7 @@ class WNetwork { // Send every changed property only device->properties()->forEach( [this, complete, topic](WProperty *property) { - if ((complete) || (property->isChanged())) { + if ((complete) || (property->changed())) { if (property->isVisible(MQTT)) { WStringStream *response = getResponseStream(); WJson json(response); @@ -620,14 +620,14 @@ class WNetwork { String(topic + SLASH + String(property->id())).c_str(), response->c_str(), true); } - property->setUnChanged(); + property->changed(false); } }); if (complete) { _initialMqttSent = true; } } - device->setLastStateNotify(millis()); + device->lastStateNotify(millis()); if ((device->deepSleepMode() != DEEP_SLEEP_NONE) && ((!_supportsWebServer) || (device->areAllPropertiesRequested()))) { @@ -639,9 +639,9 @@ class WNetwork { void _mqttCallback(char *ptopic, uint8_t *payload, unsigned int length) { payload[length] = '\0'; _wlog->notice(F("Received MQTT callback. topic: '%s'; payload: '%s'; length: %d"), ptopic, (char *)payload, length); - String baseT = String(getMqttBaseTopic()); - String stateT = String(getMqttStateTopic()); - String setT = String(getMqttSetTopic()); + String baseT = String(mqttBaseTopic()); + String stateT = String(mqttStateTopic()); + String setT = String(mqttSetTopic()); String cTopic = String(ptopic); if (cTopic.startsWith(baseT)) { @@ -727,13 +727,13 @@ class WNetwork { bool _mqttReconnect() { if (this->isSupportingMqtt()) { _wlog->notice(F("Connect to MQTT server: %s; user: '%s'; password: '%s'; clientName: '%s'"), - getMqttServer(), getMqttUser(), getMqttPassword(), _getClientName(true).c_str()); + mqttServer(), mqttUser(), mqttPassword(), _getClientName(true).c_str()); // Attempt to connect - _mqttClient->setServer(getMqttServer(), String(getMqttPort()).toInt()); + _mqttClient->setServer(mqttServer(), String(mqttPort()).toInt()); bool connected = false; // Create last will message if (this->isLastWillEnabled()) { - String lastWillTopic = String(getMqttBaseTopic()); + String lastWillTopic = String(mqttBaseTopic()); lastWillTopic.concat(SLASH); WStringStream *lastWillMessage = getResponseStream(); WJson json(lastWillMessage); @@ -741,7 +741,7 @@ class WNetwork { if (device != nullptr) { lastWillTopic.concat(device->id()); lastWillTopic.concat(SLASH); - lastWillTopic.concat(getMqttStateTopic()); + lastWillTopic.concat(mqttStateTopic()); json.beginObject(); json.propertyString("idx", getIdx()); json.propertyString("ip", getDeviceIp().toString().c_str()); @@ -750,14 +750,14 @@ class WNetwork { } connected = (_mqttClient->connect( _getClientName(true).c_str(), - getMqttUser(), - getMqttPassword(), lastWillTopic.c_str(), 0, true, + mqttUser(), + mqttPassword(), lastWillTopic.c_str(), 0, true, lastWillMessage->c_str())); } else { connected = (_mqttClient->connect( _getClientName(true).c_str(), - getMqttUser(), - getMqttPassword())); + mqttUser(), + mqttPassword())); } if (connected) { @@ -771,14 +771,14 @@ class WNetwork { WJson json(response); json.beginObject(); json.propertyString("url", "http://", getDeviceIp().toString().c_str(), "/things/", device->id()); - json.propertyString("stateTopic", getMqttBaseTopic(), SLASH, device->id(), SLASH, getMqttStateTopic()); - json.propertyString("setTopic", getMqttBaseTopic(), SLASH, device->id(), SLASH, getMqttSetTopic()); + json.propertyString("stateTopic", mqttBaseTopic(), SLASH, device->id(), SLASH, mqttStateTopic()); + json.propertyString("setTopic", mqttBaseTopic(), SLASH, device->id(), SLASH, mqttSetTopic()); json.endObject(); _mqttClient->publish(topic.c_str(), response->c_str(), false); }); _mqttClient->unsubscribe("devices/#"); // Subscribe to device specific topic - _mqttClient->subscribe(String(String(getMqttBaseTopic()) + "/#").c_str()); + _mqttClient->subscribe(String(String(mqttBaseTopic()) + "/#").c_str()); _notify(false); return true; } else { @@ -874,27 +874,19 @@ class WNetwork { page->printf(HTTP_CONFIG_PAGE_BEGIN, "network"); page->printf(HTTP_TOGGLE_GROUP_STYLE, "ga", HTTP_NONE, "gb", HTTP_NONE); page->printf(HTTP_TEXT_FIELD, "Identifier (idx):", "i", "16", getIdx()); - page->printf(HTTP_TEXT_FIELD, "Wifi ssid (only 2.4G):", "s", "32", - getSsid()); - page->printf(HTTP_PASSWORD_FIELD, "Wifi password:", "p", "32", - getPassword()); + page->printf(HTTP_TEXT_FIELD, "Wifi ssid (only 2.4G):", "s", "32", getSsid()); + page->printf(HTTP_PASSWORD_FIELD, "Wifi password:", "p", "32", getPassword()); // mqtt - page->printf(HTTP_TEXT_FIELD, "MQTT Server:", "ms", "32", - getMqttServer()); - page->printf(HTTP_TEXT_FIELD, "MQTT Port:", "mo", "4", getMqttPort()); - page->printf(HTTP_TEXT_FIELD, "MQTT User:", "mu", "16", getMqttUser()); - page->printf(HTTP_PASSWORD_FIELD, "MQTT Password:", "mp", "32", - getMqttPassword()); + page->printf(HTTP_TEXT_FIELD, "MQTT Server:", "ms", "32", mqttServer()); + page->printf(HTTP_TEXT_FIELD, "MQTT Port:", "mo", "4", mqttPort()); + page->printf(HTTP_TEXT_FIELD, "MQTT User:", "mu", "16", mqttUser()); + page->printf(HTTP_PASSWORD_FIELD, "MQTT Password:", "mp", "32", mqttPassword()); // advanced mqtt options - page->printf(HTTP_CHECKBOX_OPTION, "sa", "sa", "", "tg()", - "Advanced MQTT options"); + page->printf(HTTP_CHECKBOX_OPTION, "sa", "sa", "", "tg()", "Advanced MQTT options"); page->printf(HTTP_DIV_ID_BEGIN, "ga"); - page->printf(HTTP_TEXT_FIELD, "MQTT Topic:", "mt", "32", - getMqttBaseTopic()); - page->printf(HTTP_TEXT_FIELD, "Topic for state requests:", "mtg", "16", - getMqttStateTopic()); - page->printf(HTTP_TEXT_FIELD, "Topic for setting values:", "mts", "16", - getMqttSetTopic()); + page->printf(HTTP_TEXT_FIELD, "MQTT Topic:", "mt", "32", mqttBaseTopic()); + page->printf(HTTP_TEXT_FIELD, "Topic for state requests:", "mtg", "16", mqttStateTopic()); + page->printf(HTTP_TEXT_FIELD, "Topic for setting values:", "mts", "16", mqttSetTopic()); page->print(FPSTR(HTTP_DIV_END)); page->printf(HTTP_TOGGLE_FUNCTION_SCRIPT, "tg()", "sa", "ga", "gb"); page->print(FPSTR(HTTP_CONFIG_SAVE_BUTTON)); @@ -908,10 +900,10 @@ class WNetwork { bool equalsOldIdx = _idx->equalsString(mbt.c_str()); String itx = request->arg("i"); - _idx->setString(itx.c_str()); - _ssid->setString(request->arg("s").c_str()); + _idx->asString(itx.c_str()); + _ssid->asString(request->arg("s").c_str()); _settings->setString("password", request->arg("p").c_str()); - _supportingMqtt->setBoolean(true); + _supportingMqtt->asBool(true); _settings->setString("mqttServer", request->arg("ms").c_str()); String mqtt_port = request->arg("mo"); _settings->setString("mqttPort", @@ -919,17 +911,17 @@ class WNetwork { _settings->setString("mqttUser", request->arg("mu").c_str()); _settings->setString("mqttPassword", request->arg("mp").c_str()); // advanced mqtt options - _mqttBaseTopic->setString(equalsOldIdx ? itx.c_str() : mbt.c_str()); + _mqttBaseTopic->asString(equalsOldIdx ? itx.c_str() : mbt.c_str()); String subTopic = request->arg("mtg"); if (subTopic.startsWith(SLASH)) subTopic.substring(1); if (subTopic.endsWith(SLASH)) subTopic.substring(0, subTopic.length() - 1); if (subTopic.equals("")) subTopic = DEFAULT_TOPIC_STATE; - _mqttStateTopic->setString(subTopic.c_str()); + _mqttStateTopic->asString(subTopic.c_str()); subTopic = request->arg("mts"); if (subTopic.startsWith(SLASH)) subTopic.substring(1); if (subTopic.endsWith(SLASH)) subTopic.substring(0, subTopic.length() - 1); if (subTopic.equals("")) subTopic = DEFAULT_TOPIC_SET; - _mqttSetTopic->setString(subTopic.c_str()); + _mqttSetTopic->asString(subTopic.c_str()); _settings->save(); _restart(request, "Settings saved. Subscribe to topic 'devices/#' at your broker to get device information."); } @@ -1234,14 +1226,14 @@ class WNetwork { _mqttStateTopic = _settings->setNetworkString("mqttStateTopic", DEFAULT_TOPIC_STATE); _mqttSetTopic = _settings->setNetworkString("mqttSetTopic", DEFAULT_TOPIC_SET); if (_settings->existsNetworkSettings()) { - if (strcmp(getMqttBaseTopic(), "") == 0) { - _mqttBaseTopic->setString(_getClientName(true).c_str()); + if (strcmp(mqttBaseTopic(), "") == 0) { + _mqttBaseTopic->asString(_getClientName(true).c_str()); } if ((isSupportingMqtt()) && (_mqttClient != nullptr)) { this->disconnectMqtt(); } _wlog->debug(F("SSID: '%s'; MQTT enabled: %T; MQTT server: '%s'; MQTT port: %s; WebServer started: %T"), - getSsid(), isSupportingMqtt(), getMqttServer(), getMqttPort(), isWebServerRunning()); + getSsid(), isSupportingMqtt(), mqttServer(), mqttPort(), isWebServerRunning()); } else { _wlog->notice(F("Network settings are missing.")); } @@ -1305,7 +1297,7 @@ class WNetwork { json.beginObject(); property->toJsonValue(&json); json.endObject(); - property->setRequested(true); + property->requested(true); request->send(response); } } diff --git a/src/WOutput.h b/src/WOutput.h index 8228575..56a3f02 100644 --- a/src/WOutput.h +++ b/src/WOutput.h @@ -52,7 +52,7 @@ class WOutput { } virtual void handleChangedProperty(WValue value) { - this->setOn(value.asBoolean); + this->setOn(value.asBool); } virtual void loop(unsigned long now) {} diff --git a/src/WPin.h b/src/WPin.h deleted file mode 100644 index 554df90..0000000 --- a/src/WPin.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef W_PIN_H -#define W_PIN_H - -#include "WProperty.h" - -const int NO_PIN = -1; -const int NO_MODE = -1; - -class WPin { -public: - WPin(int pin, int mode) { - this->pin = pin; - this->property = nullptr; - if ((this->pin != NO_PIN) && ((mode == INPUT) || (mode == OUTPUT) || (mode == INPUT_PULLUP))) { - pinMode(this->pin, mode); - } - } - - WProperty* getProperty() { - return property; - } - - void setProperty(WProperty* property) { - if (this->property != property) { - this->property = property; - this->loop(millis()); - } - } - - bool hasProperty() { - return (this->property != nullptr); - } - - virtual void loop(unsigned long now) { - } - - WPin* next = nullptr; - -protected: - - virtual bool isInitialized() { - return (pin != NO_PIN); - } - - int getPin() { - return pin; - } - -private: - int pin; - WProperty* property; -}; - -#endif diff --git a/src/WProperty.h b/src/WProperty.h index 2b79996..0dfe295 100644 --- a/src/WProperty.h +++ b/src/WProperty.h @@ -62,7 +62,7 @@ class WProperty { } } - void setOnValueRequest(TOnPropertyChange onValueRequest) { + void onValueRequest(TOnPropertyChange onValueRequest) { _onValueRequest = onValueRequest; } @@ -71,17 +71,15 @@ class WProperty { _listeners.push_back(onChange); } - void setDeviceNotification(TOnPropertyChange deviceNotification) { + void deviceNotification(TOnPropertyChange deviceNotification) { _deviceNotification = deviceNotification; } const char* id() { return _id; } - const char* title() { return _title; } + const char* title() { return _title; } - WPropertyType type() { return _type; } - - byte getLength() { + byte length() { switch (_type) { case STRING: return (_valueNull ? 0 : strlen(_value.string)); @@ -97,59 +95,62 @@ class WProperty { case BOOLEAN: return 1; case BYTE_ARRAY: - return (_valueNull ? 0 : getByteArrayLength()); + return (_valueNull ? 0 : byteArrayLength()); } return 0; } - void setType(WPropertyType type) { _type = type; } + WPropertyType type() { return _type; } + + void type(WPropertyType type) { _type = type; } const char* atType() { return _atType; } bool isNull() { return (_valueNull); } - bool isRequested() { return (_requested); } + void setNull() { _valueNull = true; } - void setRequested(bool requested) { - _requested = ((requested) && (!isNull())); - } + bool requested() { return (_requested); } - void setNull() { _valueNull = true; } + void requested(bool requested) { + _requested = ((requested) && (!isNull())); + } - bool isChanged() { return (_changed); } + bool changed() { return (_changed); } - void setUnChanged() { _changed = false; } + void changed(bool changed) { _changed = changed; } - virtual bool parse(String value) { - if ((!isReadOnly()) && (value != nullptr)) { + virtual bool parse(const char* value) { + if ((!readOnly()) && (value != nullptr)) { + String v = String(value); switch (_type) { case BOOLEAN: { - value.toLowerCase(); - setBoolean(value.equals("true")); + v.toLowerCase(); + asBool(v.equals("true")); return true; } case DOUBLE: { - setDouble(value.toDouble()); + asDouble(v.toDouble()); return true; } case SHORT: { - setShort(value.toInt()); + asShort(v.toInt()); return true; } case INTEGER: { - setInteger(value.toInt()); + asInt(v.toInt()); return true; } case UNSIGNED_LONG: { - setUnsignedLong(value.toInt()); + asUnsignedLong(v.toInt()); return true; } case BYTE: { - setByte(value.toInt()); + asByte(v.toInt()); return true; } case STRING: { - setString(value.c_str()); + asString(value); return true; } case BYTE_ARRAY: { @@ -161,32 +162,32 @@ class WProperty { return false; } - bool getBoolean() { - requestValue(); - return (!_valueNull ? _value.asBoolean : false); + bool asBool() { + _requestValue(); + return (!_valueNull ? _value.asBool : false); } - void setBoolean(bool newValue) { + void asBool(bool newValue) { if (_type != BOOLEAN) { return; } - bool changed = ((_valueNull) || (_value.asBoolean != newValue)); + bool changed = ((_valueNull) || (_value.asBool != newValue)); if (changed) { WValue valueB; - valueB.asBoolean = newValue; - this->setValue(valueB); + valueB.asBool = newValue; + this->value(valueB); } } - void toggleBoolean() { + void toggleBool() { if (_type != BOOLEAN) { return; } - setBoolean(!getBoolean()); + asBool(!asBool()); } - double getDouble() { - requestValue(); + double asDouble() { + _requestValue(); return (!_valueNull ? _value.asDouble : 0.0); } @@ -195,7 +196,7 @@ class WProperty { return ((diff < precision) && (-diff < precision)); } - void setDouble(double newValue) { + void asDouble(double newValue) { if (_type != DOUBLE) { return; } @@ -203,7 +204,7 @@ class WProperty { if (changed) { WValue valueB; valueB.asDouble = newValue; - this->setValue(valueB); + this->value(valueB); } } @@ -212,29 +213,29 @@ class WProperty { (isEqual(_value.asDouble, number, 0.01))); } - int getInteger() { - requestValue(); - return (!_valueNull ? _value.asInteger : 0); + int asInt() { + _requestValue(); + return (!_valueNull ? _value.asInt : 0); } - void setInteger(int newValue) { + void asInt(int newValue) { if (_type != INTEGER) { return; } - bool changed = ((_valueNull) || (_value.asInteger != newValue)); + bool changed = ((_valueNull) || (_value.asInt != newValue)); if (changed) { WValue valueB; - valueB.asInteger = newValue; - this->setValue(valueB); + valueB.asInt = newValue; + this->value(valueB); } } - short getShort() { - requestValue(); + short asShort() { + _requestValue(); return (!_valueNull ? _value.asShort : 0); } - void setShort(short newValue) { + void asShort(short newValue) { if (_type != SHORT) { return; } @@ -242,16 +243,16 @@ class WProperty { if (changed) { WValue valueB; valueB.asShort = newValue; - this->setValue(valueB); + this->value(valueB); } } - unsigned long getUnsignedLong() { - requestValue(); + unsigned long asUnsignedLong() { + _requestValue(); return (!_valueNull ? _value.asUnsignedLong : 0); } - void setUnsignedLong(unsigned long newValue) { + void asUnsignedLong(unsigned long newValue) { if (_type != UNSIGNED_LONG) { return; } @@ -260,17 +261,17 @@ class WProperty { if (changed) { WValue valueB; valueB.asUnsignedLong = newValue; - this->setValue(valueB); + this->value(valueB); } } bool equalsInteger(int number) { - return ((!_valueNull) && (_value.asInteger == number)); + return ((!_valueNull) && (_value.asInt == number)); } bool isIntegerBetween(int lowerLimit, int upperLimit) { - return ((!_valueNull) && (_value.asInteger >= lowerLimit) && - (_value.asInteger < upperLimit)); + return ((!_valueNull) && (_value.asInt >= lowerLimit) && + (_value.asInt < upperLimit)); } bool equalsShort(short number) { @@ -299,12 +300,12 @@ class WProperty { (_value.asUnsignedLong < upperLimit)); } - byte getByte() { - requestValue(); + byte asByte() { + _requestValue(); return (!_valueNull ? _value.asByte : 0x00); } - void setByte(byte newValue) { + void asByte(byte newValue) { if (_type != BYTE) { return; } @@ -312,24 +313,19 @@ class WProperty { if (changed) { WValue valueB; valueB.asByte = newValue; - this->setValue(valueB); + this->value(valueB); } } bool equalsByte(byte number) { return ((!_valueNull) && (_value.asByte == number)); - } - - char* c_str() { - requestValue(); - return _value.string; - } + } - byte* getByteArray() { + byte* asByteArray() { if (_type != BYTE_ARRAY) { return 0; } else { - byte length = getByteArrayLength(); + byte length = byteArrayLength(); if (length > 0) { byte* result = (byte*) malloc(length); for (int i = 0; i < length; i++) { @@ -342,7 +338,7 @@ class WProperty { } } - bool setByteArray(byte length, const byte* newValue) { + bool asByteArray(byte length, const byte* newValue) { if (_type != BYTE_ARRAY) { return false; } @@ -361,16 +357,16 @@ class WProperty { _valueNull = false; _changed = true; valueChanged(); - notify(); + _notify(); } return changed; } - byte getByteArrayLength() { return (!_valueNull ? _value.asByteArray[0] : 0); } + byte byteArrayLength() { return (!_valueNull ? _value.asByteArray[0] : 0); } - byte getByteArrayValue(byte index) { return _value.asByteArray[index + 1]; } + byte byteArrayValue(byte index) { return _value.asByteArray[index + 1]; } - bool setByteArrayValue(byte index, byte newValue) { + bool byteArrayValue(byte index, byte newValue) { if (_type != BYTE_ARRAY) { return false; } @@ -380,38 +376,47 @@ class WProperty { _valueNull = false; _changed = true; valueChanged(); - notify(); + _notify(); } return changed; } - bool getByteArrayBitValue(byte byteIndex, byte bitIndex) { - return bitRead(getByteArrayValue(byteIndex), bitIndex); + bool byteArrayBitValue(byte byteIndex, byte bitIndex) { + return bitRead(byteArrayValue(byteIndex), bitIndex); } - bool setByteArrayBitValue(byte byteIndex, byte bitIndex, bool bitValue) { + bool byteArrayBitValue(byte byteIndex, byte bitIndex, bool bitValue) { if (_type != BYTE_ARRAY) { return false; } - byte v = getByteArrayValue(byteIndex); + byte v = byteArrayValue(byteIndex); if (bitValue) { bitSet(v, bitIndex); } else { bitClear(v, bitIndex); } - return setByteArrayValue(byteIndex, v); + return byteArrayValue(byteIndex, v); } - WValue getValue() { return _value; } + WValue value() { return _value; } + + char* c_str() { + _requestValue(); + return _value.string; + } + + char* asString() { + return c_str(); + } - bool setString(const char* newValue) { + bool asString(const char* newValue) { if (_type != STRING) { return false; } bool changed = ((_valueNull) || (strcmp(_value.string, newValue) != 0)); if ((changed) && (newValue != nullptr) && (this->hasEnums())) { // proceed only at valid enums - changed = (getEnumIndex(this, newValue) != 0xFF); + changed = (enumIndex(this, newValue) != 0xFF); } if (changed) { if (!_valueNull) { @@ -431,44 +436,44 @@ class WProperty { } _changed = true; valueChanged(); - notify(); + _notify(); } return changed; } - bool isReadOnly() { return _readOnly; } + bool readOnly() { return _readOnly; } - void setReadOnly(bool readOnly) { _readOnly = readOnly; } + void readOnly(bool readOnly) { _readOnly = readOnly; } - const char* getUnit() { return _unit; } + const char* unit() { return _unit; } - void setUnit(const char* unit) { _unit = unit; } + void unit(const char* unit) { _unit = unit; } - double getMultipleOf() { return _multipleOf; } + double multipleOf() { return _multipleOf; } - void setMultipleOf(double multipleOf) { _multipleOf = multipleOf; } + void multipleOf(double multipleOf) { _multipleOf = multipleOf; } virtual void toJsonValue(WJson* json, bool onlyValue = false) { - requestValue(); + _requestValue(); const char* memberName = (onlyValue ? nullptr : id()); switch (_type) { case BOOLEAN: - json->propertyBoolean(memberName, getBoolean()); + json->propertyBoolean(memberName, asBool()); break; case DOUBLE: - json->propertyDouble(memberName, getDouble()); + json->propertyDouble(memberName, asDouble()); break; case INTEGER: - json->propertyInteger(memberName, getInteger()); + json->propertyInteger(memberName, asInt()); break; case SHORT: - json->propertyShort(memberName, getShort()); + json->propertyShort(memberName, asShort()); break; case UNSIGNED_LONG: - json->propertyUnsignedLong(memberName, getUnsignedLong()); + json->propertyUnsignedLong(memberName, asUnsignedLong()); break; case BYTE: - json->propertyByte(memberName, getByte()); + json->propertyByte(memberName, asByte()); break; case STRING: if (!onlyValue) @@ -478,7 +483,7 @@ class WProperty { break; case BYTE_ARRAY: // tbi - json->propertyByteArray(memberName, getLength(), getByteArray()); + json->propertyByteArray(memberName, length(), asByteArray()); break; } _requested = true; @@ -511,16 +516,16 @@ class WProperty { break; } // readOnly - if (this->isReadOnly()) { + if (this->readOnly()) { json->propertyBoolean("readOnly", true); } // unit - if (this->getUnit() != "") { - json->propertyString("unit", this->getUnit()); + if (this->unit() != "") { + json->propertyString("unit", this->unit()); } // multipleOf - if (this->getMultipleOf() > 0.0) { - json->propertyDouble("multipleOf", this->getMultipleOf()); + if (this->multipleOf() > 0.0) { + json->propertyDouble("multipleOf", this->multipleOf()); } // enum if (this->hasEnums()) { @@ -528,22 +533,22 @@ class WProperty { _enums->forEach([this, json](WProperty* propE){ switch (_type) { case BOOLEAN: - json->boolean(propE->getBoolean()); + json->boolean(propE->asBool()); break; case DOUBLE: - json->numberDouble(propE->getDouble()); + json->numberDouble(propE->asDouble()); break; case SHORT: - json->numberShort(propE->getShort()); + json->numberShort(propE->asShort()); break; case INTEGER: - json->numberInteger(propE->getInteger()); + json->numberInteger(propE->asInt()); break; case UNSIGNED_LONG: - json->numberUnsignedLong(propE->getUnsignedLong()); + json->numberUnsignedLong(propE->asUnsignedLong()); break; case BYTE: - json->numberByte(propE->getByte()); + json->numberByte(propE->asByte()); break; case STRING: json->string(propE->c_str()); @@ -570,7 +575,7 @@ class WProperty { return; } WProperty* valueE = new WProperty("", "", _type, ""); - valueE->setBoolean(enumBoolean); + valueE->asBool(enumBoolean); this->addEnum(valueE); } @@ -579,7 +584,7 @@ class WProperty { return; } WProperty* valueE = new WProperty("", "", _type, ""); - valueE->setDouble(enumNumber); + valueE->asDouble(enumNumber); this->addEnum(valueE); } @@ -588,7 +593,7 @@ class WProperty { return; } WProperty* valueE = new WProperty("", "", _type, ""); - valueE->setInteger(enumNumber); + valueE->asInt(enumNumber); this->addEnum(valueE); } @@ -597,7 +602,7 @@ class WProperty { return; } WProperty* valueE = new WProperty("", "", _type, ""); - valueE->setShort(enumNumber); + valueE->asShort(enumNumber); this->addEnum(valueE); } @@ -606,7 +611,7 @@ class WProperty { return; } WProperty* valueE = new WProperty("", "", _type, ""); - valueE->setUnsignedLong(enumNumber); + valueE->asUnsignedLong(enumNumber); this->addEnum(valueE); } @@ -615,7 +620,7 @@ class WProperty { return; } WProperty* valueE = new WProperty("", "", _type, ""); - valueE->setByte(enumByte); + valueE->asByte(enumByte); this->addEnum(valueE); } @@ -624,16 +629,16 @@ class WProperty { return; } WProperty* valueE = new WProperty("", "", _type, ""); - valueE->setString(enumString); + valueE->asString(enumString); this->addEnum(valueE); } - byte getEnumIndex() { return getEnumIndex(this, this->getValue().string); } + byte enumIndex() { return enumIndex(this, this->value().string); } - static byte getEnumIndex(WProperty* property, const char* enumString) { + static byte enumIndex(WProperty* property, const char* enumString) { if ((property->hasEnums()) && (enumString != nullptr) && (property->type() == STRING)) { WProperty* en = property->_enums->getIf([property, enumString](WProperty* en) { - return (strcmp(en->getValue().string, enumString) == 0); + return (strcmp(en->value().string, enumString) == 0); }); return (en != nullptr ? property->_enums->indexOf(en) : 0xFF); } else { @@ -645,14 +650,14 @@ class WProperty { } } - const char* getEnumString(byte enumIndex) { - return getEnumString(this, enumIndex); + const char* enumString(byte enumIndex) { + return enumString(this, enumIndex); } - static const char* getEnumString(WProperty* property, byte enumIndex) { + static const char* enumString(WProperty* property, byte enumIndex) { if ((property->hasEnums()) && (property->type() == STRING)) { WProperty* en = property->_enums->get(enumIndex); - return (en != nullptr ? en->getValue().string : nullptr); + return (en != nullptr ? en->value().string : nullptr); } else { return nullptr; } @@ -690,35 +695,35 @@ class WProperty { WPropertyVisibility visibility() { return _visibility; } - void setVisibility(WPropertyVisibility visibility) { + void visibility(WPropertyVisibility visibility) { _visibility = visibility; } - void setVisibility(bool mqtt, bool webthing) { + void visibility(bool mqtt, bool webthing) { if ((mqtt) && (webthing)) { - setVisibility(ALL); + visibility(ALL); } else if ((!mqtt) && (!webthing)) { - setVisibility(NONE); + visibility(NONE); } else if (mqtt) { - setVisibility(MQTT); + visibility(MQTT); } else { - setVisibility(WEBTHING); + visibility(WEBTHING); } } - void setVisibilityMqtt(bool value) { + void visibilityMqtt(bool value) { if ((value) && (_visibility != MQTT) && (_visibility != ALL)) { - setVisibility(_visibility == WEBTHING ? ALL : MQTT); + visibility(_visibility == WEBTHING ? ALL : MQTT); } else if ((!value) && (_visibility != NONE) && (_visibility != WEBTHING)) { - setVisibility(_visibility == ALL ? WEBTHING : NONE); + visibility(_visibility == ALL ? WEBTHING : NONE); } } - void setVisibilityWebthing(bool value) { + void visibilityWebthing(bool value) { if ((value) && (_visibility != WEBTHING) && (_visibility != ALL)) { - setVisibility(_visibility == MQTT ? ALL : WEBTHING); + visibility(_visibility == MQTT ? ALL : WEBTHING); } else if ((!value) && (_visibility != NONE) && (_visibility != MQTT)) { - setVisibility(_visibility == ALL ? MQTT : NONE); + visibility(_visibility == ALL ? MQTT : NONE); } } @@ -726,7 +731,7 @@ class WProperty { return ((_visibility == ALL) || (_visibility == visibility)); } - void setId(const char* id) { + void id(const char* id) { delete _id; _id = new char[strlen(id) + 1]; strcpy(_id, id); @@ -758,12 +763,12 @@ class WProperty { _outputs = nullptr; } - void setValue(WValue newValue) { - _value = newValue; + void value(WValue value) { + _value = value; _valueNull = false; _changed = true; valueChanged(); - notify(); + _notify(); } virtual void valueChanged() {} @@ -793,7 +798,7 @@ class WProperty { WList* _outputs; WList* _enums; - void notify() { + void _notify() { if (!_valueRequesting) { _notifying = true; if (!_listeners.empty()) { @@ -812,7 +817,7 @@ class WProperty { } } - void requestValue() { + void _requestValue() { if ((!_notifying) && (_onValueRequest)) { _valueRequesting = true; _onValueRequest(this); @@ -834,7 +839,7 @@ class WRangeProperty: public WProperty { } int getMinAsInteger() { - return _min.asInteger; + return _min.asInt; } double getMaxAsDouble() { @@ -842,18 +847,18 @@ class WRangeProperty: public WProperty { } int getMaxAsInteger() { - return _max.asInteger; + return _max.asInt; } byte getScaledToMax0xFF() { int v = 0; switch (this->type()) { case DOUBLE: { - v = (int) round(getDouble() * 0xFF / getMaxAsDouble()); + v = (int) round(asDouble() * 0xFF / getMaxAsDouble()); break; } case INTEGER: { - v = getInteger() * 0xFF / getMaxAsInteger(); + v = asInt() * 0xFF / getMaxAsInteger(); break; } } @@ -924,7 +929,7 @@ class WColorProperty : public WProperty { if (_blue < 0x10) result.print("0"); result.print(buffer); _changeValue = true; - setString(result.c_str()); + asString(result.c_str()); _changeValue = false; } @@ -943,9 +948,9 @@ class WColorProperty : public WProperty { } bool parse(String value) { - if ((!isReadOnly()) && (value != nullptr)) { + if ((!readOnly()) && (value != nullptr)) { if ((value.startsWith("#")) && (value.length() == 7)) { - setString(value.c_str()); + asString(value.c_str()); return true; } else if ((value.startsWith("rgb(")) && (value.endsWith(")"))) { value = value.substring(4, value.length() - 1); diff --git a/src/WProps.h b/src/WProps.h index 79f6d44..6b7807d 100644 --- a/src/WProps.h +++ b/src/WProps.h @@ -37,23 +37,23 @@ class WProps { static WRangeProperty* createTargetTemperatureProperty(const char* id, const char* title) { WRangeProperty* p = new WRangeProperty(id, title, DOUBLE, WValue::ofDouble(15.0), WValue::ofDouble(25.0), TYPE_TARGET_TEMPERATURE_PROPERTY); - p->setMultipleOf(0.5); - p->setUnit(UNIT_CELSIUS); + p->multipleOf(0.5); + p->unit(UNIT_CELSIUS); return p; } static WProperty* createTemperatureProperty(const char* id, const char* title) { WProperty* p = new WProperty(id, title, DOUBLE, TYPE_TEMPERATURE_PROPERTY); - p->setReadOnly(true); - p->setUnit(UNIT_CELSIUS); + p->readOnly(true); + p->unit(UNIT_CELSIUS); return p; } static WRangeProperty* createHumidityProperty(const char* id, const char* title) { WRangeProperty* p = new WRangeProperty(id, title, DOUBLE, WValue::ofDouble(0.0), WValue::ofDouble(100.0), TYPE_HUMIDITY_PROPERTY); - p->setReadOnly(true); - p->setUnit(UNIT_PERCENT); + p->readOnly(true); + p->unit(UNIT_PERCENT); return p; } @@ -63,12 +63,12 @@ class WProps { } static WRangeProperty* createLevelIntProperty(const char* id, const char* title, int min, int max) { - WRangeProperty* p = new WRangeProperty(id, title, INTEGER, WValue::ofInteger(min), WValue::ofInteger(max), TYPE_LEVEL_PROPERTY); + WRangeProperty* p = new WRangeProperty(id, title, INTEGER, WValue::ofInt(min), WValue::ofInt(max), TYPE_LEVEL_PROPERTY); return p; } static WRangeProperty* createBrightnessProperty(const char* id, const char* title, byte min = 0, byte max = 100) { - WRangeProperty* p = new WRangeProperty(id, title, INTEGER, WValue::ofInteger(min), WValue::ofInteger(max), TYPE_BRIGHTNESS_PROPERTY); + WRangeProperty* p = new WRangeProperty(id, title, INTEGER, WValue::ofInt(min), WValue::ofInt(max), TYPE_BRIGHTNESS_PROPERTY); return p; } @@ -87,7 +87,7 @@ class WProps { static WProperty* createHeatingCoolingProperty(const char* id, const char* title) { WProperty* p = new WProperty(id, title, STRING, TYPE_HEATING_COOLING_PROPERTY); - p->setReadOnly(true); + p->readOnly(true); p->addEnumString(VALUE_OFF); p->addEnumString(VALUE_HEATING); p->addEnumString(VALUE_COOLING); diff --git a/src/WSettings.h b/src/WSettings.h index 8fb70ae..32ca7e4 100644 --- a/src/WSettings.h +++ b/src/WSettings.h @@ -90,47 +90,47 @@ class WSettings { ((!networkSetting) && (_existsSettingsApplication)))) { switch (property->type()) { case BOOLEAN: { - property->setBoolean(EEPROM.read(_address) == 0xFF); + property->asBool(EEPROM.read(_address) == 0xFF); break; } case DOUBLE: { double d; EEPROM.get(_address, d); - property->setDouble(d); + property->asDouble(d); break; } case SHORT: { short value = 0; EEPROM.get(_address, value); - property->setShort(value); + property->asShort(value); break; } case INTEGER: { int value = 0; EEPROM.get(_address, value); - property->setInteger(value); + property->asInt(value); break; } case UNSIGNED_LONG: { unsigned long value = 0; EEPROM.get(_address, value); - property->setUnsignedLong(value); + property->asUnsignedLong(value); break; } case BYTE: { int b2 = EEPROM.read(_address); - property->setByte(b2); + property->asByte(b2); break; } case BYTE_ARRAY: { const byte* ba = readByteArray(_address); - property->setByteArray(readByteArrayLength(_address), ba); + property->asByteArray(readByteArrayLength(_address), ba); delete ba; break; } case STRING: { const char* rs = readString(_address); - property->setString(rs); + property->asString(rs); delete rs; break; } @@ -148,7 +148,7 @@ class WSettings { bool getBoolean(const char* id) { WProperty* setting = getSetting(id); - return (setting != nullptr ? setting->getBoolean() : false); + return (setting != nullptr ? setting->asBool() : false); } WProperty* setBoolean(const char* id, bool value) { @@ -161,7 +161,7 @@ class WSettings { byte getByte(const char* id) { WProperty* setting = getSetting(id); - return (setting != nullptr ? setting->getByte() : 0x00); + return (setting != nullptr ? setting->asByte() : 0x00); } WProperty* setByte(const char* id, byte value) { @@ -172,81 +172,81 @@ class WSettings { WProperty* setting = getSetting(id); if (setting == nullptr) { setting = WProps::createByteProperty(id, id); - setting->setByte(value); + setting->asByte(value); add(setting); - if ((max > 0) && (setting->getByte() > max)) { - setting->setByte(value); + if ((max > 0) && (setting->asByte() > max)) { + setting->asByte(value); } } else { - setting->setByte(value); + setting->asByte(value); } return setting; } int getInteger(const char* id) { WProperty* setting = getSetting(id); - return (setting != nullptr ? setting->getInteger() : 0); + return (setting != nullptr ? setting->asInt() : 0); } WProperty* setInteger(const char* id, int value) { WProperty* setting = getSetting(id); if (setting == nullptr) { setting = WProps::createIntegerProperty(id, id); - setting->setInteger(value); + setting->asInt(value); add(setting); } else { - setting->setInteger(value); + setting->asInt(value); } return setting; } short getShort(const char* id) { WProperty* setting = getSetting(id); - return (setting != nullptr ? setting->getShort() : 0); + return (setting != nullptr ? setting->asShort() : 0); } WProperty* setShort(const char* id, short value) { WProperty* setting = getSetting(id); if (setting == nullptr) { setting = WProps::createShortProperty(id, id); - setting->setShort(value); + setting->asShort(value); add(setting); } else { - setting->setShort(value); + setting->asShort(value); } return setting; } unsigned long getUnsignedLong(const char* id) { WProperty* setting = getSetting(id); - return (setting != nullptr ? setting->getUnsignedLong() : 0); + return (setting != nullptr ? setting->asUnsignedLong() : 0); } WProperty* setUnsignedLong(const char* id, unsigned long value) { WProperty* setting = getSetting(id); if (setting == nullptr) { setting = WProps::createUnsignedLongProperty(id, id); - setting->setUnsignedLong(value); + setting->asUnsignedLong(value); add(setting); } else { - setting->setUnsignedLong(value); + setting->asUnsignedLong(value); } return setting; } double getDouble(const char* id) { WProperty* setting = getSetting(id); - return (setting != nullptr ? setting->getDouble() : 0.0); + return (setting != nullptr ? setting->asDouble() : 0.0); } WProperty* setDouble(const char* id, double value) { WProperty* setting = getSetting(id); if (setting == nullptr) { setting = WProps::createDoubleProperty(id, id); - setting->setDouble(value); + setting->asDouble(value); add(setting); } else { - setting->setDouble(value); + setting->asDouble(value); } return setting; } @@ -268,11 +268,11 @@ class WSettings { WProperty* setting = getSetting(id); if (setting == nullptr) { setting = new WProperty(id, id, BYTE_ARRAY, ""); - setting->setByteArray(length, value); - setting->setVisibility(NONE); + setting->asByteArray(length, value); + setting->visibility(NONE); add(setting); } else { - setting->setByteArray(length, value); + setting->asByteArray(length, value); } return setting; } @@ -308,10 +308,10 @@ class WSettings { WProperty* setting = getSetting(id); if (setting == nullptr) { setting = WProps::createBooleanProperty(id, id); - setting->setBoolean(value); + setting->asBool(value); add(setting, networkSetting); } else { - setting->setBoolean(value); + setting->asBool(value); } return setting; } @@ -320,10 +320,10 @@ class WSettings { WProperty* setting = getSetting(id); if (setting == nullptr) { setting = WProps::createStringProperty(id, id); - setting->setString(value); + setting->asString(value); add(setting, networkSetting); } else { - setting->setString(value); + setting->asString(value); } return setting; } @@ -331,31 +331,31 @@ class WSettings { void save(WProperty* setting) { switch (setting->type()){ case BOOLEAN: { - EEPROM.write(_address, (setting->getBoolean() ? 0xFF : 0x00)); + EEPROM.write(_address, (setting->asBool() ? 0xFF : 0x00)); break; } case BYTE: { - EEPROM.write(_address, setting->getByte()); + EEPROM.write(_address, setting->asByte()); break; } case SHORT: { - EEPROM.put(_address, setting->getShort()); + EEPROM.put(_address, setting->asShort()); break; } case INTEGER: { - EEPROM.put(_address, setting->getInteger()); + EEPROM.put(_address, setting->asInt()); break; } case UNSIGNED_LONG: { - EEPROM.put(_address, setting->getUnsignedLong()); + EEPROM.put(_address, setting->asUnsignedLong()); break; } case DOUBLE: { - EEPROM.put(_address, setting->getDouble()); + EEPROM.put(_address, setting->asDouble()); break; } case BYTE_ARRAY: { - writeByteArray(_address, setting->getByteArrayLength(), setting->getByteArray()); + writeByteArray(_address, setting->byteArrayLength(), setting->asByteArray()); break; } case STRING: { @@ -379,9 +379,9 @@ class WSettings { switch (setting->type()){ case BYTE_ARRAY: case STRING: - return (setting->getLength() + 1); + return (setting->length() + 1); } - return setting->getLength(); + return setting->length(); } const byte readByteArrayLength(int address) { diff --git a/src/WSwitch.h b/src/WSwitch.h index 8a3315c..ebd6fb4 100644 --- a/src/WSwitch.h +++ b/src/WSwitch.h @@ -94,7 +94,7 @@ class WSwitch: public WInput { setTriggerValue(true); if (property() != nullptr) { - property()->setBoolean(!property()->getBoolean()); + property()->asBool(!property()->asBool()); } if (_onPressed) { _onPressed(); @@ -145,7 +145,7 @@ class WSwitch: public WInput { void setTriggerValue(bool triggered) { if (_triggerProperty != nullptr) { - _triggerProperty->setBoolean(triggered); + _triggerProperty->asBool(triggered); } } diff --git a/src/WValue.h b/src/WValue.h index 0a5119c..34f03cf 100644 --- a/src/WValue.h +++ b/src/WValue.h @@ -4,10 +4,10 @@ #include union WValue { - bool asBoolean; + bool asBool; double asDouble; short asShort; - int asInteger; + int asInt; unsigned long asUnsignedLong; byte asByte; char* string; @@ -19,9 +19,9 @@ union WValue { return r; } - static WValue ofInteger(int d) { + static WValue ofInt(int d) { WValue r; - r.asInteger = d; + r.asInt = d; return r; } }; diff --git a/src/hw/PT2314.h b/src/hw/PT2314.h new file mode 100644 index 0000000..f0b9a2f --- /dev/null +++ b/src/hw/PT2314.h @@ -0,0 +1,222 @@ +#ifndef W_PT2314_h +#define W_PT2314_h + +/* Arduino PT2314 Library + * Copyright (C) 2013 by Andy Karpov + * + * This file is part of the Arduino PT2314 Library + * + * This Library is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * . + */ + +#include "Wire.h" +#include "../WProperty.h" +#include "../WI2C.h" + +#define PT2314_I2C_ADDRESS 0x44 + +#define PT2314_BASS_TONE_CONTROL 0x60 // 0b01100000 +#define PT2314_TREBLE_TONE_CONTROL 0x70 // 0b01110000 + +#define PT2314_AUDIO_BYTE 0x58 +#define PT2314_AUDIO_BYTE_LOUD_ON 0x00 +#define PT2314_AUDIO_BYTE_LOAD_OFF 0x04 + +#define PT2314_SPEAKER_ATTN_L 0xc0 // 0b11000000 +#define PT2314_SPEAKER_ATTN_R 0xe0 // 0b11100000 +#define PT2314_SPEAKER_ATTN_L_MUTE 0xdf +#define PT2314_SPEAKER_ATTN_R_MUTE 0xff + +unsigned char eq_map[] = { + 0b0000, // -7 + 0b0001, // -6 + 0b0010, // -5 + 0b0011, // -4 + 0b0100, // -3 + 0b0101, // -2 + 0b0110, // -1 + 0b0111, // 0 + 0b1110, // +1 + 0b1101, // +2 + 0b1100, // +3 + 0b1011, // +4 + 0b1010, // +5 + 0b1001, // +6 + 0b1000, // +7 +}; + +class PT2314 : public WI2C{ + public: + PT2314(int sda = 21, int scl = 22, TwoWire* i2cPort = &Wire) + : WI2C(PT2314_I2C_ADDRESS, sda, scl, NO_PIN, i2cPort) { + _bass = WProps::createLevelIntProperty("bass", "Bass", -7, 7); + _bass->setInteger(0); + _bass->addListener([this] (WProperty* p) { _updateBass(); }); + _treble = WProps::createLevelIntProperty("treble", "Treble", -7, 7); + _treble->setInteger(0); + _treble->addListener([this] (WProperty* p) { _updateTreble(); }); + + _loudness = WProps::createBooleanProperty("loudness", "Loudness"); + _loudness->setBoolean(false); + _loudness->addListener([this] (WProperty* p) { _updateAudioSwitch(); }); + _gain = WProps::createByteProperty("gain", "Gain"); + _gain->setByte(0); + _gain->addListener([this] (WProperty* p) { _updateAudioSwitch(); }); + + _channel = WProps::createByteProperty("channel", "Channel"); + _channel->setByte(0); + _channel->addListener([this] (WProperty* p) { _updateAudioSwitch(); }); + + _volume = WProps::createLevelIntProperty("volume", "Volume", 0, 100); + _volume->setInteger(100); + _volume->addListener([this] (WProperty* p) { _updateVolume(); }); + _mute = WProps::createBooleanProperty("mute", "Mute"); + _mute->setBoolean(false); + _mute->addListener([this] (WProperty* p) { _updateAttenuation(); _updateVolume(); }); + + _attenuationL = 100; + _attenuationR = 100; + if (isInitialized()) { + _updateAll(); + } + } + + WProperty* mute() { return _mute; } + + WProperty* volume() { return _volume; } + + WProperty* channel() { return _channel; } + + WProperty* loudness() { return _loudness; } + + WProperty* gain() { return _gain; } + + void attenuation(int l, int r) { + _attenuationL = constrain(l, 0, 100); + _attenuationR = constrain(r, 0, 100); + _updateAttenuation(); + } + + WProperty* bass() { return _bass; } + + WProperty* treble() { return _treble; } + + private: + WProperty* _volume; + int _attenuationL; + int _attenuationR; + WProperty* _mute; + WProperty* _loudness; + WProperty* _gain; + WProperty* _channel; + WProperty* _bass; + WProperty* _treble; + + int volume_to_pt2314(int vol) { return 63 - ((vol * 63) / 100); } + + int writeI2CChar(unsigned char c) { + Wire.beginTransmission(PT2314_I2C_ADDRESS); + Wire.write(c); + return Wire.endTransmission(); + } + + bool _updateVolume() { + unsigned int val = volume_to_pt2314(_volume->getInteger()); + return (writeI2CChar(val) == 0) ? true : false; + } + + bool _updateAttenuation() { + unsigned int aL = map(_attenuationL, 0, 100, 0b00011111, 0b00000000); + unsigned int aR = map(_attenuationR, 0, 100, 0b00011111, 0b00000000); + if (_mute->getBoolean()) { + if (writeI2CChar(0b11011111) != 0) { + return false; + } + if (writeI2CChar(0b11111111) != 0) { + return false; + } + } else { + if (writeI2CChar(0b11000000 | aL) != 0) { + return false; + } + if (writeI2CChar(0b11100000 | aR) != 0) { + return false; + } + } + + return true; + } + + bool _updateAudioSwitch() { + /* + AUDIO SWITCH DATA BYTE + MSB LSB Function + 0 1 0 G1 G0 S2 S1 S0 Audio Switch + 0 0 Stereo 1 + 0 1 Stereo 2 + 1 0 Stereo 3 + 1 1 Stereo 4 + 0 Loudness ON + 1 Loudness OFF + 0 0 +11.25dB + 0 1 +7.5dB + 1 0 +3.75dB + 1 1 0dB + */ + + int audioByte = 0b01000000; // audio switch + gain +11.25dB. + // gain byte, 0b00011000 = no gain, 0b00010000 = +3.75dB, 0b00001000 = + // +7.5dB, 0b00000000 = +11.25dB + byte g = ((3 - _gain->getByte()) << 3); + audioByte |= g; + if (_loudness->getBoolean()) { + audioByte |= 0b00000000; + } else { + audioByte |= 0b00000100; + } + audioByte |= _channel->getByte(); + return (writeI2CChar(audioByte) == 0) ? true : false; + } + + bool _updateBass() { + unsigned int val = eq_map[_bass->getInteger()];// eq_to_pt2314(map(_bass->getInteger(), -10, 10, 0, 28)); + return (writeI2CChar(0x60 | val) == 0) ? true : false; + } + + bool _updateTreble() { + unsigned int val = eq_map[_treble->getInteger()];// eq_to_pt2314(map(_treble->getInteger(), -10, 10, 0, 28)); + return (writeI2CChar(0x70 | val) == 0) ? true : false; + } + + bool _updateAll() { + if (_updateVolume() == false) { + return false; + } + + if (_updateAttenuation() == false) { + return false; + } + + if (_updateAudioSwitch() == false) { + return false; + } + + if (_updateBass() == false) { + return false; + } + + return _updateTreble(); + } +}; + +#endif diff --git a/src/hw/W2812.h b/src/hw/W2812.h index 5074a32..2569ebb 100644 --- a/src/hw/W2812.h +++ b/src/hw/W2812.h @@ -19,16 +19,16 @@ class W2812Led : public WOutput { _color = new WColorProperty("color", "Color", 255, 0, 0); // network->getSettings()->add(this->color); _brightness = WProps::createLevelIntProperty("brightness", "Brightness", 10, 255); - _brightness->setInteger(160); + _brightness->asInt(160); // network->getSettings()->add(this->brightness); _brightness->addListener([this](WProperty* property) { - _strip->setBrightness(property->getInteger()); + _strip->setBrightness(property->asInt()); }); _strip = new Adafruit_NeoPixel(numberOfLeds, ledPin, NEO_GRB + NEO_KHZ800); //_strip = new Adafruit_NeoPixel(numberOfLeds, ledPin, NEO_GRBW + NEO_KHZ800); _strip->begin(); // INITIALIZE NeoPixel strip object (REQUIRED) _strip->show(); // Turn OFF all pixels ASAP - _strip->setBrightness(_brightness->getInteger()); // Set BRIGHTNESS to about 1/5 (max = 255) + _strip->setBrightness(_brightness->asInt()); // Set BRIGHTNESS to about 1/5 (max = 255) } void onChanged() { diff --git a/src/hw/WHtu21D.h b/src/hw/WHtu21D.h index 6d0dddd..2e596c1 100644 --- a/src/hw/WHtu21D.h +++ b/src/hw/WHtu21D.h @@ -1,15 +1,12 @@ #ifndef W_HTU21D_H #define W_HTU21D_H -#include "../WI2C.h" +#include "hw/WI2CTemperature.h" #define HTU21D_ADDRESS 0x40 #define I2C_TIMEOUT 500 #define I2C_BETWEEN 500 #define I2C_REQUEST_TO_RESULT 50 -#define ERROR_NONE 0 -#define ERROR_I2C_TIMEOUT 1 -#define ERROR_BAD_CRC 2 #define TRIGGER_TEMP_MEASURE_NOHOLD 0xF3 #define TRIGGER_HUMD_MEASURE_NOHOLD 0xF5 #define MAX_WAIT 100 @@ -24,21 +21,19 @@ enum WHtu21DState { STATE_READ_HUMIDITY_PAUSED }; -class WHtu21D: public WI2C { +class WHtu21D: public WI2CTemperature { public: - WHtu21D(int sda, int scl, int interrupt = NO_PIN, TwoWire* i2cPort = &Wire) - : WI2C(HTU21D_ADDRESS, sda, scl, interrupt, i2cPort) { + WHtu21D(int sda, int scl, TwoWire* i2cPort = &Wire) + : WI2CTemperature(HTU21D_ADDRESS, sda, scl, i2cPort) { _lastMeasure = 0; _measureInterval = 10000; - _humidity = nullptr; _correctionTemperature = -0.5; _correctionHumidity = 0.0; _reset(); - _lastError = ERROR_NONE; } virtual void loop(unsigned long now) { - WI2C::loop(now); + WI2CTemperature::loop(now); if (_state == STATE_IDLE) { if ((_lastMeasure == 0) || (now - _lastMeasure > (unsigned long)(_measureInterval))) { //start measurement @@ -76,7 +71,7 @@ class WHtu21D: public WI2C { } else { _temperatureValue = _temperatureValue / (double) HTU21D_AVERAGE_COUNTS; if (hasProperty()) { - property()->setDouble(_temperatureValue + _correctionTemperature); + property()->asDouble(_temperatureValue + _correctionTemperature); } _counter = 0; _request(now, TRIGGER_HUMD_MEASURE_NOHOLD, STATE_READ_HUMIDITY); @@ -91,7 +86,7 @@ class WHtu21D: public WI2C { } else { _humidityValue = _humidityValue / (double) HTU21D_AVERAGE_COUNTS; if (hasHumidity()) { - humidity()->setDouble(_humidityValue + _correctionHumidity); + humidity()->asDouble(_humidityValue + _correctionHumidity); } _reset(); _lastError = ERROR_NONE; @@ -159,10 +154,8 @@ class WHtu21D: public WI2C { unsigned long _lastMeasure, _lastRequest; int _measureInterval; double _temperatureValue, _humidityValue; - WProperty* _humidity; WHtu21DState _state; byte _counter; - byte _lastError; double _correctionTemperature, _correctionHumidity; byte _checkCRC(uint16_t message_from_sensor, uint8_t check_value_from_sensor) { diff --git a/src/hw/WI2CTemperature.h b/src/hw/WI2CTemperature.h new file mode 100644 index 0000000..ecf40cc --- /dev/null +++ b/src/hw/WI2CTemperature.h @@ -0,0 +1,48 @@ +#ifndef W_I2C_TEMPERATURE_H +#define W_I2C_TEMPERATURE_H + +#include "../WI2C.h" + +#define ERROR_NONE 0 +#define ERROR_I2C_TIMEOUT 1 +#define ERROR_BAD_CRC 2 +#define ERROR_I2C_REQUEST 3 + +class WI2CTemperature: public WI2C { +public: + WI2CTemperature(byte address, int sda, int scl, TwoWire* i2cPort = &Wire) + : WI2C(address, sda, scl, NO_PIN, i2cPort) { + _humidity = nullptr; + _lastError = ERROR_NONE; + } + + virtual void loop(unsigned long now) { + WI2C::loop(now); + } + + + WProperty* humidity() { return _humidity; } + + void setHumidity(WProperty* humidity) { + if (_humidity != humidity) { + _humidity = humidity; + this->loop(millis()); + } + } + + bool hasHumidity() { return (_humidity != nullptr); } + + bool hasError() { return (_lastError != ERROR_NONE); } + + byte lastError() { return _lastError; } + +protected: + WProperty* _humidity; + byte _lastError; + +private: + + +}; + +#endif diff --git a/src/hw/WSht30.h b/src/hw/WSht30.h new file mode 100644 index 0000000..61fd20a --- /dev/null +++ b/src/hw/WSht30.h @@ -0,0 +1,133 @@ + +#ifndef W_SHT30_H +#define W_SHT30_H + +#include "hw/WI2CTemperature.h" +#include "Wire.h" +#include "WProperty.h" + +#define SHT30_ADDRESS 0x44 +#define I2C_REQUEST_TO_RESULT 100 +#define I2C_BETWEEN 800 +#define I2C_TIMEOUT 500 +#define SHT30_AVERAGE_COUNTS 3 + +#define ERROR_NONE 0 +#define ERROR_I2C_TIMEOUT 1 +#define ERROR_BAD_CRC 2 +#define ERROR_I2C_REQUEST 3 + + +enum WSht30ReadState { + STH30_STATE_IDLE, + STH30_STATE_READ, + STH30_STATE_READ_PAUSED +}; + +class WSht30 : public WI2CTemperature { + public: + WSht30(int sda, int scl, TwoWire* i2cPort = &Wire) + : WI2CTemperature(SHT30_ADDRESS, sda, scl, i2cPort) { + _lastMeasure = 0; + _measureInterval = 10000; + _correctionTemperature = -0.5; + _correctionHumidity = 0.0; + _reset(); + } + + virtual void loop(unsigned long now) { + WI2CTemperature::loop(now); + if (_state == STH30_STATE_IDLE) { + if ((_lastMeasure == 0) || (now - _lastMeasure > (unsigned long)(_measureInterval))) { + // start measurement + _lastMeasure = now; + _reset(); + if (_request(now)) { + _state = STH30_STATE_READ; + } else { + _lastError = ERROR_I2C_REQUEST; + } + } + } else if (_state == STH30_STATE_READ) { + if ((now - _lastRequest > I2C_REQUEST_TO_RESULT) && (_i2cPort->requestFrom(address(), 6) == 6)) { + unsigned int data[6]; + for (int i = 0; i < 6; i++) { + data[i] = _i2cPort->read(); + }; + _temperatureValue = _temperatureValue + (((((data[0] * 256.0) + data[1]) * 175) / 65535.0) - 45); + _humidityValue = _humidityValue + ((((data[3] * 256.0) + data[4]) * 100) / 65535.0); + _counter++; + if (_counter < SHT30_AVERAGE_COUNTS) { + _state = STH30_STATE_READ_PAUSED; + } else { + _temperatureValue = _temperatureValue / (double) SHT30_AVERAGE_COUNTS; + if (hasProperty()) { + property()->asDouble(_temperatureValue + _correctionTemperature); + } + _humidityValue = _humidityValue / (double) SHT30_AVERAGE_COUNTS; + if (hasHumidity()) { + humidity()->asDouble(_humidityValue + _correctionHumidity); + } + _lastMeasure = now; + _reset(); //IDLE + _lastError = ERROR_NONE; + } + } else if (now - _lastRequest > I2C_TIMEOUT) { + // Timeout + _reset(); + _lastError = ERROR_I2C_TIMEOUT; + } + } else { + //STH30_STATE_READ_PAUSED + if (now - _lastRequest > I2C_BETWEEN) { + if (_request(now)) { + _state = STH30_STATE_READ; + } else { + _reset(); + _lastError = ERROR_I2C_REQUEST; + } + } + } + } + + WProperty* humidity() { return _humidity; } + + void setHumidity(WProperty* humidity) { + if (_humidity != humidity) { + _humidity = humidity; + this->loop(millis()); + } + } + + bool hasHumidity() { return (_humidity != nullptr); } + + private: + WSht30ReadState _state; + unsigned long _lastMeasure, _lastRequest; + int _measureInterval; + double _temperatureValue, _humidityValue; + double _correctionTemperature, _correctionHumidity; + byte _counter; + + void _reset() { + _state = STH30_STATE_IDLE; + _lastRequest = 0; + _temperatureValue = 0.0; + _humidityValue = 0.0; + _counter = 0; + } + + byte _request(unsigned long now) { + _i2cPort->beginTransmission(_address); + _i2cPort->write(0x2C); + _i2cPort->write(0x06); + if (_i2cPort->endTransmission() == 0) { + _lastRequest = now; + return true; + } else { + return false; + } + } +}; + +#endif