├── .gitignore ├── LICENSE ├── README.md ├── Sensatio_FW_ESP8266.cpp ├── Sensatio_FW_ESP8266.h └── src ├── communication ├── Data.cpp ├── Data.h ├── MQTT.cpp ├── MQTT.h ├── RestServer.cpp ├── RestServer.h ├── WiFiManager.cpp └── WiFiManager.h ├── controller ├── Bridge.cpp ├── Bridge.h ├── OTA.cpp ├── OTA.h ├── StateHelper.cpp ├── StateHelper.h ├── UUID.cpp └── UUID.h ├── input ├── Sensor.cpp ├── Sensor.h ├── SensorCalculation.cpp ├── SensorCalculation.h ├── SensorDigitalSwitch.cpp ├── SensorDigitalSwitch.h ├── analog │ ├── SensorAnalogue.cpp │ └── SensorAnalogue.h ├── i2c │ ├── Ads1x15.cpp │ ├── Ads1x15.h │ ├── SensorBH1750.cpp │ ├── SensorBH1750.h │ ├── SensorBME680.cpp │ ├── SensorBME680.h │ ├── SensorBMx280.cpp │ ├── SensorBMx280.h │ ├── SensorMax44009.cpp │ ├── SensorMax44009.h │ ├── SensorSI1145.cpp │ ├── SensorSI1145.h │ ├── SensorVEML6075.cpp │ ├── SensorVEML6075.h │ └── thirdparty │ │ ├── Adafruit_ADS1015.cpp │ │ ├── Adafruit_ADS1015.h │ │ ├── BH1750.cpp │ │ └── BH1750.h └── onewire │ ├── SensorDHT.cpp │ ├── SensorDHT.h │ ├── SensorDallas.cpp │ └── SensorDallas.h └── output ├── VisualisationHelper.cpp ├── VisualisationHelper.h ├── display ├── Display.cpp ├── Display.h ├── DisplayOLED128.cpp ├── DisplayOLED128.h ├── DisplayST7735.cpp └── DisplayST7735.h └── model ├── DisplayDataModel.cpp ├── DisplayDataModel.h ├── DisplayValueData.cpp ├── DisplayValueData.h └── valuetype.h /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /.vscode 3 | /.DS_Store 4 | /archive 5 | /src/input/.DS_Store 6 | /src/input/i2c/.DS_Store 7 | /sloeber.ino.cpp 8 | /Release/ 9 | /.cproject 10 | /.project 11 | /.settings 12 | /spec.d 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # firmware-esp8266 2 | 3 | The Sensatio ESP8266 firmware is used to connect ESP8266 based hardware with the Sensatio Cloud and the Sensatio apps. 4 | Find out more at https://www.sensatio.io 5 | 6 | # The Sensatio Firmware for ESP8266 currently uses the following Libraries: 7 | 8 | - Arduino IDE ESP8266 Base Library (https://github.com/esp8266/Arduino v2.7.4) 9 | - ArduinoJson (https://github.com/bblanchon/ArduinoJson v5.13.5) 10 | - ESP8266TrueRandom (https://github.com/marvinroger/ESP8266TrueRandom from 17.7.18) 11 | - Thingpulse SSD1306 (https://github.com/ThingPulse/esp8266-oled-ssd1306 v4.0.0) 12 | - Soligen2010 fork of Adafruit_ADS1x15 (https://github.com/soligen2010/Adafruit_ADS1X15) v1.2.1 13 | - Adafruit Unified Sensor Library (https://github.com/adafruit/Adafruit_Sensor v1.1.4) 14 | - Adafruit DHT Sensor Library (https://github.com/adafruit/DHT-sensor-library v1.4.1) 15 | - Adafruit BusIO (https://github.com/adafruit/Adafruit_BusIO v1.7.0) 16 | - Adafruit VEML6075 (https://github.com/adafruit/Adafruit_VEML6075 v2.1.0) 17 | - OneWire (https://www.pjrc.com/teensy/td_libs_OneWire.html v2.3.5) 18 | - DallasTemperature (https://github.com/milesburton/Arduino-Temperature-Control-Library v3.9.0) 19 | - BME280 (https://github.com/finitespace/BME280 v2.3.0) 20 | - Adafruit BME680 (https://github.com/adafruit/Adafruit_BME680 v1.1.1) 21 | - Max44009 (https://github.com/dantudose/MAX44009 v1.2.3) 22 | - BH1750 (https://github.com/claws/BH1750 v1.2.0) 23 | - MQTT Client Library (https://github.com/knolleary/pubsubclient v2.8.0) 24 | - SI1145 (https://github.com/wollewald/SI1145_WE v1.1.4) 25 | 26 | Windows, Linux and Mac Users: 27 | Use pyflasher from https://github.com/marcelstoer/nodemcu-pyflasher/releases for flashing the firmware. 28 | 29 | Find more informations here: 30 | https://www.sensatio.io 31 | 32 | And here in German: 33 | https://www.sensatio.io/de 34 | -------------------------------------------------------------------------------- /Sensatio_FW_ESP8266.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Sensatio_FW_ESP8266.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensatio ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensatio Cloud and the Sensatio apps. 8 | 9 | ----> https://www.sensatio.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v45 - Fixed Pressure Measurement for BME280 Sensors 15 | v44 - More Memory Improvements 16 | v43 - Fixed data transmit issues in configurations with many sensors 17 | v42 - Fixed low memory issues in configurations with many sensors and a ST7735 Bug 18 | v41 - Changed IDE, Sensatio, Renamed Display Class to support more types 19 | v40 - New Display Structure to enable Display Rotation, different Styles etc. 20 | v39 - ReAdded Support for VEML6075 and SI1145 UVI Sensors, added auto-reinit if sensor fails 21 | v38 - Changed automatic Update to only if required Update, removed VEML6075 and SI1145 UV Sensors 22 | v36 - Greatly improved reliability of connectivity 23 | v35 - Added Support for VEML6075 and SI1145 UVI Sensors 24 | v34 - Added Generic Analog Sensor Support 25 | v33 - Added Digital Sensor Switch Support, Improved MQTT Setup Routine 26 | v32 - Added MQTT Support! 27 | v31 - Fixed an issue with DHT11 Sensors 28 | v30 - Added support for SSD1306 I2C Displays 29 | v29 - First Public Release 30 | */ 31 | /**************************************************************************/ 32 | 33 | #include "Sensatio_FW_ESP8266.h" 34 | 35 | VisualisationHelper* vHelper; 36 | Display* display = NULL; 37 | 38 | int currentVersion = 45; 39 | boolean printMemory = false; 40 | 41 | //String board = "Generic"; 42 | //char firmwareType[] = "ESP8266"; 43 | //char firmwareType[] = "ESP8266-1M"; 44 | 45 | String board = "NodeMCU"; 46 | char firmwareType[] = "ESP8266-NodeMCU"; 47 | 48 | // String board = "ESP12s"; 49 | // char firmwareType[] = "ESP8266-ESP12s"; 50 | 51 | // String board = "ESP07"; 52 | // char firmwareType[] = "ESP8266-ESP07"; 53 | 54 | // String board = "D1Mini"; 55 | // char firmwareType[] = "ESP8266-D1Mini"; 56 | 57 | String name = "Bridge"; 58 | String ucType = "ESP8266"; 59 | 60 | String variant = "SensatioV"+String(currentVersion)+board; 61 | String apiVersion = "v1"; 62 | 63 | int powerMode; 64 | long powerOnDelay = 0; 65 | String powerSavePort; 66 | boolean invPowerSavePort = false; 67 | 68 | bool isResetting = false; 69 | 70 | unsigned long previousDelayMillis = 0; 71 | unsigned long previousTickerMillis = 0; 72 | unsigned long currentMillis; 73 | State state = Boot; 74 | 75 | int displayMode; 76 | boolean displayEnabled; 77 | int displayType; 78 | int displayHeight; 79 | int displayWidth; 80 | int displayRotation; 81 | bool firstSensorData; 82 | 83 | extern struct rst_info resetInfo; 84 | 85 | extern uint8_t i2cSDAPort; 86 | extern uint8_t i2cSCLPort; 87 | extern MQTT* mqtt; 88 | 89 | extern String urlString; 90 | extern String requestDataString; 91 | extern String payload; 92 | 93 | #define tickerInterval 250 94 | #define delayInterval 10000 95 | 96 | 97 | void setup() 98 | { 99 | Serial.begin(9600); 100 | Serial.println("---------------------------"); 101 | Serial.println(variant); 102 | Serial.println("---------------------------"); 103 | Serial.println("Startup: "); 104 | Serial.println(getUUID()); // @suppress("Invalid arguments") 105 | 106 | urlString.reserve(300); 107 | requestDataString.reserve(200); 108 | payload.reserve(1000); 109 | 110 | restoreBridgeConfig(); 111 | 112 | vHelper = new VisualisationHelper(); 113 | 114 | doPowerSavingInit(true); 115 | 116 | Serial.println("Display Type:"+String(displayType)); 117 | Serial.println("Display Enabled:"+String(displayEnabled)); 118 | Serial.println("Display Rotation:"+String(displayRotation)); 119 | Serial.println("Display Mode:"+String(displayMode)); 120 | 121 | Serial.println("Power Mode:"+String(powerMode)); 122 | Serial.println("Power On Delay:"+String(powerOnDelay)); 123 | Serial.println("Power Save Port:"+String(powerSavePort)); 124 | Serial.println("Power Save Port Inv:"+String(invPowerSavePort)); 125 | 126 | 127 | if(displayType!=0) 128 | { 129 | boolean rotateDisplay = (displayRotation == 180); 130 | 131 | switch(displayType) 132 | { 133 | case 3: 134 | display = new DisplayST7735(rotateDisplay, displayType); 135 | break; 136 | default: // Fallback to OLED init 137 | display = new DisplayOLED128(displayWidth, displayHeight, rotateDisplay, displayType,"",i2cSDAPort,i2cSCLPort); 138 | break; 139 | } 140 | 141 | if(!displayEnabled) 142 | display->clear(true); 143 | } 144 | 145 | if(display!=NULL) 146 | display->drawProductLogo(); 147 | 148 | state = Connect_WiFi; 149 | 150 | initSensate(); 151 | } 152 | 153 | void loop() 154 | { 155 | if(!isResetting) 156 | { 157 | //First: Do whatever should be done in every loop! 158 | runLoop(); 159 | 160 | //Then: Do short delayed actions (once every #tickerInterval miliseconds) 161 | currentMillis = millis(); 162 | if(currentMillis - previousTickerMillis >= tickerInterval) 163 | { 164 | previousTickerMillis = currentMillis; 165 | runTick(); 166 | } 167 | 168 | //Then: Do long delayed actions (once every #delayInterval miliseconds) 169 | currentMillis = millis(); 170 | if(currentMillis - previousDelayMillis >= delayInterval) 171 | { 172 | previousDelayMillis = currentMillis; 173 | runDelayed(); 174 | } 175 | } 176 | } 177 | 178 | void runLoop() { 179 | switch(state) 180 | { 181 | case Setup: 182 | loopDNS(); 183 | checkWiFiStatus(); 184 | case Connected_WiFi: 185 | case Init_Configuration: 186 | case Operating: 187 | loopRestserver(); 188 | if(mqtt!=NULL) 189 | mqtt->loop(); 190 | break; 191 | default: 192 | break; 193 | } 194 | } 195 | 196 | void runTick() { 197 | // Serial.print("-T-"); 198 | switch(state) 199 | { 200 | case Operating: 201 | loopDisplay(currentMillis); 202 | loopSensor(currentMillis); 203 | break; 204 | default: 205 | break; 206 | } 207 | 208 | if(printMemory) 209 | { 210 | Serial.print("HEAP: "); 211 | Serial.println(ESP.getFreeHeap()); 212 | } 213 | 214 | if(ESP.getFreeHeap()<1000) 215 | { 216 | Serial.println("RUNNING OUT OF HEAP - RESTART"); 217 | restart(); 218 | } 219 | } 220 | 221 | void runDelayed() { 222 | // Serial.print("----D----"); 223 | if(state!=Operating) 224 | initSensate(); 225 | else 226 | checkStatus(); 227 | } 228 | 229 | void initSensate() { 230 | 231 | if(state==Connect_WiFi) 232 | { 233 | Serial.println("STATE: Connect_WiFi"); 234 | connectToNetwork(); 235 | } 236 | if(state==Check_Firmware) 237 | { 238 | if(resetInfo.reason != REASON_DEEP_SLEEP_AWAKE) 239 | { 240 | Serial.println("STATE: Check_Firmware"); 241 | tryFirmwareUpdate(""); 242 | } 243 | else 244 | { 245 | Serial.println("Skip Check_Firmware (Wake from Sleep)"); 246 | state=Connected_WiFi; 247 | } 248 | } 249 | if(state==Connected_WiFi) 250 | { 251 | Serial.println("STATE: Connected_WiFi"); 252 | startRestServer(); 253 | } 254 | if(state==Init_Setup) 255 | { 256 | Serial.println("STATE: Init_Setup"); 257 | startRestServer(); 258 | startDNS(); 259 | } 260 | if(state==Register) 261 | { 262 | if(resetInfo.reason != REASON_DEEP_SLEEP_AWAKE) 263 | { 264 | Serial.println("STATE: Register_Bridge"); 265 | initSSL(); 266 | registerBridge(); 267 | } 268 | else 269 | { 270 | Serial.println("Skip Register_Bridge (Wake from Sleep)"); 271 | initSSL(); 272 | state=Init_Configuration; 273 | } 274 | } 275 | if(state==Init_Configuration) 276 | { 277 | Serial.println("STATE: Get_Configuration"); 278 | getBridgeConfig(); 279 | } 280 | 281 | } 282 | -------------------------------------------------------------------------------- /Sensatio_FW_ESP8266.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Sensatio_FW_ESP8266.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensatio ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensatio Cloud and the Sensatio apps. 8 | 9 | ----> https://www.sensatio.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v41 - Changed IDE, Sensatio 15 | */ 16 | /**************************************************************************/ 17 | 18 | // Only modify this file to include 19 | // - function definitions (prototypes) 20 | // - include files 21 | // - extern variable definitions 22 | // In the appropriate section 23 | 24 | #ifndef _Sensatio_FW_ESP8266_H_ 25 | #define _Sensatio_FW_ESP8266_H_ 26 | #include "Arduino.h" 27 | 28 | //add your includes for the project Sensatio_FW_ESP8266 here 29 | #include "src/controller/Bridge.h" 30 | #include "src/output/display/Display.h" 31 | #include "src/communication/WiFiManager.h" 32 | #include "src/controller/OTA.h" 33 | #include "src/communication/RestServer.h" 34 | #include "src/output/VisualisationHelper.h" 35 | #include 36 | //end of add your includes here 37 | 38 | 39 | //add your function definitions for the project Sensatio_FW_ESP8266 here 40 | 41 | void loop(); 42 | void runTick(); 43 | void runDelayed(); 44 | void runLoop(); 45 | void initSensate(); 46 | void setup(); 47 | 48 | 49 | //Do not add code below this line 50 | #endif /* _Sensatio_FW_ESP8266_H_ */ 51 | -------------------------------------------------------------------------------- /src/communication/Data.cpp: -------------------------------------------------------------------------------- 1 | 2 | /**************************************************************************/ 3 | /*! 4 | @file Data.cpp 5 | @author M. Fegerl (Sensate Digital Solutions GmbH) 6 | @license GPL (see LICENSE file) 7 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 8 | with the Sensate Cloud and the Sensate apps. 9 | 10 | ----> https://www.sensate.io 11 | 12 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 13 | 14 | @section HISTORY 15 | v33 - Added Digital Sensor Switch Support 16 | v32 - Added MQTT Support! 17 | v29 - First Public Release 18 | */ 19 | /**************************************************************************/ 20 | 21 | #include "Data.h" 22 | 23 | Data::Data(Sensor *sensor, float value, String unit) { 24 | _type = 1; 25 | _valueFloat = value; 26 | _sensor = sensor; 27 | _unit = unit; 28 | } 29 | 30 | Data::Data(Sensor *sensor, int value, String unit) { 31 | _type = 2; 32 | _valueInt = value; 33 | _sensor = sensor; 34 | _unit = unit; 35 | } 36 | 37 | Data::Data(Sensor *sensor, boolean value, String unit) { 38 | _type = 3; 39 | _valueBoolean = value; 40 | _sensor = sensor; 41 | _unit = unit; 42 | } 43 | 44 | String Data::getRequestString() { 45 | 46 | String returnString = String(_sensor->getId()) +","; 47 | 48 | if(_type==1) 49 | returnString = returnString + String(_valueFloat); 50 | else if(_type==2) 51 | returnString = returnString + String(_valueInt); 52 | else if(_type==3) 53 | { 54 | if(_valueBoolean) 55 | returnString = returnString + "true"; 56 | else 57 | returnString = returnString + "false"; 58 | 59 | } 60 | 61 | return returnString+","+_unit; 62 | 63 | } 64 | 65 | String Data::getValueString() { 66 | 67 | if(_type==1) 68 | return String(_valueFloat); 69 | else if(_type==2) 70 | return String(_valueInt); 71 | else if(_type==3) 72 | return String(_valueBoolean); 73 | 74 | return ""; 75 | } 76 | 77 | Sensor* Data::getSensor() { 78 | return _sensor; 79 | } -------------------------------------------------------------------------------- /src/communication/Data.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Data.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v32 - Added MQTT Support! 15 | v29 - First Public Release 16 | */ 17 | /**************************************************************************/ 18 | 19 | #include 20 | 21 | #ifndef _Data_h_ 22 | #define _Data_h_ 23 | 24 | #include "../input/Sensor.h" 25 | 26 | class Sensor; 27 | 28 | class Data { 29 | private: 30 | Sensor *_sensor; 31 | float _valueFloat; 32 | int _valueInt; 33 | boolean _valueBoolean; 34 | String _unit; 35 | int _type; 36 | public: 37 | Data(Sensor*, float, String); 38 | Data(Sensor*, int, String); 39 | Data(Sensor*, boolean, String); 40 | String getValueString(void); 41 | String getRequestString(void); 42 | Sensor* getSensor(void); 43 | }; 44 | 45 | #endif -------------------------------------------------------------------------------- /src/communication/MQTT.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file MQTT.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v34 - Added Generic Analog Sensor Support 15 | v33 - Added Digital Sensor Switch Support 16 | v32 - Added MQTT Support! 17 | */ 18 | /**************************************************************************/ 19 | 20 | #include "MQTT.h" 21 | 22 | extern unsigned long currentMillis; 23 | boolean enableMQTT; 24 | MQTT *mqtt; 25 | 26 | MQTT::MQTT (char* brokerUrl, long brokerPort, String username, String password) 27 | { 28 | _username = username; 29 | _password = password; 30 | _brokerPort = brokerPort; 31 | _brokerUrl = String(brokerUrl); 32 | 33 | espClient = WiFiClient(); 34 | pubSubClient = new PubSubClient(espClient); 35 | 36 | clientId = "Sensate-"+getUUID().substring(0,7); 37 | 38 | pubSubClient->setServer(_brokerUrl.c_str(), _brokerPort); 39 | 40 | lastMillis = 0; 41 | } 42 | 43 | MQTT::MQTT (char* brokerUrl, long brokerPort) 44 | { 45 | _username = "NULL"; 46 | _password = "NULL"; 47 | 48 | clientId = "Sensate-"+getUUID().substring(0,7); 49 | 50 | pubSubClient = new PubSubClient(espClient); 51 | pubSubClient->setServer(brokerUrl, brokerPort); 52 | 53 | } 54 | 55 | bool MQTT::connect() 56 | { 57 | Serial.println("Connecting to broker with clientId: "+clientId); 58 | 59 | if(_username=="NULL" && _password=="NULL") 60 | { 61 | Serial.println("Connecting to MQTT broker..."); 62 | 63 | if (pubSubClient->connect(clientId.c_str())) 64 | { 65 | Serial.println("Connected to MQTT broker"); 66 | return true; 67 | } 68 | else 69 | { 70 | Serial.print("Connection to MQTT Broker failed with state "); 71 | Serial.print(pubSubClient->state()); 72 | return false; 73 | } 74 | } 75 | else 76 | { 77 | Serial.println("Connecting to MQTT broker with credentials..."); 78 | 79 | if (pubSubClient->connect(clientId.c_str(), _username.c_str(), _password.c_str())) 80 | { 81 | Serial.println("Connected to MQTT broker"); 82 | return true; 83 | } 84 | else 85 | { 86 | Serial.print("Connection to MQTT Broker failed with state "); 87 | Serial.print(pubSubClient->state()); 88 | return false; 89 | } 90 | } 91 | } 92 | 93 | void MQTT::publishForAutoDiscovery(Sensor* sensor) 94 | { 95 | String pTopic; 96 | 97 | if(sensor->isBinary()) 98 | { 99 | pTopic = "homeassistant/binary_sensor/"+clientId+"/"+String(sensor->getId())+"/config"; 100 | } 101 | else 102 | pTopic = "homeassistant/sensor/"+clientId+"/"+String(sensor->getId())+"/config"; 103 | 104 | String category = sensor->getCategory(); 105 | String pPayload; 106 | 107 | if(category==NULL) 108 | category = "Unnamed"; 109 | 110 | if(sensor->getMqttClass()=="plevel" || sensor->getMqttClass()=="resistance" || sensor->getMqttClass()=="altitude" || sensor->getMqttClass()=="flux" || sensor->getMqttClass()=="" || sensor->getMqttClass()=="raw" || sensor->getMqttClass()=="voltage") 111 | { 112 | pPayload = "{\"name\": \""+sensor->getName()+"\", \"state_topic\": \"Sensate/"+category+"/"+sensor->getName()+"/value\""; 113 | if(sensor->isBinary()) 114 | pPayload = pPayload + ", \"payload_on\": \"1\", \"payload_off\": \"0\"}"; 115 | else 116 | { 117 | pPayload = pPayload + ", \"unit_of_measurement\": \""+sensor->getMqttUnit()+"\"}"; 118 | } 119 | } 120 | else 121 | pPayload = "{\"name\": \""+sensor->getName()+"\", \"device_class\": \""+sensor->getMqttClass()+"\", \"state_topic\": \"Sensate/"+category+"/"+sensor->getName()+"/value\", \"unit_of_measurement\": \""+sensor->getMqttUnit()+"\"}"; 122 | 123 | pubSubClient->publish(pTopic.c_str(), pPayload.c_str()); 124 | } 125 | 126 | void MQTT::loop() 127 | { 128 | pubSubClient->loop(); 129 | } 130 | 131 | void MQTT::publishSensorData(Data* data[], int dataCount) 132 | { 133 | boolean republish = false; 134 | 135 | if (!pubSubClient->connected()) { 136 | Serial.println("Trying reconnecting to MQTT broker..."); 137 | republish=connect(); 138 | } 139 | 140 | if((lastMillis == 0) || (currentMillis>lastMillis+300000)) 141 | { 142 | Serial.println("Republish MQTT Sensors (once every 5min)"); 143 | republish=true; 144 | lastMillis = currentMillis; 145 | } 146 | 147 | for (int i = 0; i < dataCount; i++) 148 | { 149 | if(republish) 150 | { 151 | publishForAutoDiscovery(data[i]->getSensor()); 152 | delay(250); 153 | } 154 | 155 | String cat = data[i]->getSensor()->getCategory(); 156 | if(cat.equals("")) 157 | cat="Unnamed"; 158 | String name = data[i]->getSensor()->getName(); 159 | String vTopic = "Sensate/"+cat+"/"+name+"/value"; 160 | pubSubClient->publish(vTopic.c_str(), data[i]->getValueString().c_str()); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/communication/MQTT.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file MQTT.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v32 - Added MQTT Support! 15 | */ 16 | /**************************************************************************/ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #ifndef _MQTT_h_ 23 | #define _MQTT_h_ 24 | 25 | #include "../controller/UUID.h" 26 | #include "Data.h" 27 | 28 | class MQTT { 29 | private: 30 | unsigned long lastMillis; 31 | String _brokerUrl; 32 | long _brokerPort; 33 | String _username; 34 | String _password; 35 | WiFiClient espClient; 36 | PubSubClient* pubSubClient; 37 | String clientId; 38 | 39 | public: 40 | MQTT (char*, long); 41 | MQTT (char*, long, String, String); 42 | bool connect(void); 43 | void loop(void); 44 | void publishSensorData(Data* data[], int); 45 | void publishForAutoDiscovery(Sensor*); 46 | }; 47 | 48 | #endif -------------------------------------------------------------------------------- /src/communication/RestServer.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file RestServer.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v32 - Added MQTT Support! 15 | v29 - First Public Release 16 | */ 17 | /**************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #ifndef _RestServer_h_ 24 | #define _RestServer_h_ 25 | 26 | #include "../controller/StateHelper.h" 27 | #include "../controller/UUID.h" 28 | #include "../output/display/DisplayOLED128.h" 29 | #include "../communication/WiFiManager.h" 30 | #include "MQTT.h" 31 | 32 | void startRestServer(); 33 | void loopRestserver(); 34 | void configRestServerRouting(); 35 | void androidCaptiveResponse(); 36 | void captiveResponse(); 37 | void tryIdentify(); 38 | void restGetUuid(); 39 | void handleNotFound(); 40 | bool captivePortal(); 41 | void handleRoot(); 42 | void returnNetworkList(); 43 | void presentWiFiSetupScreen(); 44 | void tryRestart(); 45 | void restUpdateName(); 46 | void handleAppleCaptivePortal(); 47 | void initMqtt(); 48 | 49 | String toStringIp(IPAddress ip); 50 | bool isIp(String str); 51 | 52 | #endif -------------------------------------------------------------------------------- /src/communication/WiFiManager.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file WiFiManager.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensatio ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensatio Cloud and the Sensatio apps. 8 | 9 | ----> https://www.sensatio.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v41 - Renamed Display Class to support more types 15 | v29 - First Public Release 16 | */ 17 | /**************************************************************************/ 18 | 19 | #include "WiFiManager.h" 20 | 21 | extern State state; 22 | extern Display* display; 23 | extern int powerMode; 24 | extern int i2cSDAPort; 25 | extern int i2cSCLPort; 26 | 27 | extern ESP8266WebServer http_rest_server; 28 | 29 | IPAddress apIP(192, 168, 4, 1); 30 | IPAddress netMsk(255, 255, 255, 0); 31 | 32 | const char *myHostname = "sensateBridge"; 33 | 34 | DNSServer dnsServer; 35 | const byte DNS_PORT = 53; 36 | 37 | StaticJsonBuffer<10000> jsonBuffer; 38 | 39 | void connectToNetwork() 40 | { 41 | if(isWiFiConfigured()) 42 | { 43 | connectToAP(); 44 | } 45 | else 46 | { 47 | state = Init_AP; 48 | startUpLocalAP(); 49 | } 50 | 51 | } 52 | 53 | void connectToAP() { 54 | 55 | Serial.println("Connecting to AP"); 56 | 57 | EEPROM.begin(121); 58 | 59 | char ssidChars[33]; 60 | char passwordChars[64]; 61 | 62 | EEPROM.get(24, ssidChars); 63 | EEPROM.get(57, passwordChars); 64 | 65 | Serial.println("SSID: " + String(ssidChars)); 66 | Serial.println("Password: ************"); 67 | 68 | EEPROM.end(); 69 | 70 | if(display!=NULL) 71 | { 72 | display->clear(true); 73 | display->drawProductLogo(); 74 | display->drawString(0, 5, "Connecting to..."); 75 | display->drawString(0, 21, String(ssidChars)); 76 | } 77 | 78 | WiFi.begin(ssidChars, passwordChars); 79 | 80 | Serial.println("Connecting to WiFi"); 81 | int x = 0; 82 | 83 | int connRes = WiFi.waitForConnectResult(); 84 | Serial.print("connRes: "); 85 | Serial.println(connRes); 86 | 87 | if(connRes==4) 88 | { 89 | Serial.println("Wait a little longer for WiFi to catch up.."); 90 | delay(1000); 91 | yield(); 92 | delay(1000); 93 | yield(); 94 | delay(1000); 95 | yield(); 96 | delay(1000); 97 | yield(); 98 | delay(1000); 99 | yield(); 100 | } 101 | 102 | if (WiFi.status() != WL_CONNECTED) 103 | { 104 | if(powerMode==2) 105 | { 106 | Serial.println("No WiFi connection possible, going back to Deep Sleep for 5 minutes."); 107 | trySleep(300000000); 108 | } 109 | else 110 | { 111 | Serial.println("Starting up Setup AP"); 112 | state = Init_AP; 113 | startUpLocalAP(); 114 | } 115 | } 116 | else 117 | { 118 | if(display!=NULL) 119 | { 120 | display->clear(true); 121 | display->drawProductLogo(); 122 | display->drawString(0, 5, "Joined:"); 123 | display->drawString(0, 21, String(ssidChars)); 124 | } 125 | 126 | Serial.print("Connected, IP address: "); 127 | Serial.println(WiFi.localIP()); 128 | state = Check_Firmware; 129 | } 130 | 131 | } 132 | 133 | void checkWiFiStatus() { 134 | 135 | if (isWiFiConfigured() && WiFi.status() == WL_CONNECTED) 136 | { 137 | if(display!=NULL) 138 | { 139 | EEPROM.begin(121); 140 | char ssidChars[33]; 141 | EEPROM.get(24, ssidChars); 142 | EEPROM.end(); 143 | 144 | display->clear(true); 145 | display->drawProductLogo(); 146 | display->drawString(0, 5, "Joined:"); 147 | display->drawString(0, 21, String(ssidChars)); 148 | } 149 | 150 | Serial.println("softAPdisconnect()"); 151 | WiFi.softAPdisconnect (true); 152 | 153 | Serial.println("Connected, IP address: "); 154 | Serial.println(WiFi.localIP()); 155 | state = Check_Firmware; 156 | } 157 | } 158 | 159 | bool startUpLocalAP() { 160 | 161 | Serial.println("Starting SoftAP 'Sensate-Setup'"); 162 | WiFi.softAPConfig(apIP, apIP, netMsk); 163 | WiFi.softAP("Sensate-Setup","Setup-Sensate"); 164 | int x = 0; 165 | while (WiFi.softAPIP().toString() == "0.0.0.0") 166 | { 167 | delay(500); 168 | Serial.print("."); 169 | } 170 | Serial.println("Started, SoftAP IP address: "); 171 | Serial.println(WiFi.softAPIP()); 172 | 173 | if(display!=NULL) 174 | { 175 | display->clear(true); 176 | display->drawProductLogo(); 177 | display->drawString(0, 5, "Please use App to"); 178 | display->drawString(0, 21, "setup WiFi Network"); 179 | } 180 | state = Init_Setup; 181 | return true; 182 | } 183 | 184 | void setupBridgeConfig() { 185 | 186 | Serial.println("REST POST /setupbridge"); 187 | 188 | JsonObject& bridgeSettings = jsonBuffer.parseObject(http_rest_server.arg("plain")); 189 | 190 | String ssid = bridgeSettings["ssid"]; 191 | String wifipassword = bridgeSettings["password"]; 192 | String url = bridgeSettings["url"]; 193 | String name = bridgeSettings["name"]; 194 | String secPassword = bridgeSettings["secPassword"]; 195 | 196 | if(display!=NULL) 197 | { 198 | display->clear(false); 199 | display->drawProductLogo(); 200 | display->drawString(0, 5, "Connecting to..."); 201 | display->drawString(0, 21, "'"+ssid+"'"); 202 | } 203 | 204 | jsonBuffer.clear(); 205 | 206 | if (ssid == "") 207 | { 208 | Serial.println("SSID Argument not found"); 209 | http_rest_server.send(400); 210 | http_rest_server.client().stop(); 211 | } 212 | else if (wifipassword == "") 213 | { 214 | Serial.println("Password Argument not found"); 215 | http_rest_server.send(400); 216 | http_rest_server.client().stop(); 217 | } 218 | else 219 | { 220 | http_rest_server.send(200); 221 | http_rest_server.client().stop(); 222 | yield(); 223 | 224 | char ssidChars[33]; 225 | ssid.toCharArray(ssidChars, 33); 226 | char passwordChars[64]; 227 | wifipassword.toCharArray(passwordChars, 64); 228 | char urlChars[100]; 229 | url.toCharArray(urlChars, 100); 230 | 231 | EEPROM.begin(289); 232 | EEPROM.write(20, 11); 233 | EEPROM.write(21, 21); 234 | EEPROM.write(22, 31); 235 | EEPROM.write(23, 41); 236 | EEPROM.put(24, ssidChars); 237 | EEPROM.put(57, passwordChars); 238 | EEPROM.put(121, urlChars); 239 | 240 | if(name!="" || secPassword!="") 241 | { 242 | EEPROM.write(221, 221); 243 | EEPROM.write(222, 222); 244 | 245 | char nameChars[25]; 246 | name.toCharArray(nameChars, 25); 247 | EEPROM.put(223, nameChars); 248 | 249 | if(secPassword!="") 250 | { 251 | char secPassChars[41]; 252 | String shaSecPwd = sha1(secPassword); 253 | shaSecPwd.toCharArray(secPassChars, 41); 254 | EEPROM.put(248, secPassChars); 255 | } 256 | else 257 | { 258 | EEPROM.put(248, '\0'); 259 | } 260 | } 261 | 262 | EEPROM.end(); 263 | 264 | yield(); 265 | 266 | restart(); 267 | } 268 | 269 | } 270 | 271 | void setupBridgeConfigManual() { 272 | 273 | Serial.println("REST POST /manualsetup"); 274 | 275 | String ssid = http_rest_server.arg("ssid"); 276 | String wifipassword = http_rest_server.arg("password"); 277 | String url = http_rest_server.arg("url"); 278 | String name = http_rest_server.arg("identifier"); 279 | String secPassword = http_rest_server.arg(""); 280 | 281 | if(display!=NULL) 282 | { 283 | display->clear(false); 284 | display->drawProductLogo(); 285 | display->drawString(0, 5, "Connecting to..."); 286 | display->drawString(0, 21, "'"+ssid+"'"); 287 | } 288 | 289 | if (ssid == "") 290 | { 291 | Serial.println("SSID Argument not found"); 292 | http_rest_server.send(400); 293 | http_rest_server.client().stop(); 294 | } 295 | else if (wifipassword == "") 296 | { 297 | Serial.println("Password Argument not found"); 298 | http_rest_server.send(400); 299 | http_rest_server.client().stop(); 300 | } 301 | else 302 | { 303 | String wifiResponse = "

Setup Complete - Bridge is restarting! Continue in App.

"; 304 | http_rest_server.send(200, "text/html", wifiResponse); 305 | http_rest_server.client().stop(); 306 | yield(); 307 | 308 | char ssidChars[33]; 309 | ssid.toCharArray(ssidChars, 33); 310 | char passwordChars[64]; 311 | wifipassword.toCharArray(passwordChars, 64); 312 | char urlChars[100]; 313 | url.toCharArray(urlChars, 100); 314 | 315 | EEPROM.begin(289); 316 | EEPROM.write(20, 11); 317 | EEPROM.write(21, 21); 318 | EEPROM.write(22, 31); 319 | EEPROM.write(23, 41); 320 | EEPROM.put(24, ssidChars); 321 | EEPROM.put(57, passwordChars); 322 | EEPROM.put(121, urlChars); 323 | 324 | if(name!="" || secPassword!="") 325 | { 326 | EEPROM.write(221, 221); 327 | EEPROM.write(222, 222); 328 | 329 | char nameChars[25]; 330 | name.toCharArray(nameChars, 25); 331 | EEPROM.put(223, nameChars); 332 | 333 | if(secPassword!="") 334 | { 335 | char secPassChars[41]; 336 | String shaSecPwd = sha1(secPassword); 337 | shaSecPwd.toCharArray(secPassChars, 41); 338 | EEPROM.put(248, secPassChars); 339 | } 340 | else 341 | { 342 | EEPROM.put(248, '\0'); 343 | } 344 | } 345 | 346 | EEPROM.end(); 347 | 348 | yield(); 349 | 350 | restart(); 351 | } 352 | 353 | } 354 | 355 | void resetBridgeConfig() { 356 | 357 | Serial.println("REST GET /resetWiFi"); 358 | 359 | EEPROM.begin(296); 360 | EEPROM.write(20, 0); 361 | EEPROM.write(21, 0); 362 | EEPROM.write(22, 0); 363 | EEPROM.write(23, 0); 364 | EEPROM.write(221, 0); 365 | EEPROM.write(222, 0); 366 | 367 | char nameChars[25] = ""; 368 | EEPROM.put(223, nameChars); 369 | 370 | char pwdChars[41] = ""; 371 | EEPROM.put(248, pwdChars); 372 | 373 | EEPROM.write(290, 0); 374 | EEPROM.write(291, 0); 375 | EEPROM.write(292, 0); 376 | EEPROM.write(293, 0); 377 | EEPROM.write(294, 0); 378 | EEPROM.write(295, 0); 379 | 380 | EEPROM.end(); 381 | 382 | http_rest_server.send(200); 383 | http_rest_server.client().stop(); 384 | yield(); 385 | 386 | restart(); 387 | 388 | } 389 | 390 | void startDNS() { 391 | dnsServer.setErrorReplyCode(DNSReplyCode::NoError); 392 | dnsServer.start(DNS_PORT, "*", apIP); 393 | 394 | if (!MDNS.begin(myHostname)) { 395 | Serial.println("Error setting up MDNS responder!"); 396 | } else { 397 | Serial.println("mDNS responder started"); 398 | // Add service to MDNS-SD 399 | MDNS.addService("http", "tcp", 80); 400 | } 401 | 402 | state = Setup; 403 | } 404 | 405 | void shutDownWiFi() { 406 | Serial.println("shutDownWiFi()"); 407 | 408 | yield(); 409 | delay(1000); 410 | 411 | if(state==Setup) 412 | dnsServer.stop(); 413 | 414 | yield(); 415 | delay(1000); 416 | 417 | WiFi.forceSleepBegin(); 418 | } 419 | 420 | void loopDNS() { 421 | 422 | dnsServer.processNextRequest(); 423 | 424 | if(WiFi.status()==WL_CONNECTED) { 425 | MDNS.update(); 426 | } 427 | 428 | } 429 | -------------------------------------------------------------------------------- /src/communication/WiFiManager.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file WiFiManager.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v29 - First Public Release 15 | */ 16 | /**************************************************************************/ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "Hash.h" 26 | 27 | #ifndef _WiFiManager_h_ 28 | #define _WiFiManager_h_ 29 | 30 | #include "../output/display/Display.h" 31 | #include "../controller/StateHelper.h" 32 | #include "../controller/Bridge.h" 33 | 34 | void connectToNetwork(); 35 | void connectToAP(); 36 | bool startUpLocalAP(); 37 | void setupBridgeConfig(); 38 | void resetBridgeConfig(); 39 | void setupBridgeConfigManual(); 40 | void shutDownWiFi(); 41 | void startDNS(); 42 | void loopDNS(); 43 | void checkWiFiStatus(); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/controller/Bridge.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Bridge.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v43 - Fixed data transmit issues in configurations with many sensors 15 | v42 - Fixed low memory issues in configurations with many sensors and a ST7735 Bug 16 | v40 - New Display Structure to enable Display Rotation, different Styles etc. 17 | v36 - Greatly improved reliability of connectivity 18 | v35 - Added Support for VEML6075 and SI1145 UVI Sensors 19 | v33 - Added Digital Sensor Switch Support 20 | v32 - Added MQTT Support! 21 | v29 - First Public Release 22 | */ 23 | /**************************************************************************/ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #ifndef _BRIDGE_H_ 30 | #define _BRIDGE_H_ 31 | 32 | #include "StateHelper.h" 33 | #include "UUID.h" 34 | #include "OTA.h" 35 | #include "../communication/WiFiManager.h" 36 | #include "../communication/MQTT.h" 37 | #include "../input/Sensor.h" 38 | #include "../input/analog/SensorAnalogue.h" 39 | #include "../input/SensorDigitalSwitch.h" 40 | #include "../input/i2c/Ads1x15.h" 41 | #include "../input/i2c/SensorBMx280.h" 42 | #include "../input/i2c/SensorBME680.h" 43 | #include "../input/i2c/SensorMax44009.h" 44 | #include "../input/i2c/SensorBH1750.h" 45 | #include "../input/i2c/SensorVEML6075.h" 46 | #include "../input/i2c/SensorSI1145.h" 47 | #include "../input/onewire/SensorDHT.h" 48 | #include "../input/onewire/SensorDallas.h" 49 | #include "../output/display/Display.h" 50 | #include "../output/display/DisplayOLED128.h" 51 | #include "../output/display/DisplayST7735.h" 52 | #include "../output/VisualisationHelper.h" 53 | 54 | void initSSL(); 55 | void registerBridge(); 56 | void restoreBridgeConfig(); 57 | void restart(); 58 | 59 | void getBridgeConfig(); 60 | void configureBridge(JsonObject&); 61 | void initVisualisationHelper(JsonObject&); 62 | void configureDisplayValueData(int, JsonObject&); 63 | void configureExpansionPort(int, JsonObject&); 64 | void configurePort(int, JsonObject&); 65 | void addSensor(Sensor *); 66 | void loopSensor(int); 67 | void loopDisplay(unsigned long); 68 | boolean postSensorData(Data* data[], int); 69 | boolean postSensorDataPart(Data* data[], int, int); 70 | void checkStatus(); 71 | void trySleep(long); 72 | void storeDisplayAndPowerConfig(boolean); 73 | void doPowerSaving(); 74 | void doPowerSavingInit(boolean); 75 | uint8_t translateGPIOPort(String); 76 | void tryInitMQTT(); 77 | void handlePortConfigArray(JsonArray&); 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /src/controller/OTA.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file OTA.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensatio ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensatio Cloud and the Sensatio apps. 8 | 9 | ----> https://www.sensatio.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v41 - Renamed Display Class to support more types 15 | v38 - Changed automatic Update to only if required Update 16 | v29 - First Public Release 17 | */ 18 | /**************************************************************************/ 19 | 20 | #include "OTA.h" 21 | 22 | extern State state; 23 | extern DisplayOLED128* display; 24 | extern bool isResetting; 25 | 26 | extern char firmwareType[]; 27 | extern int currentVersion; 28 | 29 | void tryFirmwareUpdate(String fwUpdateToken) { 30 | 31 | t_httpUpdate_return ret; 32 | ESPhttpUpdate.rebootOnUpdate(false); 33 | 34 | Serial.println("Trying firmware Update..."); 35 | 36 | if(display!=NULL) 37 | { 38 | display->clear(true); 39 | display->drawProductLogo(); 40 | display->drawString(10, 5, "Trying Firmware"); 41 | display->drawString(20, 21, "Update..."); 42 | } 43 | 44 | String updatePath = "/v1/bridge/firmware/"+fwUpdateToken+"?version="+String(currentVersion)+"&type="+firmwareType; 45 | 46 | Serial.println(updatePath); 47 | 48 | ret = ESPhttpUpdate.update("hub.sensate.cloud", 80, updatePath); 49 | switch(ret) { 50 | case HTTP_UPDATE_FAILED: 51 | if(display!=NULL) 52 | { 53 | display->clear(false); 54 | display->drawProductLogo(); 55 | } 56 | Serial.println("[update] Update failed."); 57 | break; 58 | case HTTP_UPDATE_NO_UPDATES: 59 | if(display!=NULL) 60 | { 61 | display->clear(false); 62 | display->drawProductLogo(); 63 | } 64 | Serial.println("[update] Update no Update."); 65 | break; 66 | case HTTP_UPDATE_OK: 67 | if(display!=NULL) 68 | { 69 | display->clear(true); 70 | } 71 | restart(); 72 | Serial.println("[update] Update ok."); // may not called we reboot the ESP 73 | break; 74 | } 75 | 76 | if(state==Check_Firmware) 77 | state = Connected_WiFi; 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/controller/OTA.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file OTA.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v38 - Changed automatic Update to only if required Update 15 | v29 - First Public Release 16 | */ 17 | /**************************************************************************/ 18 | 19 | #include 20 | #include "StateHelper.h" 21 | #include "../output/display/DisplayOLED128.h" 22 | 23 | #ifndef _OTA_h_ 24 | #define _OTA_h_ 25 | 26 | #include "Bridge.h" 27 | 28 | void tryFirmwareUpdate(String fwUpdateToken); 29 | 30 | #endif -------------------------------------------------------------------------------- /src/controller/StateHelper.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file StateHelper.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v29 - First Public Release 15 | */ 16 | /**************************************************************************/ 17 | 18 | #include "StateHelper.h" 19 | 20 | bool isWiFiConfigured() 21 | { 22 | EEPROM.begin(24); 23 | 24 | int val20 = EEPROM.read(20); 25 | int val21 = EEPROM.read(21); 26 | int val22 = EEPROM.read(22); 27 | int val23 = EEPROM.read(23); 28 | 29 | EEPROM.end(); 30 | 31 | if (val20 == 10 && val21 == 20 && val22 == 30 && val23 == 40) 32 | { 33 | EEPROM.begin(24); 34 | val20 = EEPROM.read(20); 35 | val21 = EEPROM.read(21); 36 | val22 = EEPROM.read(22); 37 | val23 = EEPROM.read(23); 38 | EEPROM.end(); 39 | } 40 | if (val20 == 11 && val21 == 21 && val22 == 31 && val23 == 41) 41 | return true; 42 | else 43 | return false; 44 | } -------------------------------------------------------------------------------- /src/controller/StateHelper.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file StateHelper.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v29 - First Public Release 15 | */ 16 | /**************************************************************************/ 17 | 18 | #include 19 | 20 | #ifndef _StateHelper_h_ 21 | #define _StateHelper_h_ 22 | 23 | typedef enum { 24 | Boot, // First State, do everything thats required to start 25 | Connect_WiFi, // Try to connect to a specified Wireless Network 26 | Check_Firmware, // On Connection Success, try to get Firmware Update 27 | Connected_WiFi, // Connection to WiFi Successful and Firmware Up to Date 28 | Register, // Register Bridge at the Cloud Service 29 | Init_Configuration, // Request the Bridge Configuration from the Sensate Cloud and initialize the received Configuration 30 | Operating, // Normal State after Setup 31 | Init_AP, // If connection cannot be established, enter Setup AP Mode 32 | Init_Setup, // Start everything needed for Setup Mode 33 | Setup // Operating in Setup Mode 34 | } State; 35 | 36 | bool isWiFiConfigured(); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/controller/UUID.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file UUID.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v29 - First Public Release 15 | */ 16 | /**************************************************************************/ 17 | 18 | #include "UUID.h" 19 | 20 | String _uuid = ""; 21 | 22 | String getUUID() { 23 | 24 | if (_uuid.length() != 0) 25 | return _uuid; 26 | else 27 | { 28 | EEPROM.begin(20); 29 | restoreUUID(); 30 | if (_uuid.length() == 0) 31 | generateUUID(); 32 | EEPROM.end(); 33 | } 34 | return _uuid; 35 | 36 | } 37 | 38 | void restoreUUID() { 39 | 40 | digitalWrite(16, HIGH); 41 | delay(300); 42 | digitalWrite(16, LOW); 43 | delay(300); 44 | 45 | int val0 = EEPROM.read(0); 46 | int val1 = EEPROM.read(1); 47 | int val2 = EEPROM.read(2); 48 | int val3 = EEPROM.read(3); 49 | 50 | if (val0 == 10 && val1 == 20 && val2 == 30 && val3 == 40) 51 | { 52 | byte uuidNumber[16]; 53 | EEPROM.get(4, uuidNumber); 54 | _uuid = ESP8266TrueRandom.uuidToString(uuidNumber); 55 | } 56 | 57 | } 58 | 59 | void generateUUID() { 60 | Serial.println("Generating new UUID"); 61 | byte uuidNumber[16]; 62 | ESP8266TrueRandom.uuid(uuidNumber); 63 | EEPROM.write(0, 10); 64 | EEPROM.write(1, 20); 65 | EEPROM.write(2, 30); 66 | EEPROM.write(3, 40); 67 | EEPROM.put(4, uuidNumber); 68 | _uuid = ESP8266TrueRandom.uuidToString(uuidNumber); 69 | } -------------------------------------------------------------------------------- /src/controller/UUID.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file UUID.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v29 - First Public Release 15 | */ 16 | /**************************************************************************/ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #ifndef _uuid_h_ 23 | #define _uuid_h_ 24 | 25 | String getUUID(); 26 | void restoreUUID(); 27 | void generateUUID(); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/input/Sensor.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Sensor.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v33 - Changes for Digital Sensor Switch Support 15 | v32 - Added MQTT Support! 16 | v29 - First Public Release 17 | */ 18 | /**************************************************************************/ 19 | 20 | #include "Sensor.h" 21 | 22 | extern unsigned long nextSensorDue; 23 | 24 | Sensor::Sensor (long id, String category, String shortName, String name, int refreshInterval, int postDataInterval, float smartValueThreshold, SensorCalculation* calculation, bool binary) { 25 | lastTick = -1; 26 | lastPost = -1; 27 | _refreshInterval = refreshInterval; 28 | _postDataInterval = postDataInterval; 29 | _name = name; 30 | _shortName = shortName; 31 | _category = category; 32 | _id = id; 33 | _calculation = calculation; 34 | _smartValueThreshold = smartValueThreshold; 35 | _binary = binary; 36 | } 37 | 38 | int Sensor::getRefreshInterval() { 39 | return _refreshInterval; 40 | } 41 | 42 | int Sensor::getPostDataInterval() { 43 | return _postDataInterval; 44 | } 45 | 46 | String Sensor::getCategory() { 47 | return _category; 48 | } 49 | 50 | String Sensor::getShortName() { 51 | return _shortName; 52 | } 53 | 54 | String Sensor::getName() { 55 | return _name; 56 | } 57 | 58 | String Sensor::getMqttClass() { 59 | 60 | if(_calculation==NULL) 61 | return "unknown"; 62 | 63 | return _calculation->getValueType(); 64 | } 65 | 66 | String Sensor::getMqttUnit() { 67 | if(_calculation==NULL) 68 | return "?"; 69 | 70 | return _calculation->getValueUnit(); 71 | } 72 | 73 | bool Sensor::isBinary() { 74 | return _binary; 75 | } 76 | 77 | long Sensor::getId() { 78 | return _id; 79 | } 80 | 81 | void Sensor::preCycle(int cycleId) 82 | { 83 | Serial.println("Base Sensor Pre Cycle: " + String(cycleId)); 84 | } 85 | 86 | Data* Sensor::read(bool shouldPostData) { 87 | Serial.println("Base Sensor Read: " + getName()); 88 | } 89 | 90 | Data* Sensor::trySensorRead(unsigned long currentTimeMillis, int cycleId) { 91 | 92 | if (lastTick==-1 || currentTimeMillis < lastTick) 93 | return forceSensorRead(currentTimeMillis, cycleId); 94 | else 95 | { 96 | if (lastTick + _refreshInterval <= currentTimeMillis) 97 | return forceSensorRead(currentTimeMillis, cycleId); 98 | } 99 | return NULL; 100 | } 101 | 102 | Data* Sensor::forceSensorRead(unsigned long currentTimeMillis, int cycleId) { 103 | 104 | preCycle(cycleId); 105 | 106 | bool shouldPostData = false; 107 | if(lastPost==-1 || (lastPost + _postDataInterval <= currentTimeMillis)) 108 | { 109 | shouldPostData = true; 110 | } 111 | 112 | Data *d = read(shouldPostData); 113 | lastTick = currentTimeMillis; 114 | if(shouldPostData) 115 | { 116 | if (d!=NULL) 117 | { 118 | lastPost = currentTimeMillis; 119 | } 120 | } 121 | 122 | if(nextSensorDue==-1 || nextSensorDue < currentTimeMillis || (nextSensorDue > currentTimeMillis+_postDataInterval)) 123 | { 124 | nextSensorDue = currentTimeMillis+_postDataInterval; 125 | } 126 | 127 | return d; 128 | 129 | } -------------------------------------------------------------------------------- /src/input/Sensor.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Sensor.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v33 - Changes for Digital Sensor Switch Support 15 | v32 - Added MQTT Support! 16 | v29 - First Public Release 17 | */ 18 | /**************************************************************************/ 19 | 20 | #include 21 | 22 | #ifndef _Sensor_h_ 23 | #define _Sensor_h_ 24 | 25 | #include "SensorCalculation.h" 26 | #include "../communication/Data.h" 27 | 28 | class SensorCalculation; 29 | 30 | class Sensor { 31 | protected: 32 | unsigned int _refreshInterval; 33 | unsigned int _postDataInterval; 34 | float _smartValueThreshold; 35 | unsigned long lastTick; 36 | unsigned long lastPost; 37 | String _category; 38 | String _name; 39 | String _shortName; 40 | long _id; 41 | SensorCalculation* _calculation; 42 | bool _binary; 43 | virtual void preCycle(int); 44 | virtual Data* read(bool); 45 | public: 46 | Sensor (long, String, String, String, int, int, float, SensorCalculation*, bool binary); 47 | int getRefreshInterval(void); 48 | int getPostDataInterval(void); 49 | long getId(void); 50 | String getName(void); 51 | String getShortName(void); 52 | String getCategory(void); 53 | String getMqttClass(void); 54 | String getMqttUnit(void); 55 | bool isBinary(); 56 | Data* trySensorRead(unsigned long, int); 57 | Data* forceSensorRead(unsigned long, int); 58 | }; 59 | 60 | #endif -------------------------------------------------------------------------------- /src/input/SensorCalculation.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorCalculation.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v40 - New Display Structure to enable Display Rotation, different Styles etc. 15 | v35 - Added Support for VEML6075 and SI1145 UVI Sensors 16 | v34 - Added Generic Analog Sensor Support 17 | v33 - Added Digital Sensor Switch Support 18 | v32 - Added MQTT Support! 19 | v29 - First Public Release 20 | */ 21 | /**************************************************************************/ 22 | 23 | #include "SensorCalculation.h" 24 | 25 | extern VisualisationHelper* vHelper; 26 | 27 | SensorCalculation::SensorCalculation() 28 | { 29 | 30 | } 31 | 32 | String SensorCalculation::getValueType() 33 | { 34 | return _valueType; 35 | } 36 | 37 | String SensorCalculation::getValueUnit() 38 | { 39 | return _valueUnit; 40 | } 41 | 42 | Data* SensorCalculation::calculate(Sensor* sensor, bool boolValue, bool postData) 43 | { 44 | return NULL; 45 | } 46 | 47 | SensorCalculationApproxQuad::SensorCalculationApproxQuad(double calcValue1, double calcValue2, double calcValue3, double calcValue4, int portNumber) : SensorCalculation() 48 | { 49 | _valueType = "temperature"; 50 | _valueUnit = "°C"; 51 | 52 | _portNumber = portNumber; 53 | _calcValue1 = calcValue1; 54 | _calcValue2 = calcValue2; 55 | _calcValue3 = calcValue3; 56 | _calcValue4 = calcValue4; 57 | } 58 | 59 | SensorCalculationPT1001000::SensorCalculationPT1001000(double r0, int portNumber) : SensorCalculation() 60 | { 61 | _valueType = "temperature"; 62 | _valueUnit = "°C"; 63 | 64 | a = 0.0039083; 65 | b = -0.0000005775; 66 | _portNumber = portNumber; 67 | _r0 = r0; 68 | } 69 | 70 | SensorCalculationDualNtc::SensorCalculationDualNtc(double calcValue1, double calcValue2, int portNumber) : SensorCalculation() 71 | { 72 | _valueType = "temperature"; 73 | _valueUnit = "°C"; 74 | 75 | _portNumber = portNumber; 76 | _calcValue1 = calcValue1; 77 | _calcValue2 = calcValue2; 78 | } 79 | 80 | SensorCalculationDirectKelvin::SensorCalculationDirectKelvin(int portNumber) : SensorCalculation() 81 | { 82 | _valueType = "temperature"; 83 | _valueUnit = "K"; 84 | 85 | _portNumber = portNumber; 86 | } 87 | 88 | SensorCalculationDirectCelsius::SensorCalculationDirectCelsius(int portNumber) : SensorCalculation() 89 | { 90 | _valueType = "temperature"; 91 | _valueUnit = "°C"; 92 | _portNumber = portNumber; 93 | } 94 | 95 | SensorCalculationDirectPercent::SensorCalculationDirectPercent(int portNumber) : SensorCalculation() 96 | { 97 | _valueType = "humidity"; 98 | _valueUnit = "%"; 99 | _portNumber = portNumber; 100 | } 101 | 102 | SensorCalculationDirectHektoPascal::SensorCalculationDirectHektoPascal(int portNumber) : SensorCalculation() 103 | { 104 | _valueType = "pressure"; 105 | _valueUnit = "hPa"; 106 | _portNumber = portNumber; 107 | } 108 | 109 | SensorCalculationDirectMeter::SensorCalculationDirectMeter(int portNumber) : SensorCalculation() 110 | { 111 | _valueType = ""; 112 | _valueUnit = "m"; 113 | _portNumber = portNumber; 114 | } 115 | 116 | SensorCalculationDirectLux::SensorCalculationDirectLux(int portNumber) : SensorCalculation() 117 | { 118 | _valueType = "illuminance"; 119 | _valueUnit = "lx"; 120 | _portNumber = portNumber; 121 | } 122 | 123 | SensorCalculationDirectLumen::SensorCalculationDirectLumen(int portNumber) : SensorCalculation() 124 | { 125 | _valueType = "flux"; 126 | _valueUnit = "lm"; 127 | _portNumber = portNumber; 128 | } 129 | 130 | SensorCalculationDirectOhm::SensorCalculationDirectOhm(int portNumber) : SensorCalculation() 131 | { 132 | _valueType = "resistance"; 133 | _valueUnit = "Ohm"; 134 | _portNumber = portNumber; 135 | } 136 | 137 | SensorCalculationDirectKOhm::SensorCalculationDirectKOhm(int portNumber) : SensorCalculation() 138 | { 139 | _valueType = "resistance"; 140 | _valueUnit = "kOhm"; 141 | _portNumber = portNumber; 142 | } 143 | 144 | SensorCalculationDirectPPM::SensorCalculationDirectPPM(int portNumber) : SensorCalculation() 145 | { 146 | _valueType = "concentration"; 147 | _valueUnit = "ppm"; 148 | _portNumber = portNumber; 149 | } 150 | 151 | SensorCalculationDirectNone::SensorCalculationDirectNone(int portNumber) : SensorCalculation() 152 | { 153 | _valueType = "unknown"; 154 | _valueUnit = ""; 155 | _portNumber = portNumber; 156 | } 157 | 158 | SensorCalculationDirectWpm2::SensorCalculationDirectWpm2(int portNumber) : SensorCalculation() 159 | { 160 | _valueType = "irradiance"; 161 | _valueUnit = "W/m²"; 162 | _portNumber = portNumber; 163 | } 164 | 165 | SensorCalculationCalcAltitude::SensorCalculationCalcAltitude(int portNumber) : SensorCalculation() 166 | { 167 | _valueType = "altitude"; 168 | _valueUnit = "m"; 169 | _portNumber = portNumber; 170 | } 171 | 172 | SensorCalculationRawToPercent::SensorCalculationRawToPercent(float calcValue1, float calcValue2, int portNumber) : SensorCalculation() 173 | { 174 | _valueType = "plevel"; 175 | _valueUnit = "%"; 176 | _portNumber = portNumber; 177 | _calcValue1 = calcValue1; 178 | _calcValue2 = calcValue2; 179 | } 180 | 181 | SensorCalculationRawToVoltage::SensorCalculationRawToVoltage(float calcValue1, float calcValue2, int portNumber) : SensorCalculation() 182 | { 183 | _valueType = "voltage"; 184 | _valueUnit = "V"; 185 | _portNumber = portNumber; 186 | _calcValue1 = calcValue1; 187 | _calcValue2 = calcValue2; 188 | } 189 | 190 | SensorCalculationRaw::SensorCalculationRaw(int portNumber) : SensorCalculation() 191 | { 192 | _valueType = "raw"; 193 | _valueUnit = ""; 194 | _portNumber = portNumber; 195 | } 196 | 197 | SensorCalculationRaw::SensorCalculationRaw(int portNumber, String valueUnit) : SensorCalculation() 198 | { 199 | _valueType = valueUnit; 200 | _valueUnit = ""; 201 | _portNumber = portNumber; 202 | } 203 | 204 | Data* SensorCalculation::calculate(Sensor* sensor, float rawValue, bool postData) 205 | { 206 | return NULL; 207 | } 208 | 209 | Data* SensorCalculationApproxQuad::calculate(Sensor* sensor, float rawValue, bool postData) 210 | { 211 | double v = log( (double)rawValue / _calcValue4); 212 | double z = _calcValue1 + (_calcValue2 * v) + (_calcValue3 * v * v); 213 | float tempInC = (float) ((float) (1 / z) - 273.15); 214 | 215 | if(_portNumber>=0) 216 | vHelper->getDisplayDataModel()->updateData(_portNumber, tempInC , _valueUnit); 217 | 218 | if(!postData) 219 | return NULL; 220 | return new Data (sensor, tempInC, "CELSIUS"); 221 | } 222 | 223 | Data* SensorCalculationPT1001000::calculate(Sensor* sensor, float rT, bool postData) 224 | { 225 | double v2 = _r0*_r0*a*a; 226 | double v3 = 4*_r0*b*(_r0-rT); 227 | double v4 = sqrt(v2-v3); 228 | 229 | double v5 = 2*_r0*b; 230 | float tempInC = (float)(-_r0*a+v4)/v5; 231 | 232 | if(_portNumber>=0) 233 | vHelper->getDisplayDataModel()->updateData(_portNumber, tempInC , _valueUnit); 234 | 235 | if(!postData) 236 | return NULL; 237 | return new Data (sensor, tempInC, "CELSIUS"); 238 | } 239 | 240 | Data* SensorCalculationDualNtc::calculate(Sensor* sensor, float rawValue, bool postData) 241 | { 242 | double x = 0.003354016; 243 | double y = log(rawValue / _calcValue2); 244 | double z = y / _calcValue1; 245 | float tempInC = (float) ((1.0 / (z + x))- 273.15); 246 | 247 | if(_portNumber>=0) 248 | vHelper->getDisplayDataModel()->updateData(_portNumber, tempInC , _valueUnit); 249 | 250 | if(!postData) 251 | return NULL; 252 | return new Data (sensor, tempInC, "CELSIUS"); 253 | } 254 | 255 | Data* SensorCalculationDirectKelvin::calculate(Sensor* sensor, float rawValue, bool postData) 256 | { 257 | if(_portNumber>=0) 258 | vHelper->getDisplayDataModel()->updateData(_portNumber, rawValue, _valueUnit); 259 | 260 | if(!postData) 261 | return NULL; 262 | return new Data (sensor, rawValue, "KELVIN"); 263 | } 264 | 265 | Data* SensorCalculationDirectCelsius::calculate(Sensor* sensor, float rawValue, bool postData) 266 | { 267 | if(_portNumber>=0) 268 | vHelper->getDisplayDataModel()->updateData(_portNumber, rawValue, _valueUnit); 269 | 270 | if(!postData) 271 | return NULL; 272 | return new Data (sensor, rawValue, "CELSIUS"); 273 | } 274 | 275 | Data* SensorCalculationDirectPercent::calculate(Sensor* sensor, float rawValue, bool postData) 276 | { 277 | if(_portNumber>=0) 278 | vHelper->getDisplayDataModel()->updateData(_portNumber, rawValue, _valueUnit); 279 | 280 | if(!postData) 281 | return NULL; 282 | return new Data (sensor, rawValue, "PERCENT"); 283 | } 284 | 285 | Data* SensorCalculationDirectHektoPascal::calculate(Sensor* sensor, float rawValue, bool postData) 286 | { 287 | if(_portNumber>=0) 288 | vHelper->getDisplayDataModel()->updateData(_portNumber, rawValue, _valueUnit); 289 | 290 | if(!postData) 291 | return NULL; 292 | return new Data (sensor, rawValue, "HEKTOPASCAL"); 293 | } 294 | 295 | Data* SensorCalculationDirectMeter::calculate(Sensor* sensor, float rawValue, bool postData) 296 | { 297 | if(_portNumber>=0) 298 | vHelper->getDisplayDataModel()->updateData(_portNumber, rawValue, _valueUnit); 299 | 300 | if(!postData) 301 | return NULL; 302 | return new Data (sensor, rawValue, "METER"); 303 | } 304 | 305 | Data* SensorCalculationDirectLux::calculate(Sensor* sensor, float rawValue, bool postData) 306 | { 307 | if(_portNumber>=0) 308 | vHelper->getDisplayDataModel()->updateData(_portNumber, rawValue, _valueUnit); 309 | 310 | if(!postData) 311 | return NULL; 312 | return new Data (sensor, rawValue, "LUX"); 313 | } 314 | 315 | Data* SensorCalculationDirectLumen::calculate(Sensor* sensor, float rawValue, bool postData) 316 | { 317 | if(_portNumber>=0) 318 | vHelper->getDisplayDataModel()->updateData(_portNumber, rawValue, _valueUnit); 319 | 320 | if(!postData) 321 | return NULL; 322 | return new Data (sensor, rawValue, "LUMEN"); 323 | } 324 | 325 | Data* SensorCalculationDirectOhm::calculate(Sensor* sensor, float rawValue, bool postData) 326 | { 327 | if(_portNumber>=0) 328 | vHelper->getDisplayDataModel()->updateData(_portNumber, rawValue, _valueUnit); 329 | 330 | if(!postData) 331 | return NULL; 332 | return new Data (sensor, rawValue, "OHM"); 333 | } 334 | 335 | Data* SensorCalculationDirectKOhm::calculate(Sensor* sensor, float rawValue, bool postData) 336 | { 337 | if(_portNumber>=0) 338 | vHelper->getDisplayDataModel()->updateData(_portNumber, rawValue, _valueUnit); 339 | 340 | if(!postData) 341 | return NULL; 342 | return new Data (sensor, rawValue, "KOHM"); 343 | } 344 | 345 | Data* SensorCalculationDirectPPM::calculate(Sensor* sensor, float rawValue, bool postData) 346 | { 347 | if(_portNumber>=0) 348 | vHelper->getDisplayDataModel()->updateData(_portNumber, rawValue, _valueUnit); 349 | 350 | if(!postData) 351 | return NULL; 352 | return new Data (sensor, rawValue, "PPM"); 353 | } 354 | 355 | Data* SensorCalculationDirectWpm2::calculate(Sensor* sensor, float rawValue, bool postData) 356 | { 357 | if(_portNumber>=0) 358 | vHelper->getDisplayDataModel()->updateData(_portNumber, rawValue, _valueUnit); 359 | 360 | if(!postData) 361 | return NULL; 362 | return new Data (sensor, rawValue, "WPM2"); 363 | } 364 | 365 | Data* SensorCalculationDirectNone::calculate(Sensor* sensor, float rawValue, bool postData) 366 | { 367 | if(_portNumber>=0) 368 | vHelper->getDisplayDataModel()->updateData(_portNumber, rawValue, _valueUnit); 369 | 370 | if(!postData) 371 | return NULL; 372 | return new Data (sensor, rawValue, "NONE"); 373 | } 374 | 375 | Data* SensorCalculationCalcAltitude::calculate(Sensor* sensor, float rawValue, bool postData) 376 | { 377 | float altitude = 44330.0 * (1.0 - pow(rawValue / 1013.25, 0.1903)); 378 | 379 | if(_portNumber>=0) 380 | vHelper->getDisplayDataModel()->updateData(_portNumber, altitude, _valueUnit); 381 | 382 | if(!postData) 383 | return NULL; 384 | return new Data (sensor, altitude, "METER"); 385 | } 386 | 387 | Data* SensorCalculationRawToPercent::calculate(Sensor* sensor, float rawValue, bool postData) 388 | { 389 | float min = _calcValue1; 390 | float max = _calcValue2; 391 | 392 | float rawDiff = rawValue - min; 393 | float percent = rawDiff * 100 / (max - min); 394 | 395 | if(percent<0) percent = 0.0; 396 | if(percent>100) percent = 100.0; 397 | 398 | if(_portNumber>=0) 399 | vHelper->getDisplayDataModel()->updateData(_portNumber, percent, _valueUnit); 400 | 401 | if(!postData) 402 | return NULL; 403 | return new Data (sensor, percent, "PERCENT"); 404 | } 405 | 406 | Data* SensorCalculationRawToVoltage::calculate(Sensor* sensor, float rawValue, bool postData) 407 | { 408 | float refVoltage = _calcValue1; 409 | float maxADCValue = _calcValue2; 410 | 411 | float rawVoltage = rawValue / maxADCValue; 412 | float vResult = rawVoltage * refVoltage; 413 | 414 | if(_portNumber>=0) 415 | vHelper->getDisplayDataModel()->updateData(_portNumber, vResult, _valueUnit); 416 | 417 | if(!postData) 418 | return NULL; 419 | return new Data (sensor, vResult, "VOLT"); 420 | } 421 | 422 | Data* SensorCalculationRaw::calculate(Sensor* sensor, float rawValue, bool postData) 423 | { 424 | if(_portNumber>=0) 425 | vHelper->getDisplayDataModel()->updateData(_portNumber, rawValue, _valueUnit); 426 | 427 | if(!postData) 428 | return NULL; 429 | return new Data (sensor, rawValue, "NONE"); 430 | } 431 | 432 | Data* SensorCalculationRaw::calculate(Sensor* sensor, bool boolValue, bool postData) 433 | { 434 | if(_portNumber>=0) 435 | vHelper->getDisplayDataModel()->updateData(_portNumber, boolValue, _valueUnit); 436 | 437 | if(!postData) 438 | return NULL; 439 | return new Data (sensor, boolValue, "NONE"); 440 | } -------------------------------------------------------------------------------- /src/input/SensorCalculation.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorCalculation.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v40 - New Display Structure to enable Display Rotation, different Styles etc. 15 | v35 - Added Support for VEML6075 and SI1145 UVI Sensors 16 | v34 - Added Generic Analog Sensor Support 17 | v33 - Added Digital Sensor Switch Support 18 | v32 - Added MQTT Support! 19 | v29 - First Public Release 20 | */ 21 | /**************************************************************************/ 22 | 23 | #include 24 | #include 25 | 26 | #ifndef _SensorCalculation_h_ 27 | #define _SensorCalculation_h_ 28 | 29 | #include "Sensor.h" 30 | #include "../output/VisualisationHelper.h" 31 | 32 | class Data; 33 | class Sensor; 34 | 35 | class SensorCalculation { 36 | protected: 37 | int _portNumber; 38 | String _valueType; 39 | String _valueUnit; 40 | public: 41 | String getValueType(); 42 | String getValueUnit(); 43 | SensorCalculation(); 44 | virtual Data* calculate(Sensor* sensor, float, bool); 45 | virtual Data* calculate(Sensor* sensor, bool, bool); 46 | }; 47 | 48 | class SensorCalculationApproxQuad : public SensorCalculation { 49 | private: 50 | double _calcValue1,_calcValue2,_calcValue3,_calcValue4; 51 | public: 52 | SensorCalculationApproxQuad(double, double, double, double, int); 53 | Data* calculate(Sensor* sensor, float, bool); 54 | }; 55 | 56 | class SensorCalculationPT1001000 : public SensorCalculation { 57 | private: 58 | double _r0, a, b; 59 | public: 60 | SensorCalculationPT1001000(double, int); 61 | Data* calculate(Sensor* sensor, float, bool); 62 | }; 63 | 64 | class SensorCalculationDualNtc : public SensorCalculation { 65 | private: 66 | double _calcValue1,_calcValue2; 67 | public: 68 | SensorCalculationDualNtc(double, double, int); 69 | Data* calculate(Sensor* sensor, float, bool); 70 | }; 71 | 72 | class SensorCalculationDirectKelvin : public SensorCalculation { 73 | public: 74 | SensorCalculationDirectKelvin(int); 75 | Data* calculate(Sensor* sensor, float, bool); 76 | }; 77 | 78 | class SensorCalculationDirectCelsius : public SensorCalculation { 79 | public: 80 | SensorCalculationDirectCelsius(int); 81 | Data* calculate(Sensor* sensor, float, bool); 82 | }; 83 | 84 | class SensorCalculationDirectPercent : public SensorCalculation { 85 | public: 86 | SensorCalculationDirectPercent(int); 87 | Data* calculate(Sensor* sensor, float, bool); 88 | }; 89 | 90 | class SensorCalculationDirectHektoPascal : public SensorCalculation { 91 | public: 92 | SensorCalculationDirectHektoPascal(int); 93 | Data* calculate(Sensor* sensor, float, bool); 94 | }; 95 | 96 | class SensorCalculationDirectMeter : public SensorCalculation { 97 | public: 98 | SensorCalculationDirectMeter(int); 99 | Data* calculate(Sensor* sensor, float, bool); 100 | }; 101 | 102 | class SensorCalculationDirectLux : public SensorCalculation { 103 | public: 104 | SensorCalculationDirectLux(int); 105 | Data* calculate(Sensor* sensor, float, bool); 106 | }; 107 | 108 | class SensorCalculationDirectLumen : public SensorCalculation { 109 | public: 110 | SensorCalculationDirectLumen(int); 111 | Data* calculate(Sensor* sensor, float, bool); 112 | }; 113 | 114 | class SensorCalculationDirectNone : public SensorCalculation { 115 | public: 116 | SensorCalculationDirectNone(int); 117 | Data* calculate(Sensor* sensor, float, bool); 118 | }; 119 | 120 | class SensorCalculationDirectOhm : public SensorCalculation { 121 | public: 122 | SensorCalculationDirectOhm(int); 123 | Data* calculate(Sensor* sensor, float, bool); 124 | }; 125 | 126 | class SensorCalculationDirectKOhm : public SensorCalculation { 127 | public: 128 | SensorCalculationDirectKOhm(int); 129 | Data* calculate(Sensor* sensor, float, bool); 130 | }; 131 | 132 | class SensorCalculationDirectPPM : public SensorCalculation { 133 | public: 134 | SensorCalculationDirectPPM(int); 135 | Data* calculate(Sensor* sensor, float, bool); 136 | }; 137 | 138 | class SensorCalculationDirectWpm2 : public SensorCalculation { 139 | public: 140 | SensorCalculationDirectWpm2(int); 141 | Data* calculate(Sensor* sensor, float, bool); 142 | }; 143 | 144 | class SensorCalculationCalcAltitude : public SensorCalculation { 145 | public: 146 | SensorCalculationCalcAltitude(int); 147 | Data* calculate(Sensor* sensor, float, bool); 148 | }; 149 | 150 | class SensorCalculationRawToPercent : public SensorCalculation { 151 | private: 152 | float _calcValue1,_calcValue2; 153 | public: 154 | SensorCalculationRawToPercent(float, float, int); 155 | Data* calculate(Sensor* sensor, float, bool); 156 | }; 157 | 158 | class SensorCalculationRaw : public SensorCalculation { 159 | public: 160 | SensorCalculationRaw(int); 161 | SensorCalculationRaw(int, String); 162 | Data* calculate(Sensor* sensor, float, bool); 163 | Data* calculate(Sensor* sensor, bool, bool); 164 | }; 165 | 166 | class SensorCalculationRawToVoltage : public SensorCalculation { 167 | private: 168 | float _calcValue1,_calcValue2; 169 | public: 170 | SensorCalculationRawToVoltage(float, float, int); 171 | Data* calculate(Sensor* sensor, float, bool); 172 | }; 173 | 174 | 175 | #endif -------------------------------------------------------------------------------- /src/input/SensorDigitalSwitch.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorDigitalSwitch.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v33 - Added Digital Sensor Switch 15 | */ 16 | /**************************************************************************/ 17 | 18 | #include "SensorDigitalSwitch.h" 19 | 20 | extern boolean isResetting; 21 | extern int powerMode; 22 | 23 | SensorDigitalSwitch::SensorDigitalSwitch (long id, String category, String shortName, String name, uint8_t port, int refreshInterval, int postDataInterval, SensorCalculation* calculation) : Sensor (id, category, shortName, name, refreshInterval, postDataInterval, 0.5, calculation, true) { 24 | 25 | pinMode(port, INPUT); 26 | _port = port; 27 | 28 | } 29 | 30 | void SensorDigitalSwitch::preCycle(int cycleId) 31 | { 32 | } 33 | 34 | Data* SensorDigitalSwitch::read(bool shouldPostData) 35 | { 36 | if(!isResetting) 37 | { 38 | bool portState = digitalRead(_port); 39 | if(lastPostedValue!=portState) 40 | shouldPostData = true; 41 | 42 | Data *data = _calculation->calculate(this, portState, shouldPostData); 43 | 44 | if(shouldPostData) 45 | lastPostedValue = portState; 46 | 47 | return data; 48 | } 49 | 50 | return NULL; 51 | 52 | } 53 | 54 | boolean SensorDigitalSwitch::smartSensorCheck(float currentRawValue, float threshhold, boolean shouldPostData) 55 | { 56 | if(powerMode == 3) 57 | { 58 | if(!shouldPostData) 59 | { 60 | if(!isnan(lastPostedValue)) 61 | { 62 | if(lastPostedValue-currentRawValue>threshhold|| lastPostedValue-currentRawValue<-threshhold) 63 | { 64 | shouldPostData = true; 65 | } 66 | } 67 | } 68 | 69 | if(shouldPostData) 70 | lastPostedValue = currentRawValue; 71 | } 72 | 73 | return shouldPostData; 74 | } -------------------------------------------------------------------------------- /src/input/SensorDigitalSwitch.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorDigitalSwitch.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v33 - Added Digital Sensor Switch 15 | */ 16 | /**************************************************************************/ 17 | 18 | #ifndef _SensorDigitalSwitch_h_ 19 | #define _SensorDigitalSwitch_h_ 20 | 21 | #include "Sensor.h" 22 | 23 | class SensorDigitalSwitch : public Sensor { 24 | private: 25 | bool lastPostedValue = 0; 26 | uint8_t _port; 27 | protected: 28 | Data* read(bool); 29 | void preCycle(int); 30 | boolean smartSensorCheck(float, float, boolean); 31 | public: 32 | SensorDigitalSwitch (long, String, String, String, uint8_t, int, int, SensorCalculation*); 33 | }; 34 | 35 | #endif -------------------------------------------------------------------------------- /src/input/analog/SensorAnalogue.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorAnalogue.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v34 - Added Generic Analog Sensor Support 15 | v33 - Changes for Digital Sensor Switch Support 16 | v29 - First Public Release 17 | v32 - Added MQTT Support! 18 | */ 19 | /**************************************************************************/ 20 | 21 | #include "SensorAnalogue.h" 22 | 23 | extern boolean isResetting; 24 | extern int powerMode; 25 | 26 | SensorAnalogue::SensorAnalogue (long id, String category, String shortName, String name, int refreshInterval, int postDataInterval, float smartValueThreshold, SensorCalculation* calculation) : Sensor (id, category, shortName, name, refreshInterval, postDataInterval, smartValueThreshold, calculation, false) { 27 | 28 | } 29 | 30 | SensorAnalogue::SensorAnalogue (long id, String category, String shortName, String name, int rSplit, int refreshInterval, int postDataInterval, float smartValueThreshold, SensorCalculation* calculation) : Sensor (id, category, shortName, name, refreshInterval, postDataInterval, smartValueThreshold, calculation, false) { 31 | 32 | _rSplit = rSplit; 33 | 34 | } 35 | 36 | void SensorAnalogue::preCycle(int cycleId) 37 | { 38 | } 39 | 40 | Data* SensorAnalogue::read(bool shouldPostData) 41 | { 42 | if(!isResetting) 43 | { 44 | float adc = 0; 45 | 46 | for (int i = 0; i < 10; i++) 47 | { 48 | adc = adc + (float) analogRead(0); // ADC = A0 49 | } 50 | 51 | adc = adc / 10.0; 52 | 53 | if(!std::isinf(adc)) 54 | { 55 | if(_rSplit!=0) 56 | { 57 | double rT = ((double) adc)*_rSplit/(1023-adc); 58 | shouldPostData = smartSensorCheck(rT, _smartValueThreshold, shouldPostData); 59 | return _calculation->calculate(this, (float)rT, shouldPostData); 60 | } 61 | else 62 | { 63 | shouldPostData = smartSensorCheck(adc, _smartValueThreshold, shouldPostData); 64 | return _calculation->calculate(this, adc, shouldPostData); 65 | } 66 | } 67 | } 68 | 69 | return NULL; 70 | 71 | } 72 | 73 | boolean SensorAnalogue::smartSensorCheck(float currentRawValue, float threshhold, boolean shouldPostData) 74 | { 75 | if(powerMode == 3) 76 | { 77 | if(!shouldPostData) 78 | { 79 | if(!isnan(lastPostedValue)) 80 | { 81 | if(lastPostedValue-currentRawValue>threshhold|| lastPostedValue-currentRawValue<-threshhold) 82 | { 83 | shouldPostData = true; 84 | } 85 | } 86 | } 87 | 88 | if(shouldPostData) 89 | lastPostedValue = currentRawValue; 90 | } 91 | 92 | return shouldPostData; 93 | } -------------------------------------------------------------------------------- /src/input/analog/SensorAnalogue.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorAnalogue.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v32 - Added MQTT Support! 15 | v29 - First Public Release 16 | */ 17 | /**************************************************************************/ 18 | 19 | #ifndef _SensorAnalogue_h_ 20 | #define _SensorAnalogue_h_ 21 | 22 | #include "../Sensor.h" 23 | 24 | class SensorAnalogue : public Sensor { 25 | private: 26 | int numberOfSamples; 27 | int _rSplit; 28 | float lastPostedValue = NAN; 29 | protected: 30 | Data* read(bool); 31 | void preCycle(int); 32 | boolean smartSensorCheck(float, float, boolean); 33 | public: 34 | SensorAnalogue (long, String, String, String, int, int, float, SensorCalculation*); 35 | SensorAnalogue (long, String, String, String, int, int, int, float, SensorCalculation*); 36 | }; 37 | 38 | #endif -------------------------------------------------------------------------------- /src/input/i2c/Ads1x15.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Ads1x15.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v34 - Added Generic Analog Sensor Support 15 | v33 - Changes for Digital Sensor Switch Support 16 | v32 - Added MQTT Support! 17 | v29 - First Public Release 18 | */ 19 | /**************************************************************************/ 20 | 21 | #include "Ads1x15.h" 22 | 23 | boolean Ads1x15::init48 = false; 24 | boolean Ads1x15::init49 = false; 25 | boolean Ads1x15::init4A = false; 26 | boolean Ads1x15::init4B = false; 27 | Adafruit_ADS1015* Ads1x15::ads1x15_48 = NULL; 28 | Adafruit_ADS1015* Ads1x15::ads1x15_49 = NULL; 29 | Adafruit_ADS1015* Ads1x15::ads1x15_4A = NULL; 30 | Adafruit_ADS1015* Ads1x15::ads1x15_4B = NULL; 31 | 32 | extern int powerMode; 33 | 34 | Ads1x15::Ads1x15 (long id, String category, String shortName, String name, String type, String addressString, int channel, int preResistor, int postResistor, int refreshInterval, int postDataInterval, float smartValueThreshold, SensorCalculation* calculation) : Sensor (id, category, shortName, name, refreshInterval, postDataInterval, smartValueThreshold, calculation, false) { 35 | 36 | _channel = channel; 37 | numberOfSamples = 10; 38 | _preResistor = (float) preResistor; 39 | _postResistor = (float) postResistor; 40 | 41 | if (addressString == NULL | addressString == "" || addressString == "0x48") { 42 | if (!init48) 43 | { 44 | init48 = true; 45 | 46 | if(type == "ADS1115") 47 | ads1x15_48 = new Adafruit_ADS1115(0x48); 48 | else 49 | ads1x15_48 = new Adafruit_ADS1015(0x48); 50 | 51 | ads1x15_48->setGain(GAIN_TWOTHIRDS); 52 | ads1x15_48->begin(); 53 | } 54 | ads1x15 = ads1x15_48; 55 | } 56 | else if (addressString == "0x49") { 57 | if (!init49) 58 | { 59 | init49 = true; 60 | 61 | if(type == "ADS1115") 62 | ads1x15_48 = new Adafruit_ADS1115(0x49); 63 | else 64 | ads1x15_49 = new Adafruit_ADS1015(0x49); 65 | 66 | ads1x15_49->setGain(GAIN_TWOTHIRDS); 67 | ads1x15_49->begin(); 68 | } 69 | ads1x15 = ads1x15_49; 70 | } 71 | 72 | else if (addressString == "0x4A") { 73 | if (!init4A) 74 | { 75 | init4A = true; 76 | 77 | if(type == "ADS1115") 78 | ads1x15_48 = new Adafruit_ADS1115(0x4A); 79 | else 80 | ads1x15_4A = new Adafruit_ADS1015(0x4A); 81 | 82 | ads1x15_4A->setGain(GAIN_TWOTHIRDS); 83 | ads1x15_4A->begin(); 84 | } 85 | ads1x15 = ads1x15_4A; 86 | } 87 | else if (addressString == "0x4B") { 88 | if (!init4B) 89 | { 90 | init4B = true; 91 | 92 | if(type == "ADS1115") 93 | ads1x15_48 = new Adafruit_ADS1115(0x4B); 94 | else 95 | ads1x15_4B = new Adafruit_ADS1015(0x4B); 96 | 97 | ads1x15_4B->setGain(GAIN_TWOTHIRDS); 98 | ads1x15_4B->begin(); 99 | } 100 | ads1x15 = ads1x15_4B; 101 | } 102 | 103 | } 104 | 105 | void Ads1x15::preCycle(int cycleId) 106 | { 107 | } 108 | 109 | Data* Ads1x15::read(bool shouldPostData) 110 | { 111 | float adcMax = 0; 112 | float adc = 0; 113 | 114 | for (int i = 0; i < numberOfSamples; i++) 115 | { 116 | adcMax = adcMax + (float) ads1x15->readADC_SingleEnded(0); 117 | 118 | if (_channel == 1) 119 | adc = adc + (float) ads1x15->readADC_SingleEnded(1); 120 | if (_channel == 2) 121 | adc = adc + (float) ads1x15->readADC_SingleEnded(2); 122 | if (_channel == 3) 123 | adc = adc + (float) ads1x15->readADC_SingleEnded(3); 124 | } 125 | 126 | adcMax = adcMax / (float)numberOfSamples; 127 | adc = adc / (float)numberOfSamples; 128 | 129 | if (adc >= adcMax-20) 130 | adc = adcMax; 131 | 132 | if((_preResistor!=0 && _postResistor!=0) || (_preResistor==0 && _postResistor==0)) 133 | { 134 | shouldPostData = smartSensorCheck(adc, _smartValueThreshold, shouldPostData); 135 | return _calculation->calculate(this, adc, shouldPostData); 136 | } 137 | else 138 | { 139 | float res = NULL; 140 | 141 | if(_preResistor>0) 142 | res = _preResistor / (adcMax / adc - 1.0); 143 | else if(_postResistor>0) 144 | res = _postResistor * (adcMax / adc - 1.0); 145 | 146 | if(res!=NULL && !std::isinf(res)) 147 | { 148 | // Serial.printf("Corrected res: %f\n\r",res); 149 | shouldPostData = smartSensorCheck(res, _smartValueThreshold, shouldPostData); 150 | return _calculation->calculate(this, res, shouldPostData); 151 | } 152 | } 153 | 154 | return NULL; 155 | 156 | } 157 | 158 | boolean Ads1x15::smartSensorCheck(float currentRawValue, float threshhold, boolean shouldPostData) 159 | { 160 | if(powerMode == 3) 161 | { 162 | if(!shouldPostData) 163 | { 164 | if(!isnan(lastPostedValue)) 165 | { 166 | if(lastPostedValue-currentRawValue>threshhold || lastPostedValue-currentRawValue<-threshhold) 167 | { 168 | shouldPostData = true; 169 | } 170 | } 171 | } 172 | 173 | if(shouldPostData) 174 | lastPostedValue = currentRawValue; 175 | } 176 | 177 | return shouldPostData; 178 | 179 | } -------------------------------------------------------------------------------- /src/input/i2c/Ads1x15.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Ads1x15.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v32 - Added MQTT Support! 15 | v29 - First Public Release 16 | */ 17 | /**************************************************************************/ 18 | 19 | #ifndef _Ads1x15_h_ 20 | #define _Ads1x15_h_ 21 | 22 | #include "../Sensor.h" 23 | #include "thirdparty/Adafruit_ADS1015.h" 24 | 25 | class Ads1x15 : public Sensor { 26 | private: 27 | static boolean init48; 28 | static boolean init49; 29 | static boolean init4A; 30 | static boolean init4B; 31 | static Adafruit_ADS1015* ads1x15_48; 32 | static Adafruit_ADS1015* ads1x15_49; 33 | static Adafruit_ADS1015* ads1x15_4A; 34 | static Adafruit_ADS1015* ads1x15_4B; 35 | Adafruit_ADS1015* ads1x15; 36 | int _channel; 37 | int numberOfSamples; 38 | float _preResistor; 39 | float _postResistor; 40 | float lastPostedValue = NAN; 41 | protected: 42 | Data* read(bool); 43 | void preCycle(int); 44 | boolean smartSensorCheck(float, float, boolean); 45 | public: 46 | Ads1x15 (long, String, String, String, String, String, int, int, int, int, int, float, SensorCalculation*); 47 | }; 48 | 49 | #endif -------------------------------------------------------------------------------- /src/input/i2c/SensorBH1750.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorBH1750.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v33 - Changes for Digital Sensor Switch Support 15 | v32 - Added MQTT Support! 16 | v29 - First Public Release 17 | */ 18 | /**************************************************************************/ 19 | 20 | #include "SensorBH1750.h" 21 | 22 | extern boolean isResetting; 23 | extern int powerMode; 24 | 25 | BH1750* SensorBH1750::bh1750; 26 | 27 | SensorBH1750::SensorBH1750 (long id, String category, String shortName, String name, String PortSDA, String PortSCL, int refreshInterval, int postDataInterval, float smartValueThreshold, SensorCalculation* calculation) : Sensor (id, category, shortName, name, refreshInterval, postDataInterval, smartValueThreshold, calculation, false) { 28 | 29 | if(bh1750==NULL) 30 | { 31 | bh1750 = new BH1750(); 32 | 33 | bh1750->begin(); 34 | } 35 | } 36 | 37 | void SensorBH1750::preCycle(int cycleId) 38 | { 39 | } 40 | 41 | Data* SensorBH1750::read(bool shouldPostData) 42 | { 43 | if(!isResetting) 44 | { 45 | if(_calculation->getValueType()=="illuminance") 46 | { 47 | float illuminance = bh1750->readLightLevel(); 48 | 49 | if(illuminance>=0) 50 | { 51 | shouldPostData = smartSensorCheck(illuminance, _smartValueThreshold, shouldPostData); 52 | return _calculation->calculate(this, illuminance, shouldPostData); 53 | } 54 | else 55 | Serial.println("NAN Illuminance!"); 56 | } 57 | } 58 | 59 | return NULL; 60 | } 61 | 62 | boolean SensorBH1750::smartSensorCheck(float currentRawValue, float threshhold, boolean shouldPostData) 63 | { 64 | if(powerMode == 3) 65 | { 66 | if(!shouldPostData) 67 | { 68 | if(!isnan(lastPostedValue)) 69 | { 70 | if(lastPostedValue-currentRawValue>threshhold || lastPostedValue-currentRawValue<-threshhold) 71 | { 72 | shouldPostData = true; 73 | } 74 | } 75 | } 76 | 77 | if(shouldPostData) 78 | lastPostedValue = currentRawValue; 79 | } 80 | 81 | return shouldPostData; 82 | 83 | } -------------------------------------------------------------------------------- /src/input/i2c/SensorBH1750.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorBH1750.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v32 - Added MQTT Support! 15 | v29 - First Public Release 16 | */ 17 | /**************************************************************************/ 18 | 19 | #include 20 | 21 | #ifndef _SensorBH1750_h_ 22 | #define _SensorBH1750_h_ 23 | 24 | #include "../Sensor.h" 25 | #include "thirdparty/BH1750.h" 26 | 27 | class SensorBH1750 : public Sensor { 28 | private: 29 | static BH1750 *bh1750; 30 | float lastPostedValue = NAN; 31 | protected: 32 | Data* read(bool); 33 | void preCycle(int); 34 | boolean smartSensorCheck(float, float, boolean); 35 | public: 36 | SensorBH1750 (long, String, String, String, String, String, int, int, float, SensorCalculation*); 37 | }; 38 | 39 | #endif -------------------------------------------------------------------------------- /src/input/i2c/SensorBME680.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorBME680.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v33 - Changes for Digital Sensor Switch Support 15 | v32 - Added MQTT Support! 16 | v29 - First Public Release 17 | */ 18 | /**************************************************************************/ 19 | 20 | #include "SensorBME680.h" 21 | 22 | extern boolean isResetting; 23 | extern int powerMode; 24 | 25 | Adafruit_BME680* SensorBME680::bme = NULL; 26 | int SensorBME680::lastReadCycleId = 0; 27 | 28 | #define BME_SCK 13 29 | #define BME_MISO 12 30 | #define BME_MOSI 11 31 | #define BME_CS 10 32 | 33 | SensorBME680::SensorBME680 (long id, String category, String shortName, String name, String PortSDA, String PortSCL, int refreshInterval, int postDataInterval, float smartValueThreshold, SensorCalculation* calculation) : Sensor (id, category, shortName, name, refreshInterval, postDataInterval, smartValueThreshold, calculation, false) { 34 | 35 | if(bme == NULL) 36 | { 37 | bme = new Adafruit_BME680(); 38 | 39 | int i=0; 40 | uint8_t addr = 0x76; 41 | 42 | while(!bme->begin(addr)) 43 | { 44 | Serial.println("Trying to find BME680 sensor!"); 45 | delay(500); 46 | 47 | if(i==5) 48 | { 49 | Serial.println("Could not find a valid BME680 sensor, check wiring!"); 50 | bme = NULL; 51 | break; 52 | } 53 | 54 | if(addr==0x76) addr = 0x77; 55 | else addr=0x76; 56 | 57 | i++; 58 | } 59 | 60 | if(bme!=NULL) 61 | { 62 | // Set up oversampling and filter initialization 63 | bme->setTemperatureOversampling(BME680_OS_8X); 64 | bme->setHumidityOversampling(BME680_OS_2X); 65 | bme->setPressureOversampling(BME680_OS_4X); 66 | bme->setIIRFilterSize(BME680_FILTER_SIZE_3); 67 | bme->setGasHeater(320, 500); // 320*C for 500 ms 68 | } 69 | } 70 | } 71 | 72 | void SensorBME680::preCycle(int cycleId) 73 | { 74 | if(lastReadCycleId!=cycleId) 75 | { 76 | if(!isResetting && bme != NULL) 77 | { 78 | if(cycleId==1) 79 | { 80 | Serial.println("Pre heating BME680 sensor..."); 81 | 82 | for(int i=0;i<5;i++) 83 | { 84 | bme->performReading(); 85 | yield(); 86 | // delay(500); 87 | // yield(); 88 | } 89 | 90 | Serial.println("Pre heating done!"); 91 | } 92 | else if (!bme->performReading()) { 93 | Serial.println("Failed to perform reading :("); 94 | } 95 | } 96 | lastReadCycleId = cycleId; 97 | } 98 | } 99 | 100 | Data* SensorBME680::read(bool shouldPostData) 101 | { 102 | if(!isResetting && bme != NULL) 103 | { 104 | if(_calculation->getValueType()=="humidity") 105 | { 106 | float humidity = bme->humidity; 107 | shouldPostData = smartSensorCheck(humidity, _smartValueThreshold, shouldPostData); 108 | return _calculation->calculate(this, humidity, shouldPostData); 109 | } 110 | else if(_calculation->getValueType()=="temperature") 111 | { 112 | float tempC = bme->temperature; 113 | shouldPostData = smartSensorCheck(tempC, _smartValueThreshold, shouldPostData); 114 | return _calculation->calculate(this, tempC, shouldPostData); 115 | } 116 | else if(_calculation->getValueType()=="pressure") 117 | { 118 | float pressure = bme->pressure/100.0; 119 | shouldPostData = smartSensorCheck(pressure, _smartValueThreshold, shouldPostData); 120 | return _calculation->calculate(this, pressure, shouldPostData); 121 | } 122 | else if(_calculation->getValueType()=="resistance") 123 | { 124 | if(_calculation->getValueUnit()=="Ohm") 125 | { 126 | float resistance = bme->gas_resistance; 127 | shouldPostData = smartSensorCheck(resistance, _smartValueThreshold, shouldPostData); 128 | return _calculation->calculate(this, resistance, shouldPostData); 129 | } 130 | else if(_calculation->getValueUnit()=="kOhm") 131 | { 132 | float resistance = bme->gas_resistance/1000.0; 133 | shouldPostData = smartSensorCheck(resistance, _smartValueThreshold, shouldPostData); 134 | return _calculation->calculate(this, resistance, shouldPostData); 135 | } 136 | } 137 | } 138 | 139 | return NULL; 140 | } 141 | 142 | boolean SensorBME680::smartSensorCheck(float currentRawValue, float threshhold, boolean shouldPostData) 143 | { 144 | if(powerMode == 3) 145 | { 146 | if(!shouldPostData) 147 | { 148 | if(!isnan(lastPostedValue)) 149 | { 150 | if(lastPostedValue-currentRawValue>threshhold || lastPostedValue-currentRawValue<-threshhold) 151 | { 152 | shouldPostData = true; 153 | } 154 | } 155 | } 156 | 157 | if(shouldPostData) 158 | lastPostedValue = currentRawValue; 159 | } 160 | 161 | return shouldPostData; 162 | 163 | } -------------------------------------------------------------------------------- /src/input/i2c/SensorBME680.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorBME680.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v32 - Added MQTT Support! 15 | v29 - First Public Release 16 | */ 17 | /**************************************************************************/ 18 | 19 | #include 20 | // #include 21 | 22 | #ifndef _SensorBME680_h_ 23 | #define _SensorBME680_h_ 24 | 25 | #include "../Sensor.h" 26 | 27 | class SensorBME680 : public Sensor { 28 | private: 29 | static Adafruit_BME680* bme; 30 | static int lastReadCycleId; 31 | float lastPostedValue = NAN; 32 | protected: 33 | Data* read(bool); 34 | void preCycle(int); 35 | boolean smartSensorCheck(float, float, boolean); 36 | public: 37 | SensorBME680 (long, String, String, String, String, String, int, int, float, SensorCalculation*); 38 | }; 39 | 40 | #endif -------------------------------------------------------------------------------- /src/input/i2c/SensorBMx280.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorBMx280.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensatio ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensatio Cloud and the Sensatio apps. 8 | 9 | ----> https://www.sensatio.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v45 - Fixed Pressure Measurement for BME280 Sensors 15 | v33 - Changes for Digital Sensor Switch Support 16 | v32 - Added MQTT Support! 17 | v29 - First Public Release 18 | */ 19 | /**************************************************************************/ 20 | 21 | #include "SensorBMx280.h" 22 | #include "Wire.h" 23 | 24 | extern boolean isResetting; 25 | extern int powerMode; 26 | 27 | BME280I2C* SensorBMx280::bme76 = NULL; 28 | BME280I2C* SensorBMx280::bme77 = NULL; 29 | 30 | SensorBMx280::SensorBMx280 (long id, String category, String shortName, String name, String i2cAdress, int refreshInterval, int postDataInterval, float smartValueThreshold, SensorCalculation* calculation) : Sensor (id, category, shortName, name, refreshInterval, postDataInterval, smartValueThreshold, calculation, false) { 31 | 32 | BME280::TempUnit tempUnit(BME280::TempUnit_Celsius); 33 | BME280::PresUnit presUnit(BME280::PresUnit_hPa); 34 | 35 | if(i2cAdress=="0x77") 36 | { 37 | if(bme77 == NULL) 38 | { 39 | BME280I2C::Settings settings( 40 | BME280::OSR_X1, 41 | BME280::OSR_X1, 42 | BME280::OSR_X1, 43 | BME280::Mode_Forced, 44 | BME280::StandbyTime_1000ms, 45 | BME280::Filter_16, 46 | BME280::SpiEnable_False, 47 | BME280I2C::I2CAddr_0x77 48 | ); 49 | bme77 = new BME280I2C(settings); 50 | } 51 | bme = bme77; 52 | } 53 | else 54 | { 55 | if(bme76 == NULL) 56 | { 57 | bme76 = new BME280I2C(); 58 | } 59 | bme = bme76; 60 | } 61 | 62 | int i=0; 63 | 64 | while(!bme->begin()) 65 | { 66 | Serial.println("Trying to find BME280 sensor!"); 67 | delay(500); 68 | 69 | if(i==5) 70 | { 71 | Serial.println("Could not find a valid BME280 sensor, check wiring!"); 72 | bme = NULL; 73 | break; 74 | } 75 | 76 | i++; 77 | } 78 | } 79 | 80 | void SensorBMx280::preCycle(int cycleId) 81 | { 82 | } 83 | 84 | Data* SensorBMx280::read(bool shouldPostData) 85 | { 86 | if(!isResetting && bme != NULL) 87 | { 88 | if(_calculation->getValueType()=="humidity") 89 | { 90 | float humidity = bme->hum(); 91 | shouldPostData = smartSensorCheck(humidity, _smartValueThreshold, shouldPostData); 92 | return _calculation->calculate(this, humidity, shouldPostData); 93 | } 94 | else if(_calculation->getValueType()=="temperature") 95 | { 96 | float tempC = bme->temp(); 97 | shouldPostData = smartSensorCheck(tempC, _smartValueThreshold, shouldPostData); 98 | return _calculation->calculate(this, tempC, shouldPostData); 99 | } 100 | else if(_calculation->getValueType()=="pressure") 101 | { 102 | float pressure = bme->pres(BME280::PresUnit_hPa); 103 | shouldPostData = smartSensorCheck(pressure, _smartValueThreshold, shouldPostData); 104 | return _calculation->calculate(this, pressure, shouldPostData); 105 | } 106 | else if(_calculation->getValueType()=="altitude") 107 | { 108 | float pressure = bme->pres(BME280::PresUnit_hPa); 109 | shouldPostData = smartSensorCheck(pressure, _smartValueThreshold, shouldPostData); 110 | return _calculation->calculate(this, pressure, shouldPostData); 111 | } 112 | } 113 | 114 | return NULL; 115 | } 116 | 117 | boolean SensorBMx280::smartSensorCheck(float currentRawValue, float threshhold, boolean shouldPostData) 118 | { 119 | if(powerMode == 3) 120 | { 121 | if(!shouldPostData) 122 | { 123 | if(!isnan(lastPostedValue)) 124 | { 125 | if(lastPostedValue-currentRawValue>threshhold || lastPostedValue-currentRawValue<-threshhold) 126 | { 127 | shouldPostData = true; 128 | } 129 | } 130 | } 131 | 132 | if(shouldPostData) 133 | lastPostedValue = currentRawValue; 134 | } 135 | 136 | return shouldPostData; 137 | 138 | } 139 | -------------------------------------------------------------------------------- /src/input/i2c/SensorBMx280.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorBMx280.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v45 - Fixed Pressure Measurement for BME280 Sensors 15 | v33 - Changes for Digital Sensor Switch Support 16 | v32 - Added MQTT Support! 17 | v29 - First Public Release 18 | */ 19 | /**************************************************************************/ 20 | 21 | #include 22 | // #include 23 | 24 | #ifndef _SensorBMx280_h_ 25 | #define _SensorBMx280_h_ 26 | 27 | #include "../Sensor.h" 28 | 29 | class SensorBMx280 : public Sensor { 30 | private: 31 | static BME280I2C* bme76; 32 | static BME280I2C* bme77; 33 | BME280I2C* bme; 34 | float lastPostedValue = NAN; 35 | protected: 36 | Data* read(bool); 37 | void preCycle(int); 38 | boolean smartSensorCheck(float, float, boolean); 39 | public: 40 | SensorBMx280 (long, String, String, String, String, int, int, float, SensorCalculation*); 41 | }; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/input/i2c/SensorMax44009.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorMax44009.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v33 - Changes for Digital Sensor Switch Support 15 | v32 - Added MQTT Support! 16 | v29 - First Public Release 17 | */ 18 | /**************************************************************************/ 19 | 20 | #include "SensorMax44009.h" 21 | 22 | extern boolean isResetting; 23 | extern int powerMode; 24 | 25 | MAX44009* SensorMax44009::max44009; 26 | 27 | SensorMax44009::SensorMax44009 (long id, String category, String shortName, String name, String PortSDA, String PortSCL, int refreshInterval, int postDataInterval, float smartValueThreshold, SensorCalculation* calculation) : Sensor (id, category, shortName, name, refreshInterval, postDataInterval, smartValueThreshold, calculation, false) { 28 | 29 | int i=0; 30 | failedInit = false; 31 | 32 | while(max44009->begin()) 33 | { 34 | Serial.println("Trying to find MAX44009 sensor!"); 35 | delay(500); 36 | 37 | if(i==5) 38 | { 39 | Serial.println("Could not find a valid MAX44009 sensor, check wiring!"); 40 | failedInit=true; 41 | break; 42 | } 43 | 44 | i++; 45 | } 46 | } 47 | 48 | void SensorMax44009::preCycle(int cycleId) 49 | { 50 | } 51 | 52 | Data* SensorMax44009::read(bool shouldPostData) 53 | { 54 | if(!isResetting && !failedInit) 55 | { 56 | if(_calculation->getValueType()=="illuminance") 57 | { 58 | float illuminance = max44009->get_lux(); 59 | shouldPostData = smartSensorCheck(illuminance, _smartValueThreshold, shouldPostData); 60 | return _calculation->calculate(this, illuminance, shouldPostData); 61 | } 62 | } 63 | return NULL; 64 | } 65 | 66 | boolean SensorMax44009::smartSensorCheck(float currentRawValue, float threshhold, boolean shouldPostData) 67 | { 68 | if(powerMode == 3) 69 | { 70 | if(!shouldPostData) 71 | { 72 | if(!isnan(lastPostedValue)) 73 | { 74 | if(lastPostedValue-currentRawValue>threshhold || lastPostedValue-currentRawValue<-threshhold) 75 | { 76 | shouldPostData = true; 77 | } 78 | } 79 | } 80 | 81 | if(shouldPostData) 82 | lastPostedValue = currentRawValue; 83 | } 84 | 85 | return shouldPostData; 86 | 87 | } -------------------------------------------------------------------------------- /src/input/i2c/SensorMax44009.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorMax44009.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v32 - Added MQTT Support! 15 | v29 - First Public Release 16 | */ 17 | /**************************************************************************/ 18 | 19 | #include 20 | #include 21 | 22 | #ifndef _SensorMax44009_h_ 23 | #define _SensorMax44009_h_ 24 | 25 | #include "../Sensor.h" 26 | 27 | class SensorMax44009 : public Sensor { 28 | private: 29 | static MAX44009 *max44009; 30 | boolean failedInit; 31 | float lastPostedValue = NAN; 32 | protected: 33 | Data* read(bool); 34 | void preCycle(int); 35 | boolean smartSensorCheck(float, float, boolean); 36 | public: 37 | SensorMax44009 (long, String, String, String, String, String, int, int, float, SensorCalculation*); 38 | }; 39 | 40 | #endif -------------------------------------------------------------------------------- /src/input/i2c/SensorSI1145.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorSI1145.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v39 - ReAdded Support for VEML6075 and SI1145 UVI Sensors, added auto-reinit if sensor fails 15 | v35 - Added Support for VEML6075 and SI1145 UVI Sensors 16 | */ 17 | /**************************************************************************/ 18 | 19 | #include "SensorSI1145.h" 20 | 21 | extern boolean isResetting; 22 | extern int powerMode; 23 | 24 | // Adafruit_SI1145* SensorSI1145::si1145; 25 | SI1145_WE* SensorSI1145::si1145; 26 | int SensorSI1145::lastCycleId = -1; 27 | boolean SensorSI1145::failedInit = true; 28 | 29 | SensorSI1145::SensorSI1145 (long id, String category, String shortName, String name, String PortSDA, String PortSCL, int refreshInterval, int postDataInterval, float smartValueThreshold, SensorCalculation* calculation) : Sensor (id, category, shortName, name, refreshInterval, postDataInterval, smartValueThreshold, calculation, false) { 30 | 31 | if(si1145==NULL) 32 | si1145 = new SI1145_WE(); 33 | 34 | } 35 | 36 | void SensorSI1145::preCycle(int cycleId) 37 | { 38 | if(cycleId!=lastCycleId) 39 | { 40 | if(failedInit) 41 | { 42 | if(lastCycleId!=-1) 43 | Serial.println("Trying to re-init SI1145..."); 44 | si1145->init(); 45 | si1145->enableHighSignalVisRange(); // Gain divided by 14.5 46 | si1145->enableHighSignalIrRange(); // Gain divided by 14.5 47 | si1145->enableMeasurements(PSALSUV_TYPE, AUTO); 48 | failedInit=false; 49 | } 50 | lastCycleId=cycleId; 51 | } 52 | 53 | } 54 | 55 | Data* SensorSI1145::read(bool shouldPostData) 56 | { 57 | if(!isResetting && !failedInit) 58 | { 59 | if(_calculation->getValueType()=="a") 60 | { 61 | float visLight = si1145->getAlsVisData(); 62 | 63 | if (visLight==65535.0) { 64 | Serial.println("NAN VisLight!"); 65 | failedInit=true; 66 | } 67 | else { 68 | shouldPostData = smartSensorCheck(visLight, _smartValueThreshold, shouldPostData); 69 | return _calculation->calculate(this, visLight, shouldPostData); 70 | } 71 | } 72 | else if(_calculation->getValueType()=="b") 73 | { 74 | float irLight = si1145->getAlsIrData(); 75 | 76 | if (irLight==65535.0f) { 77 | Serial.println("NAN IrLight!"); 78 | failedInit=true; 79 | } 80 | else { 81 | shouldPostData = smartSensorCheck(irLight, _smartValueThreshold, shouldPostData); 82 | return _calculation->calculate(this, irLight, shouldPostData); 83 | } 84 | } 85 | else if(_calculation->getValueType()=="c") 86 | { 87 | float prox = si1145->getPsData(); 88 | 89 | if (prox==65535.0f) { 90 | Serial.println("NAN Proximiy!"); 91 | failedInit=true; 92 | } 93 | else { 94 | shouldPostData = smartSensorCheck(prox, _smartValueThreshold, shouldPostData); 95 | return _calculation->calculate(this, prox, shouldPostData); 96 | } 97 | } 98 | else if(_calculation->getValueType()=="raw") 99 | { 100 | float index = si1145->getUvIndex(); 101 | 102 | if (index==655.35f) { 103 | Serial.println("NAN UV-Index!"); 104 | failedInit=true; 105 | } 106 | else { 107 | shouldPostData = smartSensorCheck(index, _smartValueThreshold, shouldPostData); 108 | return _calculation->calculate(this, index, shouldPostData); 109 | } 110 | } 111 | } 112 | return NULL; 113 | } 114 | 115 | boolean SensorSI1145::smartSensorCheck(float currentRawValue, float threshhold, boolean shouldPostData) 116 | { 117 | if(powerMode == 3) 118 | { 119 | if(!shouldPostData) 120 | { 121 | if(!isnan(lastPostedValue)) 122 | { 123 | if(lastPostedValue-currentRawValue>threshhold || lastPostedValue-currentRawValue<-threshhold) 124 | { 125 | shouldPostData = true; 126 | } 127 | } 128 | } 129 | 130 | if(shouldPostData) 131 | lastPostedValue = currentRawValue; 132 | } 133 | 134 | return shouldPostData; 135 | 136 | } -------------------------------------------------------------------------------- /src/input/i2c/SensorSI1145.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorSI1145.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v39 - ReAdded Support for VEML6075 and SI1145 UVI Sensors, added auto-reinit if sensor fails 15 | v35 - Added Support for VEML6075 and SI1145 UVI Sensors 16 | */ 17 | /**************************************************************************/ 18 | 19 | #ifndef _SensorSI1145_h_ 20 | #define _SensorSI1145_h_ 21 | 22 | #include "../Sensor.h" 23 | // #include 24 | #include 25 | 26 | class SensorSI1145 : public Sensor { 27 | private: 28 | static SI1145_WE *si1145; 29 | static boolean failedInit; 30 | static int lastCycleId; 31 | float lastPostedValue = NAN; 32 | protected: 33 | Data* read(bool); 34 | void preCycle(int); 35 | boolean smartSensorCheck(float, float, boolean); 36 | float calcLux(uint16_t vis, uint16_t ir); 37 | public: 38 | SensorSI1145 (long, String, String, String, String, String, int, int, float, SensorCalculation*); 39 | }; 40 | 41 | #endif -------------------------------------------------------------------------------- /src/input/i2c/SensorVEML6075.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorVEML6075.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v39 - ReAdded Support for VEML6075 and SI1145 UVI Sensors, added auto-reinit if sensor fails 15 | v35 - Added Support for VEML6075 and SI1145 UVI Sensors 16 | */ 17 | /**************************************************************************/ 18 | 19 | #include "SensorVEML6075.h" 20 | 21 | extern boolean isResetting; 22 | extern int powerMode; 23 | 24 | int SensorVEML6075::lastCycleId = -1; 25 | boolean SensorVEML6075::failedInit = true; 26 | 27 | Adafruit_VEML6075* SensorVEML6075::veml6075; 28 | 29 | SensorVEML6075::SensorVEML6075 (long id, String category, String shortName, String name, String PortSDA, String PortSCL, int refreshInterval, int postDataInterval, float smartValueThreshold, SensorCalculation* calculation) : Sensor (id, category, shortName, name, refreshInterval, postDataInterval, smartValueThreshold, calculation, false) { 30 | 31 | int i=0; 32 | 33 | if(veml6075==NULL) 34 | veml6075 = new Adafruit_VEML6075(); 35 | 36 | } 37 | 38 | void SensorVEML6075::preCycle(int cycleId) 39 | { 40 | if(cycleId!=lastCycleId) 41 | { 42 | if(failedInit) 43 | { 44 | failedInit = false; 45 | 46 | int i=0; 47 | if(lastCycleId!=-1) 48 | Serial.println("Trying to re-init VEML6075..."); 49 | while(!veml6075->begin()) 50 | { 51 | delay(500); 52 | if(i==5) 53 | { 54 | Serial.println("Could not find a valid VEML6075 sensor, check wiring!"); 55 | failedInit=true; 56 | break; 57 | } 58 | 59 | i++; 60 | } 61 | 62 | if(!failedInit) 63 | { 64 | veml6075->setIntegrationTime(VEML6075_100MS); 65 | veml6075->setHighDynamic(true); 66 | veml6075->setForcedMode(false); 67 | veml6075->setCoefficients(2.22, 1.33, // UVA_A and UVA_B coefficients 68 | 2.95, 1.74, // UVB_C and UVB_D coefficients 69 | 0.001461, 0.002591); // UVA and UVB responses 70 | } 71 | 72 | } 73 | lastCycleId=cycleId; 74 | } 75 | } 76 | 77 | Data* SensorVEML6075::read(bool shouldPostData) 78 | { 79 | if(!isResetting && !failedInit) 80 | { 81 | if(_calculation->getValueType()=="a") 82 | { 83 | float irradiance_a = veml6075->readUVA(); 84 | if(irradiance_a>=-1000) { 85 | shouldPostData = smartSensorCheck(irradiance_a, _smartValueThreshold, shouldPostData); 86 | return _calculation->calculate(this, irradiance_a, shouldPostData); 87 | } 88 | else 89 | { 90 | Serial.println("NAN UV-A!"); 91 | failedInit=true; 92 | } 93 | } 94 | else if(_calculation->getValueType()=="b") 95 | { 96 | float irradiance_b = veml6075->readUVB(); 97 | if(irradiance_b>=-1000) { 98 | shouldPostData = smartSensorCheck(irradiance_b, _smartValueThreshold, shouldPostData); 99 | return _calculation->calculate(this, irradiance_b, shouldPostData); 100 | } 101 | else 102 | { 103 | Serial.println("NAN UV-B!"); 104 | failedInit=true; 105 | } 106 | } 107 | else if(_calculation->getValueType()=="raw") 108 | { 109 | float index = veml6075->readUVI(); 110 | if(index>=-1000) { 111 | shouldPostData = smartSensorCheck(index, _smartValueThreshold, shouldPostData); 112 | return _calculation->calculate(this, index, shouldPostData); 113 | } 114 | else 115 | { 116 | Serial.println("NAN UV-Index!"); 117 | failedInit=true; 118 | } 119 | 120 | } 121 | } 122 | return NULL; 123 | } 124 | 125 | boolean SensorVEML6075::smartSensorCheck(float currentRawValue, float threshhold, boolean shouldPostData) 126 | { 127 | if(powerMode == 3) 128 | { 129 | if(!shouldPostData) 130 | { 131 | if(!isnan(lastPostedValue)) 132 | { 133 | if(lastPostedValue-currentRawValue>threshhold || lastPostedValue-currentRawValue<-threshhold) 134 | { 135 | shouldPostData = true; 136 | } 137 | } 138 | } 139 | 140 | if(shouldPostData) 141 | lastPostedValue = currentRawValue; 142 | } 143 | 144 | return shouldPostData; 145 | 146 | } -------------------------------------------------------------------------------- /src/input/i2c/SensorVEML6075.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorVEML6075.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v39 - ReAdded Support for VEML6075 and SI1145 UVI Sensors, added auto-reinit if sensor fails 15 | v35 - Added Support for VEML6075 and SI1145 UVI Sensors 16 | */ 17 | /**************************************************************************/ 18 | 19 | #ifndef _SensorVEML6075_h_ 20 | #define _SensorVEML6075_h_ 21 | 22 | #include "../Sensor.h" 23 | #include 24 | 25 | class SensorVEML6075 : public Sensor { 26 | private: 27 | static Adafruit_VEML6075 *veml6075; 28 | static boolean failedInit; 29 | static int lastCycleId; 30 | float lastPostedValue = NAN; 31 | protected: 32 | Data* read(bool); 33 | void preCycle(int); 34 | boolean smartSensorCheck(float, float, boolean); 35 | public: 36 | SensorVEML6075 (long, String, String, String, String, String, int, int, float, SensorCalculation*); 37 | }; 38 | 39 | #endif -------------------------------------------------------------------------------- /src/input/i2c/thirdparty/Adafruit_ADS1015.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Adafruit_ADS1015.h 4 | @author K. Townsend (Adafruit Industries) 5 | @license BSD (see license.txt) 6 | This is a library for the Adafruit ADS1015 breakout board 7 | ----> https://www.adafruit.com/products/??? 8 | Adafruit invests time and resources providing this open source code, 9 | please support Adafruit and open-source hardware by purchasing 10 | products from Adafruit! 11 | @section HISTORY 12 | v1.0 - First release 13 | v1.1 - Added ADS1115 support - W. Earl 14 | v1.2 - Modified by Dennis Cabell. See details in ccp file. 15 | */ 16 | /**************************************************************************/ 17 | 18 | #ifndef _ADAFRUIT_ADS1X15_H 19 | #define _ADAFRUIT_ADS1X15_H 20 | 21 | #if ARDUINO >= 100 22 | #include "Arduino.h" 23 | #else 24 | #include "WProgram.h" 25 | #endif 26 | 27 | #include 28 | 29 | /*========================================================================= 30 | I2C ADDRESS/BITS 31 | -----------------------------------------------------------------------*/ 32 | #define ADS1X15_ADDRESS (0x48) // 1001 000 (ADDR = GND) 33 | /*=========================================================================*/ 34 | 35 | /*========================================================================= 36 | Default thresholds for comparator 37 | -----------------------------------------------------------------------*/ 38 | #define ADS1X15_LOW_THRESHOLD_DEFAULT (0x8000) 39 | #define ADS1X15_HIGH_THRESHOLD_DEFAULT (0x7FFF) 40 | /*=========================================================================*/ 41 | 42 | /*========================================================================= 43 | POINTER REGISTER 44 | -----------------------------------------------------------------------*/ 45 | #define ADS1X15_REG_POINTER_MASK (0x03) 46 | #define ADS1X15_REG_POINTER_CONVERT (0x00) 47 | #define ADS1X15_REG_POINTER_CONFIG (0x01) 48 | #define ADS1X15_REG_POINTER_LOWTHRESH (0x02) 49 | #define ADS1X15_REG_POINTER_HITHRESH (0x03) 50 | /*=========================================================================*/ 51 | 52 | /*========================================================================= 53 | CONFIG REGISTER 54 | -----------------------------------------------------------------------*/ 55 | #define ADS1X15_REG_CONFIG_OS_MASK (0x8000) 56 | #define ADS1X15_REG_CONFIG_OS_SINGLE (0x8000) // Write: Set to start a single-conversion 57 | #define ADS1X15_REG_CONFIG_OS_BUSY (0x0000) // Read: Bit = 0 when conversion is in progress 58 | #define ADS1X15_REG_CONFIG_OS_NOTBUSY (0x8000) // Read: Bit = 1 when device is not performing a conversion 59 | 60 | #define ADS1X15_REG_CONFIG_MUX_MASK (0x7000) 61 | #define ADS1X15_REG_CONFIG_MUX_DIFF_0_1 (0x0000) // Differential P = AIN0, N = AIN1 (default) 62 | #define ADS1X15_REG_CONFIG_MUX_DIFF_0_3 (0x1000) // Differential P = AIN0, N = AIN3 63 | #define ADS1X15_REG_CONFIG_MUX_DIFF_1_3 (0x2000) // Differential P = AIN1, N = AIN3 64 | #define ADS1X15_REG_CONFIG_MUX_DIFF_2_3 (0x3000) // Differential P = AIN2, N = AIN3 65 | #define ADS1X15_REG_CONFIG_MUX_SINGLE_0 (0x4000) // Single-ended AIN0 66 | #define ADS1X15_REG_CONFIG_MUX_SINGLE_1 (0x5000) // Single-ended AIN1 67 | #define ADS1X15_REG_CONFIG_MUX_SINGLE_2 (0x6000) // Single-ended AIN2 68 | #define ADS1X15_REG_CONFIG_MUX_SINGLE_3 (0x7000) // Single-ended AIN3 69 | 70 | #define ADS1X15_REG_CONFIG_PGA_MASK (0x0E00) 71 | #define ADS1X15_REG_CONFIG_PGA_6_144V (0x0000) // +/-6.144V range = Gain 2/3 72 | #define ADS1X15_REG_CONFIG_PGA_4_096V (0x0200) // +/-4.096V range = Gain 1 73 | #define ADS1X15_REG_CONFIG_PGA_2_048V (0x0400) // +/-2.048V range = Gain 2 (default) 74 | #define ADS1X15_REG_CONFIG_PGA_1_024V (0x0600) // +/-1.024V range = Gain 4 75 | #define ADS1X15_REG_CONFIG_PGA_0_512V (0x0800) // +/-0.512V range = Gain 8 76 | #define ADS1X15_REG_CONFIG_PGA_0_256V (0x0A00) // +/-0.256V range = Gain 16 77 | 78 | #define ADS1X15_REG_CONFIG_MODE_MASK (0x0100) 79 | #define ADS1X15_REG_CONFIG_MODE_CONTIN (0x0000) // Continuous conversion mode 80 | #define ADS1X15_REG_CONFIG_MODE_SINGLE (0x0100) // Power-down single-shot mode (default) 81 | 82 | #define ADS1015_REG_CONFIG_DR_MASK (0x00E0) 83 | #define ADS1015_REG_CONFIG_DR_128SPS (0x0000) // 128 samples per second 84 | #define ADS1015_REG_CONFIG_DR_250SPS (0x0020) // 250 samples per second 85 | #define ADS1015_REG_CONFIG_DR_490SPS (0x0040) // 490 samples per second 86 | #define ADS1015_REG_CONFIG_DR_920SPS (0x0060) // 920 samples per second 87 | #define ADS1015_REG_CONFIG_DR_1600SPS (0x0080) // 1600 samples per second (default) 88 | #define ADS1015_REG_CONFIG_DR_2400SPS (0x00A0) // 2400 samples per second 89 | #define ADS1015_REG_CONFIG_DR_3300SPS (0x00C0) // 3300 samples per second 90 | 91 | #define ADS1115_REG_CONFIG_DR_8SPS (0x0000) // 8 samples per second 92 | #define ADS1115_REG_CONFIG_DR_16SPS (0x0020) // 16 samples per second 93 | #define ADS1115_REG_CONFIG_DR_32SPS (0x0040) // 32 samples per second 94 | #define ADS1115_REG_CONFIG_DR_64SPS (0x0060) // 64 samples per second 95 | #define ADS1115_REG_CONFIG_DR_128SPS (0x0080) // 128 samples per second (default) 96 | #define ADS1115_REG_CONFIG_DR_250SPS (0x00A0) // 250 samples per second 97 | #define ADS1115_REG_CONFIG_DR_475SPS (0x00C0) // 475 samples per second 98 | #define ADS1115_REG_CONFIG_DR_860SPS (0x00E0) // 860 samples per second 99 | 100 | #define ADS1X15_REG_CONFIG_CMODE_MASK (0x0010) 101 | #define ADS1X15_REG_CONFIG_CMODE_TRAD (0x0000) // Traditional comparator with hysteresis (default) 102 | #define ADS1X15_REG_CONFIG_CMODE_WINDOW (0x0010) // Window comparator 103 | 104 | #define ADS1X15_REG_CONFIG_CPOL_MASK (0x0008) 105 | #define ADS1X15_REG_CONFIG_CPOL_ACTVLOW (0x0000) // ALERT/RDY pin is low when active (default) 106 | #define ADS1X15_REG_CONFIG_CPOL_ACTVHI (0x0008) // ALERT/RDY pin is high when active 107 | 108 | #define ADS1X15_REG_CONFIG_CLAT_MASK (0x0004) // Determines if ALERT/RDY pin latches once asserted 109 | #define ADS1X15_REG_CONFIG_CLAT_NONLAT (0x0000) // Non-latching comparator (default) 110 | #define ADS1X15_REG_CONFIG_CLAT_LATCH (0x0004) // Latching comparator 111 | 112 | #define ADS1X15_REG_CONFIG_CQUE_MASK (0x0003) 113 | #define ADS1X15_REG_CONFIG_CQUE_1CONV (0x0000) // Assert ALERT/RDY after one conversions 114 | #define ADS1X15_REG_CONFIG_CQUE_2CONV (0x0001) // Assert ALERT/RDY after two conversions 115 | #define ADS1X15_REG_CONFIG_CQUE_4CONV (0x0002) // Assert ALERT/RDY after four conversions 116 | #define ADS1X15_REG_CONFIG_CQUE_NONE (0x0003) // Disable the comparator and put ALERT/RDY in high state (default) 117 | /*=========================================================================*/ 118 | 119 | /*========================================================================= 120 | GAIN VOLTAGES 121 | -----------------------------------------------------------------------*/ 122 | #define ADS1115_VOLTS_PER_BIT_GAIN_TWOTHIRDS 0.0001875F 123 | #define ADS1115_VOLTS_PER_BIT_GAIN_ONE 0.000125F 124 | #define ADS1115_VOLTS_PER_BIT_GAIN_TWO 0.0000625F 125 | #define ADS1115_VOLTS_PER_BIT_GAIN_FOUR 0.00003125F 126 | #define ADS1115_VOLTS_PER_BIT_GAIN_EIGHT 0.000015625F 127 | #define ADS1115_VOLTS_PER_BIT_GAIN_SIXTEEN 0.0000078125F 128 | 129 | #define ADS1015_VOLTS_PER_BIT_GAIN_TWOTHIRDS 0.003F 130 | #define ADS1015_VOLTS_PER_BIT_GAIN_ONE 0.002F 131 | #define ADS1015_VOLTS_PER_BIT_GAIN_TWO 0.001F 132 | #define ADS1015_VOLTS_PER_BIT_GAIN_FOUR 0.0005F 133 | #define ADS1015_VOLTS_PER_BIT_GAIN_EIGHT 0.00025F 134 | #define ADS1015_VOLTS_PER_BIT_GAIN_SIXTEEN 0.000125F 135 | /*=========================================================================*/ 136 | 137 | /*========================================================================= 138 | CHIP BASED BIT SHIFT 139 | -----------------------------------------------------------------------*/ 140 | #define ADS1015_CONV_REG_BIT_SHIFT_4 4 141 | #define ADS1115_CONV_REG_BIT_SHIFT_0 0 142 | 143 | /*=========================================================================*/ 144 | 145 | typedef enum : uint16_t 146 | { 147 | DIFF_MUX_0_1 = ADS1X15_REG_CONFIG_MUX_DIFF_0_1, 148 | DIFF_MUX_0_3 = ADS1X15_REG_CONFIG_MUX_DIFF_0_3, 149 | DIFF_MUX_1_3 = ADS1X15_REG_CONFIG_MUX_DIFF_1_3, 150 | DIFF_MUX_2_3 = ADS1X15_REG_CONFIG_MUX_DIFF_2_3 151 | } adsDiffMux_t; 152 | 153 | typedef enum : uint16_t 154 | { 155 | GAIN_TWOTHIRDS = ADS1X15_REG_CONFIG_PGA_6_144V, 156 | GAIN_ONE = ADS1X15_REG_CONFIG_PGA_4_096V, 157 | GAIN_TWO = ADS1X15_REG_CONFIG_PGA_2_048V, 158 | GAIN_FOUR = ADS1X15_REG_CONFIG_PGA_1_024V, 159 | GAIN_EIGHT = ADS1X15_REG_CONFIG_PGA_0_512V, 160 | GAIN_SIXTEEN = ADS1X15_REG_CONFIG_PGA_0_256V, 161 | GAIN_DEFAULT = ADS1X15_REG_CONFIG_PGA_6_144V 162 | } adsGain_t; 163 | 164 | typedef enum : uint16_t 165 | { 166 | ADS1015_DR_128SPS = ADS1015_REG_CONFIG_DR_128SPS, 167 | ADS1015_DR_250SPS = ADS1015_REG_CONFIG_DR_250SPS, 168 | ADS1015_DR_490SPS = ADS1015_REG_CONFIG_DR_490SPS, 169 | ADS1015_DR_920SPS = ADS1015_REG_CONFIG_DR_920SPS, 170 | ADS1015_DR_1600SPS = ADS1015_REG_CONFIG_DR_1600SPS, // default for ADS1015 171 | ADS1015_DR_2400SPS = ADS1015_REG_CONFIG_DR_2400SPS, 172 | ADS1015_DR_3300SPS = ADS1015_REG_CONFIG_DR_3300SPS, 173 | 174 | ADS1115_DR_8SPS = ADS1115_REG_CONFIG_DR_8SPS, 175 | ADS1115_DR_16SPS = ADS1115_REG_CONFIG_DR_16SPS, 176 | ADS1115_DR_32SPS = ADS1115_REG_CONFIG_DR_32SPS, 177 | ADS1115_DR_64SPS = ADS1115_REG_CONFIG_DR_64SPS, 178 | ADS1115_DR_128SPS = ADS1115_REG_CONFIG_DR_128SPS, // default for ADS1115 179 | ADS1115_DR_250SPS = ADS1115_REG_CONFIG_DR_250SPS, 180 | ADS1115_DR_475SPS = ADS1115_REG_CONFIG_DR_475SPS, 181 | ADS1115_DR_860SPS = ADS1115_REG_CONFIG_DR_860SPS, 182 | 183 | DR_DEFAULT_SPS = (0x0080) // 1600 for ADS1015, 128 for ADS1115 184 | } adsSPS_t; 185 | 186 | class Adafruit_ADS1015 187 | { 188 | protected: 189 | // Instance-specific properties 190 | uint8_t m_i2cAddress; 191 | uint8_t m_bitShift; 192 | adsGain_t m_gain = GAIN_DEFAULT; /* +/- 6.144V range (limited to VDD +0.3V max!) */ 193 | adsSPS_t m_SPS = DR_DEFAULT_SPS; 194 | 195 | public: 196 | Adafruit_ADS1015(uint8_t i2cAddress = ADS1X15_ADDRESS); 197 | void begin(void); 198 | #if defined(ARDUINO_ARCH_ESP8266) 199 | void begin(uint8_t sda, uint8_t scl); 200 | #endif 201 | int16_t readADC_SingleEnded(uint8_t channel); 202 | int16_t readADC_Differential(adsDiffMux_t); 203 | int16_t readADC_Differential_0_1(void); 204 | int16_t readADC_Differential_0_3(void); 205 | int16_t readADC_Differential_1_3(void); 206 | int16_t readADC_Differential_2_3(void); 207 | void startComparator_SingleEnded(uint8_t channel, int16_t highThreshold); 208 | void startWindowComparator_SingleEnded(uint8_t channel, int16_t lowThreshold, int16_t highThreshold); 209 | void startContinuous_SingleEnded(uint8_t channel); 210 | void startContinuous_Differential(adsDiffMux_t); 211 | int16_t getLastConversionResults(void); 212 | void setGain(adsGain_t gain); 213 | adsGain_t getGain(void); 214 | void setSPS(adsSPS_t gain); 215 | adsSPS_t getSPS(void); 216 | float voltsPerBit(void); 217 | float readADC_SingleEnded_V(uint8_t); 218 | float readADC_Differential_0_1_V(void); 219 | float readADC_Differential_0_3_V(void); 220 | float readADC_Differential_1_3_V(void); 221 | float readADC_Differential_2_3_V(void); 222 | void startContinuous_Differential_0_1(void); 223 | void startContinuous_Differential_0_3(void); 224 | void startContinuous_Differential_1_3(void); 225 | void startContinuous_Differential_2_3(void); 226 | void waitForConversion(); 227 | 228 | private: 229 | 230 | }; 231 | 232 | // Derive from ADS1105 & override construction to set properties 233 | class Adafruit_ADS1115 : public Adafruit_ADS1015 234 | { 235 | public: 236 | Adafruit_ADS1115(uint8_t i2cAddress = ADS1X15_ADDRESS); 237 | 238 | private: 239 | }; 240 | #endif -------------------------------------------------------------------------------- /src/input/i2c/thirdparty/BH1750.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This is a library for the BH1750FVI Digital Light Sensor breakout board. 3 | The BH1750 board uses I2C for communication. Two pins are required to 4 | interface to the device. Configuring the I2C bus is expected to be done 5 | in user code. The BH1750 library doesn't do this automatically. 6 | Written by Christopher Laws, March, 2013. 7 | 8 | SOURCE: https://github.com/claws/BH1750 9 | */ 10 | 11 | #include "BH1750.h" 12 | 13 | // Define milliseconds delay for ESP8266 platform 14 | #if defined(ESP8266) 15 | 16 | #include 17 | #define _delay_ms(ms) delayMicroseconds((ms) * 1000) 18 | 19 | // Use _delay_ms from utils for AVR-based platforms 20 | #elif defined(__avr__) 21 | #include 22 | 23 | // Use Wiring's delay for compability with another platforms 24 | #else 25 | #define _delay_ms(ms) delay(ms) 26 | #endif 27 | 28 | 29 | // Legacy Wire.write() function fix 30 | #if (ARDUINO >= 100) 31 | #define __wire_write(d) Wire.write(d) 32 | #else 33 | #define __wire_write(d) Wire.send(d) 34 | #endif 35 | 36 | 37 | // Legacy Wire.read() function fix 38 | #if (ARDUINO >= 100) 39 | #define __wire_read() Wire.read() 40 | #else 41 | #define __wire_read() Wire.receive() 42 | #endif 43 | 44 | 45 | /** 46 | * Constructor 47 | * @params addr Sensor address (0x76 or 0x72, see datasheet) 48 | * 49 | * On most sensor boards, it was 0x76 50 | */ 51 | BH1750::BH1750(byte addr) { 52 | 53 | BH1750_I2CADDR = addr; 54 | 55 | } 56 | 57 | 58 | /** 59 | * Configure sensor 60 | * @param mode Measurement mode 61 | */ 62 | bool BH1750::begin(Mode mode) { 63 | 64 | // I2C is expected to be initialized outside this library 65 | 66 | // Configure sensor in specified mode 67 | return configure(mode); 68 | 69 | } 70 | 71 | 72 | /** 73 | * Configure BH1750 with specified mode 74 | * @param mode Measurement mode 75 | */ 76 | bool BH1750::configure(Mode mode) { 77 | 78 | // default transmission result to a value out of normal range 79 | byte ack = 5; 80 | 81 | // Check measurement mode is valid 82 | switch (mode) { 83 | 84 | case BH1750::CONTINUOUS_HIGH_RES_MODE: 85 | case BH1750::CONTINUOUS_HIGH_RES_MODE_2: 86 | case BH1750::CONTINUOUS_LOW_RES_MODE: 87 | case BH1750::ONE_TIME_HIGH_RES_MODE: 88 | case BH1750::ONE_TIME_HIGH_RES_MODE_2: 89 | case BH1750::ONE_TIME_LOW_RES_MODE: 90 | 91 | // Send mode to sensor 92 | Wire.beginTransmission(BH1750_I2CADDR); 93 | __wire_write((uint8_t)BH1750_MODE); 94 | ack = Wire.endTransmission(); 95 | 96 | // Wait a few moments to wake up 97 | _delay_ms(10); 98 | break; 99 | 100 | default: 101 | // Invalid measurement mode 102 | Serial.println(F("[BH1750] ERROR: Invalid mode")); 103 | break; 104 | 105 | } 106 | 107 | // Check result code 108 | switch (ack) { 109 | case 0: 110 | BH1750_MODE = mode; 111 | return true; 112 | case 1: // too long for transmit buffer 113 | Serial.println(F("[BH1750] ERROR: too long for transmit buffer")); 114 | break; 115 | case 2: // received NACK on transmit of address 116 | Serial.println(F("[BH1750] ERROR: received NACK on transmit of address")); 117 | break; 118 | case 3: // received NACK on transmit of data 119 | Serial.println(F("[BH1750] ERROR: received NACK on transmit of data")); 120 | break; 121 | case 4: // other error 122 | Serial.println(F("[BH1750] ERROR: other error")); 123 | break; 124 | default: 125 | Serial.println(F("[BH1750] ERROR: undefined error")); 126 | break; 127 | } 128 | 129 | return false; 130 | 131 | } 132 | 133 | /** 134 | * Configure BH1750 MTreg value 135 | * MT reg = Measurement Time register 136 | * @param MTreg a value between 32 and 254. Default: 69 137 | * @return bool true if MTReg successful set 138 | * false if MTreg not changed or parameter out of range 139 | */ 140 | bool BH1750::setMTreg(byte MTreg) { 141 | //Bug: lowest value seems to be 32! 142 | if (MTreg <= 31 || MTreg > 254) { 143 | Serial.println(F("[BH1750] ERROR: MTreg out of range")); 144 | return false; 145 | } 146 | byte ack = 5; 147 | // Send MTreg and the current mode to the sensor 148 | // High bit: 01000_MT[7,6,5] 149 | // Low bit: 011_MT[4,3,2,1,0] 150 | Wire.beginTransmission(BH1750_I2CADDR); 151 | __wire_write((0b01000 << 3) | (MTreg >> 5)); 152 | ack = Wire.endTransmission(); 153 | Wire.beginTransmission(BH1750_I2CADDR); 154 | __wire_write((0b011 << 5 ) | (MTreg & 0b11111)); 155 | ack = ack | Wire.endTransmission(); 156 | Wire.beginTransmission(BH1750_I2CADDR); 157 | __wire_write(BH1750_MODE); 158 | ack = ack | Wire.endTransmission(); 159 | 160 | // Wait a few moments to wake up 161 | _delay_ms(10); 162 | 163 | // Check result code 164 | switch (ack) { 165 | case 0: 166 | BH1750_MTreg = MTreg; 167 | // Delay for specific continuous mode to get valid values 168 | switch (BH1750_MODE) { 169 | case BH1750::CONTINUOUS_LOW_RES_MODE: 170 | _delay_ms(24 * BH1750_MTreg/(byte)BH1750_DEFAULT_MTREG); 171 | break; 172 | case BH1750::CONTINUOUS_HIGH_RES_MODE: 173 | case BH1750::CONTINUOUS_HIGH_RES_MODE_2: 174 | _delay_ms(180 * BH1750_MTreg/(byte)BH1750_DEFAULT_MTREG); 175 | break; 176 | default: 177 | break; 178 | } 179 | return true; 180 | case 1: // too long for transmit buffer 181 | Serial.println(F("[BH1750] ERROR: too long for transmit buffer")); 182 | break; 183 | case 2: // received NACK on transmit of address 184 | Serial.println(F("[BH1750] ERROR: received NACK on transmit of address")); 185 | break; 186 | case 3: // received NACK on transmit of data 187 | Serial.println(F("[BH1750] ERROR: received NACK on transmit of data")); 188 | break; 189 | case 4: // other error 190 | Serial.println(F("[BH1750] ERROR: other error")); 191 | break; 192 | default: 193 | Serial.println(F("[BH1750] ERROR: undefined error")); 194 | break; 195 | } 196 | 197 | return false; 198 | } 199 | 200 | /** 201 | * Read light level from sensor 202 | * The return value range differs if the MTreg value is changed. The global 203 | * maximum value is noted in the square brackets. 204 | * @return Light level in lux (0.0 ~ 54612,5 [117758,203]) 205 | * -1 : no valid return value 206 | * -2 : sensor not configured 207 | */ 208 | float BH1750::readLightLevel(bool maxWait) { 209 | 210 | if (BH1750_MODE == UNCONFIGURED) { 211 | Serial.println(F("[BH1750] Device is not configured!")); 212 | return -2.0; 213 | } 214 | 215 | // Measurement result will be stored here 216 | float level = -1.0; 217 | 218 | // Send mode to sensor 219 | Wire.beginTransmission(BH1750_I2CADDR); 220 | __wire_write((uint8_t)BH1750_MODE); 221 | Wire.endTransmission(); 222 | 223 | // Wait for measurement to be taken. 224 | // Measurements have a maximum measurement time and a typical measurement 225 | // time. The maxWait argument determines which measurement wait time is 226 | // used when a one-time mode is being used. The typical (shorter) 227 | // measurement time is used by default and if maxWait is set to True then 228 | // the maximum measurement time will be used. See data sheet pages 2, 5 229 | // and 7 for more details. 230 | // A continuous mode measurement can be read immediately after re-sending 231 | // the mode command. 232 | 233 | switch (BH1750_MODE) { 234 | 235 | case BH1750::ONE_TIME_LOW_RES_MODE: 236 | maxWait ? _delay_ms(24 * BH1750_MTreg/(byte)BH1750_DEFAULT_MTREG) : _delay_ms(16 * BH1750_MTreg/(byte)BH1750_DEFAULT_MTREG); 237 | break; 238 | case BH1750::ONE_TIME_HIGH_RES_MODE: 239 | case BH1750::ONE_TIME_HIGH_RES_MODE_2: 240 | maxWait ? _delay_ms(180 * BH1750_MTreg/(byte)BH1750_DEFAULT_MTREG) :_delay_ms(120 * BH1750_MTreg/(byte)BH1750_DEFAULT_MTREG); 241 | break; 242 | default: 243 | break; 244 | } 245 | 246 | // Read two bytes from the sensor, which are low and high parts of the sensor 247 | // value 248 | if (2 == Wire.requestFrom((int)BH1750_I2CADDR, (int)2)) { 249 | unsigned int tmp = 0; 250 | tmp = __wire_read(); 251 | tmp <<= 8; 252 | tmp |= __wire_read(); 253 | level = tmp; 254 | } 255 | 256 | if (level != -1.0) { 257 | // Print raw value if debug enabled 258 | #ifdef BH1750_DEBUG 259 | Serial.print(F("[BH1750] Raw value: ")); 260 | Serial.println(level); 261 | #endif 262 | 263 | if (BH1750_MTreg != BH1750_DEFAULT_MTREG) { 264 | level *= (float)((byte)BH1750_DEFAULT_MTREG/(float)BH1750_MTreg); 265 | // Print MTreg factor if debug enabled 266 | #ifdef BH1750_DEBUG 267 | Serial.print(F("[BH1750] MTreg factor: ")); 268 | Serial.println( String((float)((byte)BH1750_DEFAULT_MTREG/(float)BH1750_MTreg)) ); 269 | #endif 270 | } 271 | if (BH1750_MODE == BH1750::ONE_TIME_HIGH_RES_MODE_2 || BH1750_MODE == BH1750::CONTINUOUS_HIGH_RES_MODE_2) { 272 | level /= 2; 273 | } 274 | // Convert raw value to lux 275 | level /= BH1750_CONV_FACTOR; 276 | 277 | // Print converted value if debug enabled 278 | #ifdef BH1750_DEBUG 279 | Serial.print(F("[BH1750] Converted float value: ")); 280 | Serial.println(level); 281 | #endif 282 | } 283 | 284 | return level; 285 | 286 | } -------------------------------------------------------------------------------- /src/input/i2c/thirdparty/BH1750.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | This is a library for the BH1750FVI Digital Light Sensor breakout board. 4 | The BH1750 board uses I2C for communication. Two pins are required to 5 | interface to the device. Configuring the I2C bus is expected to be done 6 | in user code. The BH1750 library doesn't do this automatically. 7 | Datasheet: http://www.elechouse.com/elechouse/images/product/Digital%20light%20Sensor/bh1750fvi-e.pdf 8 | Written by Christopher Laws, March, 2013. 9 | 10 | SOURCE: https://github.com/claws/BH1750 11 | */ 12 | 13 | #ifndef BH1750_h 14 | #define BH1750_h 15 | 16 | #if (ARDUINO >= 100) 17 | #include 18 | #else 19 | #include 20 | #endif 21 | 22 | #include "Wire.h" 23 | 24 | // Uncomment, to enable debug messages 25 | // #define BH1750_DEBUG 26 | 27 | // No active state 28 | #define BH1750_POWER_DOWN 0x00 29 | 30 | // Waiting for measurement command 31 | #define BH1750_POWER_ON 0x01 32 | 33 | // Reset data register value - not accepted in POWER_DOWN mode 34 | #define BH1750_RESET 0x07 35 | 36 | // Default MTreg value 37 | #define BH1750_DEFAULT_MTREG 69 38 | 39 | class BH1750 { 40 | 41 | public: 42 | 43 | enum Mode 44 | { 45 | UNCONFIGURED = 0, 46 | // Measurement at 1 lux resolution. Measurement time is approx 120ms. 47 | CONTINUOUS_HIGH_RES_MODE = 0x10, 48 | // Measurement at 0.5 lux resolution. Measurement time is approx 120ms. 49 | CONTINUOUS_HIGH_RES_MODE_2 = 0x11, 50 | // Measurement at 4 lux resolution. Measurement time is approx 16ms. 51 | CONTINUOUS_LOW_RES_MODE = 0x13, 52 | // Measurement at 1 lux resolution. Measurement time is approx 120ms. 53 | ONE_TIME_HIGH_RES_MODE = 0x20, 54 | // Measurement at 0.5 lux resolution. Measurement time is approx 120ms. 55 | ONE_TIME_HIGH_RES_MODE_2 = 0x21, 56 | // Measurement at 4 lux resolution. Measurement time is approx 16ms. 57 | ONE_TIME_LOW_RES_MODE = 0x23 58 | }; 59 | 60 | BH1750(byte addr = 0x23); 61 | bool begin(Mode mode = CONTINUOUS_HIGH_RES_MODE); 62 | bool configure(Mode mode); 63 | bool setMTreg(byte MTreg); 64 | float readLightLevel(bool maxWait = false); 65 | 66 | private: 67 | byte BH1750_I2CADDR; 68 | byte BH1750_MTreg = (byte)BH1750_DEFAULT_MTREG; 69 | // Correction factor used to calculate lux. Typical value is 1.2 but can 70 | // range from 0.96 to 1.44. See the data sheet (p.2, Measurement Accuracy) 71 | // for more information. 72 | const float BH1750_CONV_FACTOR = 1.2; 73 | Mode BH1750_MODE = UNCONFIGURED; 74 | 75 | }; 76 | 77 | #endif -------------------------------------------------------------------------------- /src/input/onewire/SensorDHT.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorDHT.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v33 - Changes for Digital Sensor Switch Support 15 | v32 - Added MQTT Support! 16 | v31 - Fixed an issue with DHT11 Sensors 17 | v29 - First Public Release 18 | */ 19 | /**************************************************************************/ 20 | 21 | #include "SensorDHT.h" 22 | 23 | boolean SensorDHT::initDHT0 = false; 24 | boolean SensorDHT::initDHT1 = false; 25 | boolean SensorDHT::initDHT2 = false; 26 | boolean SensorDHT::initDHT3 = false; 27 | boolean SensorDHT::initDHT4 = false; 28 | boolean SensorDHT::initDHT5 = false; 29 | boolean SensorDHT::initDHT6 = false; 30 | boolean SensorDHT::initDHT7 = false; 31 | boolean SensorDHT::initDHT8 = false; 32 | boolean SensorDHT::initDHT9 = false; 33 | boolean SensorDHT::initDHT10 = false; 34 | boolean SensorDHT::initDHT11 = false; 35 | boolean SensorDHT::initDHT12 = false; 36 | boolean SensorDHT::initDHT13 = false; 37 | boolean SensorDHT::initDHT14 = false; 38 | boolean SensorDHT::initDHT15 = false; 39 | boolean SensorDHT::initDHT16 = false; 40 | 41 | DHT_Unified* SensorDHT::dht0 = NULL; 42 | DHT_Unified* SensorDHT::dht1 = NULL; 43 | DHT_Unified* SensorDHT::dht2 = NULL; 44 | DHT_Unified* SensorDHT::dht3 = NULL; 45 | DHT_Unified* SensorDHT::dht4 = NULL; 46 | DHT_Unified* SensorDHT::dht5 = NULL; 47 | DHT_Unified* SensorDHT::dht6 = NULL; 48 | DHT_Unified* SensorDHT::dht7 = NULL; 49 | DHT_Unified* SensorDHT::dht8 = NULL; 50 | DHT_Unified* SensorDHT::dht9 = NULL; 51 | DHT_Unified* SensorDHT::dht10 = NULL; 52 | DHT_Unified* SensorDHT::dht11 = NULL; 53 | DHT_Unified* SensorDHT::dht12 = NULL; 54 | DHT_Unified* SensorDHT::dht13 = NULL; 55 | DHT_Unified* SensorDHT::dht14 = NULL; 56 | DHT_Unified* SensorDHT::dht15 = NULL; 57 | DHT_Unified* SensorDHT::dht16 = NULL; 58 | 59 | extern boolean isResetting; 60 | extern int powerMode; 61 | 62 | SensorDHT::SensorDHT (long id, String category, String shortName, String name, String dhtType, uint8_t port, int refreshInterval, int postDataInterval, float smartValueThreshold, SensorCalculation* calculation) : Sensor (id, category, shortName, name, refreshInterval, postDataInterval, smartValueThreshold, calculation, false) { 63 | 64 | uint8_t type; 65 | 66 | if(dhtType=="DHT11") 67 | type = DHT11; 68 | else if(dhtType=="DHT21") 69 | type = DHT21; 70 | else if(dhtType=="DHT22") 71 | { 72 | type = DHT22; 73 | } 74 | 75 | if(port==0) 76 | { 77 | if(!initDHT0) 78 | { 79 | initDHT0=true; 80 | dht0 = new DHT_Unified(0, type); 81 | dht0->begin(); 82 | } 83 | dht = dht0; 84 | } 85 | else if(port==1) 86 | { 87 | if(!initDHT1) 88 | { 89 | initDHT1=true; 90 | dht1 = new DHT_Unified(1, type); 91 | dht1->begin(); 92 | } 93 | dht = dht1; 94 | } 95 | else if(port==2) 96 | { 97 | if(!initDHT2) 98 | { 99 | initDHT2=true; 100 | dht2 = new DHT_Unified(2, type); 101 | dht2->begin(); 102 | } 103 | dht = dht2; 104 | } 105 | else if(port==3) 106 | { 107 | if(!initDHT3) 108 | { 109 | initDHT3=true; 110 | dht3 = new DHT_Unified(3, type); 111 | dht3->begin(); 112 | } 113 | else 114 | { 115 | dht = dht3; 116 | } 117 | } 118 | else if(port==4) 119 | { 120 | if(!initDHT4) 121 | { 122 | initDHT4=true; 123 | dht4 = new DHT_Unified(4, type); 124 | dht4->begin(); 125 | } 126 | dht = dht4; 127 | } 128 | else if(port==5) 129 | { 130 | if(!initDHT5) 131 | { 132 | initDHT5=true; 133 | dht5 = new DHT_Unified(5, type); 134 | dht5->begin(); 135 | } 136 | else 137 | { 138 | dht = dht5; 139 | } 140 | } 141 | else if(port==6) 142 | { 143 | if(!initDHT6) 144 | { 145 | initDHT6=true; 146 | dht6 = new DHT_Unified(6, type); 147 | dht6->begin(); 148 | } 149 | dht = dht6; 150 | } 151 | else if(port==7) 152 | { 153 | if(!initDHT7) 154 | { 155 | initDHT7=true; 156 | dht7 = new DHT_Unified(7, type); 157 | dht7->begin(); 158 | } 159 | dht = dht7; 160 | } 161 | else if(port==8) 162 | { 163 | if(!initDHT8) 164 | { 165 | initDHT8=true; 166 | dht8 = new DHT_Unified(8, type); 167 | dht8->begin(); 168 | } 169 | dht = dht8; 170 | } 171 | else if(port==9) 172 | { 173 | if(!initDHT9) 174 | { 175 | initDHT9=true; 176 | dht9 = new DHT_Unified(9, type); 177 | dht9->begin(); 178 | } 179 | else 180 | { 181 | dht = dht9; 182 | } 183 | } 184 | else if(port==10) 185 | { 186 | if(!initDHT10) 187 | { 188 | initDHT10=true; 189 | dht10 = new DHT_Unified(10, type); 190 | dht10->begin(); 191 | } 192 | dht = dht10; 193 | } 194 | else if(port==11) 195 | { 196 | if(!initDHT11) 197 | { 198 | initDHT11=true; 199 | dht11 = new DHT_Unified(11, type); 200 | dht11->begin(); 201 | } 202 | dht = dht11; 203 | } 204 | else if(port==12) 205 | { 206 | if(!initDHT12) 207 | { 208 | initDHT12=true; 209 | dht12 = new DHT_Unified(12, type); 210 | dht12->begin(); 211 | } 212 | dht = dht12; 213 | } 214 | else if(port==13) 215 | { 216 | if(!initDHT13) 217 | { 218 | initDHT13=true; 219 | dht13 = new DHT_Unified(13, type); 220 | dht13->begin(); 221 | } 222 | dht = dht13; 223 | } 224 | else if(port==14) 225 | { 226 | if(!initDHT14) 227 | { 228 | initDHT14=true; 229 | dht14 = new DHT_Unified(14, type); 230 | dht14->begin(); 231 | } 232 | dht = dht14; 233 | } 234 | else if(port==15) 235 | { 236 | if(!initDHT15) 237 | { 238 | initDHT15=true; 239 | dht15 = new DHT_Unified(15, type); 240 | dht15->begin(); 241 | } 242 | dht = dht15; 243 | } 244 | else if(port==16) 245 | { 246 | if(!initDHT16) 247 | { 248 | initDHT16=true; 249 | dht16 = new DHT_Unified(16, type); 250 | dht16->begin(); 251 | } 252 | dht = dht16; 253 | } 254 | } 255 | 256 | void SensorDHT::preCycle(int cycleId) 257 | { 258 | } 259 | 260 | Data* SensorDHT::read(bool shouldPostData) 261 | { 262 | if(!isResetting) 263 | { 264 | sensors_event_t event; 265 | 266 | if(_calculation->getValueType()=="humidity") 267 | { 268 | dht->humidity().getEvent(&event); 269 | 270 | if (isnan(event.relative_humidity)) { 271 | Serial.println("NAN Humidity!"); 272 | } 273 | else { 274 | shouldPostData = smartSensorCheck(event.relative_humidity, _smartValueThreshold, shouldPostData); 275 | return _calculation->calculate(this, event.relative_humidity, shouldPostData); 276 | } 277 | } 278 | else if(_calculation->getValueType()=="temperature") 279 | { 280 | dht->temperature().getEvent(&event); 281 | 282 | if (isnan(event.temperature)) { 283 | Serial.println("NAN Temperature!"); 284 | } 285 | else { 286 | shouldPostData = smartSensorCheck(event.temperature, _smartValueThreshold, shouldPostData); 287 | return _calculation->calculate(this, event.temperature, shouldPostData); 288 | } 289 | } 290 | } 291 | 292 | return NULL; 293 | } 294 | 295 | boolean SensorDHT::smartSensorCheck(float currentRawValue, float threshhold, boolean shouldPostData) 296 | { 297 | if(powerMode == 3) 298 | { 299 | if(!shouldPostData) 300 | { 301 | if(!isnan(lastPostedValue)) 302 | { 303 | if(lastPostedValue-currentRawValue>threshhold || lastPostedValue-currentRawValue<-threshhold) 304 | { 305 | Serial.println("Overwrite shouldPostData!"); 306 | shouldPostData = true; 307 | } 308 | 309 | } 310 | } 311 | 312 | if(shouldPostData) 313 | lastPostedValue = currentRawValue; 314 | } 315 | 316 | return shouldPostData; 317 | 318 | } -------------------------------------------------------------------------------- /src/input/onewire/SensorDHT.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorDHT.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v32 - Added MQTT Support! 15 | v29 - First Public Release 16 | */ 17 | /**************************************************************************/ 18 | 19 | #include 20 | #include 21 | 22 | #ifndef _SensorDHT_h_ 23 | #define _SensorDHT_h_ 24 | 25 | #include "../Sensor.h" 26 | 27 | class SensorDHT : public Sensor { 28 | private: 29 | static boolean initDHT0; 30 | static boolean initDHT1; 31 | static boolean initDHT2; 32 | static boolean initDHT3; 33 | static boolean initDHT4; 34 | static boolean initDHT5; 35 | static boolean initDHT6; 36 | static boolean initDHT7; 37 | static boolean initDHT8; 38 | static boolean initDHT9; 39 | static boolean initDHT10; 40 | static boolean initDHT11; 41 | static boolean initDHT12; 42 | static boolean initDHT13; 43 | static boolean initDHT14; 44 | static boolean initDHT15; 45 | static boolean initDHT16; 46 | static DHT_Unified* dht0; 47 | static DHT_Unified* dht1; 48 | static DHT_Unified* dht2; 49 | static DHT_Unified* dht3; 50 | static DHT_Unified* dht4; 51 | static DHT_Unified* dht5; 52 | static DHT_Unified* dht6; 53 | static DHT_Unified* dht7; 54 | static DHT_Unified* dht8; 55 | static DHT_Unified* dht9; 56 | static DHT_Unified* dht10; 57 | static DHT_Unified* dht11; 58 | static DHT_Unified* dht12; 59 | static DHT_Unified* dht13; 60 | static DHT_Unified* dht14; 61 | static DHT_Unified* dht15; 62 | static DHT_Unified* dht16; 63 | DHT_Unified* dht; 64 | float lastPostedValue = NAN; 65 | protected: 66 | Data* read(bool); 67 | void preCycle(int); 68 | boolean smartSensorCheck(float, float, boolean); 69 | public: 70 | SensorDHT (long, String, String, String,String, uint8_t, int, int, float, SensorCalculation*); 71 | }; 72 | 73 | #endif -------------------------------------------------------------------------------- /src/input/onewire/SensorDallas.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorDallas.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v33 - Changes for Digital Sensor Switch Support 15 | v32 - Added MQTT Support! 16 | v29 - First Public Release 17 | */ 18 | /**************************************************************************/ 19 | 20 | #include "SensorDallas.h" 21 | 22 | boolean SensorDallas::initDallas0 = false; 23 | boolean SensorDallas::initDallas1 = false; 24 | boolean SensorDallas::initDallas2 = false; 25 | boolean SensorDallas::initDallas3 = false; 26 | boolean SensorDallas::initDallas4 = false; 27 | boolean SensorDallas::initDallas5 = false; 28 | boolean SensorDallas::initDallas6 = false; 29 | boolean SensorDallas::initDallas7 = false; 30 | boolean SensorDallas::initDallas8 = false; 31 | boolean SensorDallas::initDallas9 = false; 32 | boolean SensorDallas::initDallas10 = false; 33 | boolean SensorDallas::initDallas11 = false; 34 | boolean SensorDallas::initDallas12 = false; 35 | boolean SensorDallas::initDallas13 = false; 36 | boolean SensorDallas::initDallas14 = false; 37 | boolean SensorDallas::initDallas15 = false; 38 | boolean SensorDallas::initDallas16 = false; 39 | OneWire* SensorDallas::oneWire0 = NULL; 40 | OneWire* SensorDallas::oneWire1 = NULL; 41 | OneWire* SensorDallas::oneWire2 = NULL; 42 | OneWire* SensorDallas::oneWire3 = NULL; 43 | OneWire* SensorDallas::oneWire4 = NULL; 44 | OneWire* SensorDallas::oneWire5 = NULL; 45 | OneWire* SensorDallas::oneWire6 = NULL; 46 | OneWire* SensorDallas::oneWire7 = NULL; 47 | OneWire* SensorDallas::oneWire8 = NULL; 48 | OneWire* SensorDallas::oneWire9 = NULL; 49 | OneWire* SensorDallas::oneWire10 = NULL; 50 | OneWire* SensorDallas::oneWire11 = NULL; 51 | OneWire* SensorDallas::oneWire12 = NULL; 52 | OneWire* SensorDallas::oneWire13 = NULL; 53 | OneWire* SensorDallas::oneWire14 = NULL; 54 | OneWire* SensorDallas::oneWire15 = NULL; 55 | OneWire* SensorDallas::oneWire16 = NULL; 56 | DallasTemperature* SensorDallas::dallasTemperature0 = NULL; 57 | DallasTemperature* SensorDallas::dallasTemperature1 = NULL; 58 | DallasTemperature* SensorDallas::dallasTemperature2 = NULL; 59 | DallasTemperature* SensorDallas::dallasTemperature3 = NULL; 60 | DallasTemperature* SensorDallas::dallasTemperature4 = NULL; 61 | DallasTemperature* SensorDallas::dallasTemperature5 = NULL; 62 | DallasTemperature* SensorDallas::dallasTemperature6 = NULL; 63 | DallasTemperature* SensorDallas::dallasTemperature7 = NULL; 64 | DallasTemperature* SensorDallas::dallasTemperature8 = NULL; 65 | DallasTemperature* SensorDallas::dallasTemperature9 = NULL; 66 | DallasTemperature* SensorDallas::dallasTemperature10 = NULL; 67 | DallasTemperature* SensorDallas::dallasTemperature11 = NULL; 68 | DallasTemperature* SensorDallas::dallasTemperature12 = NULL; 69 | DallasTemperature* SensorDallas::dallasTemperature13 = NULL; 70 | DallasTemperature* SensorDallas::dallasTemperature14 = NULL; 71 | DallasTemperature* SensorDallas::dallasTemperature15 = NULL; 72 | DallasTemperature* SensorDallas::dallasTemperature16 = NULL; 73 | 74 | extern boolean isResetting; 75 | extern int powerMode; 76 | 77 | SensorDallas::SensorDallas (long id, String category, String shortName, String name, uint8_t port, int channel, int refreshInterval, int postDataInterval, float smartValueThreshold, SensorCalculation* calculation) : Sensor (id, category, shortName, name, refreshInterval, postDataInterval, smartValueThreshold, calculation, false) { 78 | 79 | _channel = channel; 80 | 81 | if(port==0) 82 | { 83 | if(!initDallas0) 84 | { 85 | initDallas0=true; 86 | oneWire0 = new OneWire(0); 87 | dallasTemperature0 = new DallasTemperature(oneWire0); 88 | dallasTemperature0->begin(); 89 | } 90 | dallasTemperature = dallasTemperature0; 91 | } 92 | else if(port==1) 93 | { 94 | if(!initDallas1) 95 | { 96 | initDallas1=true; 97 | oneWire1 = new OneWire(1); 98 | dallasTemperature1 = new DallasTemperature(oneWire1); 99 | dallasTemperature1->begin(); 100 | } 101 | dallasTemperature = dallasTemperature1; 102 | } 103 | else if(port==2) 104 | { 105 | if(!initDallas2) 106 | { 107 | initDallas2=true; 108 | oneWire2 = new OneWire(2); 109 | dallasTemperature2 = new DallasTemperature(oneWire2); 110 | dallasTemperature2->begin(); 111 | } 112 | dallasTemperature = dallasTemperature2; 113 | } 114 | else if(port==3) 115 | { 116 | if(!initDallas3) 117 | { 118 | initDallas3=true; 119 | oneWire3 = new OneWire(3); 120 | dallasTemperature3 = new DallasTemperature(oneWire3); 121 | dallasTemperature3->begin(); 122 | } 123 | dallasTemperature = dallasTemperature3; 124 | } 125 | else if(port==4) 126 | { 127 | if(!initDallas4) 128 | { 129 | initDallas4=true; 130 | oneWire4 = new OneWire(4); 131 | dallasTemperature4 = new DallasTemperature(oneWire4); 132 | dallasTemperature4->begin(); 133 | } 134 | dallasTemperature = dallasTemperature4; 135 | } 136 | else if(port==5) 137 | { 138 | if(!initDallas5) 139 | { 140 | initDallas5=true; 141 | oneWire5 = new OneWire(5); 142 | dallasTemperature5 = new DallasTemperature(oneWire5); 143 | dallasTemperature5->begin(); 144 | } 145 | dallasTemperature = dallasTemperature5; 146 | } 147 | else if(port==6) 148 | { 149 | if(!initDallas6) 150 | { 151 | initDallas6=true; 152 | oneWire6 = new OneWire(6); 153 | dallasTemperature6 = new DallasTemperature(oneWire6); 154 | dallasTemperature6->begin(); 155 | } 156 | dallasTemperature = dallasTemperature6; 157 | } 158 | else if(port==7) 159 | { 160 | if(!initDallas7) 161 | { 162 | initDallas7=true; 163 | oneWire7 = new OneWire(7); 164 | dallasTemperature7 = new DallasTemperature(oneWire7); 165 | dallasTemperature7->begin(); 166 | } 167 | dallasTemperature = dallasTemperature7; 168 | } 169 | else if(port==8) 170 | { 171 | if(!initDallas8) 172 | { 173 | initDallas8=true; 174 | oneWire8 = new OneWire(8); 175 | dallasTemperature8 = new DallasTemperature(oneWire8); 176 | dallasTemperature8->begin(); 177 | } 178 | dallasTemperature = dallasTemperature8; 179 | } 180 | else if(port==9) 181 | { 182 | if(!initDallas9) 183 | { 184 | initDallas9=true; 185 | oneWire9 = new OneWire(9); 186 | dallasTemperature9 = new DallasTemperature(oneWire9); 187 | dallasTemperature9->begin(); 188 | } 189 | dallasTemperature = dallasTemperature9; 190 | } 191 | else if(port==10) 192 | { 193 | if(!initDallas10) 194 | { 195 | initDallas10=true; 196 | oneWire10 = new OneWire(10); 197 | dallasTemperature10 = new DallasTemperature(oneWire10); 198 | dallasTemperature10->begin(); 199 | } 200 | dallasTemperature = dallasTemperature10; 201 | } 202 | else if(port==11) 203 | { 204 | if(!initDallas11) 205 | { 206 | initDallas11=true; 207 | oneWire11 = new OneWire(11); 208 | dallasTemperature11 = new DallasTemperature(oneWire11); 209 | dallasTemperature11->begin(); 210 | } 211 | dallasTemperature = dallasTemperature11; 212 | } 213 | else if(port==12) 214 | { 215 | if(!initDallas12) 216 | { 217 | initDallas12=true; 218 | oneWire12 = new OneWire(12); 219 | dallasTemperature12 = new DallasTemperature(oneWire12); 220 | dallasTemperature12->begin(); 221 | } 222 | dallasTemperature = dallasTemperature12; 223 | } 224 | else if(port==13) 225 | { 226 | if(!initDallas13) 227 | { 228 | initDallas13=true; 229 | oneWire13 = new OneWire(13); 230 | dallasTemperature13 = new DallasTemperature(oneWire13); 231 | dallasTemperature13->begin(); 232 | } 233 | dallasTemperature = dallasTemperature13; 234 | } 235 | else if(port==14) 236 | { 237 | if(!initDallas14) 238 | { 239 | initDallas14=true; 240 | oneWire14 = new OneWire(14); 241 | dallasTemperature14 = new DallasTemperature(oneWire14); 242 | dallasTemperature14->begin(); 243 | } 244 | dallasTemperature = dallasTemperature14; 245 | } 246 | else if(port==15) 247 | { 248 | if(!initDallas15) 249 | { 250 | initDallas15=true; 251 | oneWire15 = new OneWire(15); 252 | dallasTemperature15 = new DallasTemperature(oneWire15); 253 | dallasTemperature15->begin(); 254 | } 255 | dallasTemperature = dallasTemperature15; 256 | } 257 | else if(port==16) 258 | { 259 | if(!initDallas16) 260 | { 261 | initDallas16=true; 262 | oneWire16 = new OneWire(16); 263 | dallasTemperature16 = new DallasTemperature(oneWire16); 264 | dallasTemperature16->begin(); 265 | } 266 | dallasTemperature = dallasTemperature16; 267 | } 268 | 269 | numberOfDevices = dallasTemperature->getDeviceCount(); 270 | 271 | if(_channelgetAddress(_address, channel); 273 | 274 | } 275 | 276 | void SensorDallas::preCycle(int cycleId) 277 | { 278 | } 279 | 280 | Data* SensorDallas::read(bool shouldPostData) 281 | { 282 | if(!isResetting && numberOfDevices>0 && _channelrequestTemperaturesByAddress(_address); 285 | float tempC = dallasTemperature->getTempC(_address); 286 | 287 | if(tempC==-127.00 || tempC==85.00) 288 | { 289 | for(int i=0;i<10;i++) 290 | { 291 | dallasTemperature->requestTemperaturesByAddress(_address); 292 | delay(50); 293 | yield(); 294 | tempC = dallasTemperature->getTempC(_address); 295 | delay(100); 296 | yield(); 297 | 298 | if(tempC!=-127.00 && tempC!=85.00) 299 | break; 300 | } 301 | } 302 | 303 | if(tempC!=-127.00 && tempC!=85.00) { 304 | shouldPostData = smartSensorCheck(tempC, 0.3f, shouldPostData); 305 | return _calculation->calculate(this, tempC, shouldPostData); 306 | } 307 | } 308 | 309 | return NULL; 310 | 311 | } 312 | 313 | boolean SensorDallas::smartSensorCheck(float currentRawValue, float threshhold, boolean shouldPostData) 314 | { 315 | if(powerMode == 3) 316 | { 317 | if(!shouldPostData) 318 | { 319 | if(!isnan(lastPostedValue)) 320 | { 321 | if(lastPostedValue-currentRawValue>threshhold || lastPostedValue-currentRawValue<-threshhold) 322 | { 323 | shouldPostData = true; 324 | } 325 | } 326 | } 327 | 328 | if(shouldPostData) 329 | lastPostedValue = currentRawValue; 330 | } 331 | 332 | return shouldPostData; 333 | 334 | } -------------------------------------------------------------------------------- /src/input/onewire/SensorDallas.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file SensorDallas.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v32 - Added MQTT Support! 15 | v29 - First Public Release 16 | */ 17 | /**************************************************************************/ 18 | 19 | #include 20 | 21 | #ifndef _SensorDallas_h_ 22 | #define _SensorDallas_h_ 23 | 24 | #include "../Sensor.h" 25 | 26 | //DS18B20 27 | #define ONE_WIRE_MAX_DEV 15 //The maximum number of devices per Bus 28 | 29 | class SensorDallas : public Sensor { 30 | private: 31 | static boolean initDallas0; 32 | static boolean initDallas1; 33 | static boolean initDallas2; 34 | static boolean initDallas3; 35 | static boolean initDallas4; 36 | static boolean initDallas5; 37 | static boolean initDallas6; 38 | static boolean initDallas7; 39 | static boolean initDallas8; 40 | static boolean initDallas9; 41 | static boolean initDallas10; 42 | static boolean initDallas11; 43 | static boolean initDallas12; 44 | static boolean initDallas13; 45 | static boolean initDallas14; 46 | static boolean initDallas15; 47 | static boolean initDallas16; 48 | static DallasTemperature* dallasTemperature0; 49 | static DallasTemperature* dallasTemperature1; 50 | static DallasTemperature* dallasTemperature2; 51 | static DallasTemperature* dallasTemperature3; 52 | static DallasTemperature* dallasTemperature4; 53 | static DallasTemperature* dallasTemperature5; 54 | static DallasTemperature* dallasTemperature6; 55 | static DallasTemperature* dallasTemperature7; 56 | static DallasTemperature* dallasTemperature8; 57 | static DallasTemperature* dallasTemperature9; 58 | static DallasTemperature* dallasTemperature10; 59 | static DallasTemperature* dallasTemperature11; 60 | static DallasTemperature* dallasTemperature12; 61 | static DallasTemperature* dallasTemperature13; 62 | static DallasTemperature* dallasTemperature14; 63 | static DallasTemperature* dallasTemperature15; 64 | static DallasTemperature* dallasTemperature16; 65 | static OneWire* oneWire0; 66 | static OneWire* oneWire1; 67 | static OneWire* oneWire2; 68 | static OneWire* oneWire3; 69 | static OneWire* oneWire4; 70 | static OneWire* oneWire5; 71 | static OneWire* oneWire6; 72 | static OneWire* oneWire7; 73 | static OneWire* oneWire8; 74 | static OneWire* oneWire9; 75 | static OneWire* oneWire10; 76 | static OneWire* oneWire11; 77 | static OneWire* oneWire12; 78 | static OneWire* oneWire13; 79 | static OneWire* oneWire14; 80 | static OneWire* oneWire15; 81 | static OneWire* oneWire16; 82 | DallasTemperature* dallasTemperature; 83 | int numberOfDevices; 84 | DeviceAddress devAddr[ONE_WIRE_MAX_DEV]; 85 | int _channel; 86 | DeviceAddress _address; 87 | float lastPostedValue = NAN; 88 | protected: 89 | Data* read(bool); 90 | void preCycle(int); 91 | boolean smartSensorCheck(float, float, boolean); 92 | public: 93 | SensorDallas (long, String, String, String, uint8_t, int, int, int, float, SensorCalculation*); 94 | }; 95 | 96 | #endif -------------------------------------------------------------------------------- /src/output/VisualisationHelper.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file VisualisationHelper.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP32 firmware is used to connect ESP32 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v40 - New Display Structure to enable Display Rotation, different Styles etc. 15 | */ 16 | /**************************************************************************/ 17 | 18 | #include "VisualisationHelper.h" 19 | 20 | VisualisationHelper::VisualisationHelper() 21 | { 22 | _displayDataModel = new DisplayDataModel(); 23 | } 24 | 25 | DisplayDataModel* VisualisationHelper::getDisplayDataModel() 26 | { 27 | return _displayDataModel; 28 | } 29 | 30 | void VisualisationHelper::enableDisplayCycle(unsigned long currentMillis, int simultanValueCount, unsigned long interval) 31 | { 32 | if(!_enableCycle && (_displayDataModel->getCount()>simultanValueCount)) 33 | { 34 | _enableCycle = true; 35 | _lastDisplayCycleUpdate = currentMillis; 36 | 37 | _simultanValueCount = simultanValueCount; 38 | _displayCycleInterval = interval; 39 | 40 | int dataCount = _displayDataModel->getCount(); 41 | _maxCyclePosition = dataCount/simultanValueCount; 42 | if(dataCount%simultanValueCount==0) 43 | _maxCyclePosition--; 44 | 45 | Serial.println("Display Cycle enabled with "+String(_maxCyclePosition+1)+" screens showing "+String(simultanValueCount)+" values on each."); 46 | } 47 | } 48 | 49 | void VisualisationHelper::disableDisplayCycle() 50 | { 51 | _enableCycle = false; 52 | _currentCyclePosition = 0; 53 | } 54 | 55 | DisplayValueData* VisualisationHelper::getDataForPosition(unsigned long currentMillis, int position) 56 | { 57 | if(_displayDataModel!=NULL) 58 | { 59 | if(!_enableCycle) 60 | { 61 | return _displayDataModel->getData(position); 62 | } 63 | else 64 | { 65 | if(currentMillis > _lastDisplayCycleUpdate+_displayCycleInterval || currentMillis < _lastDisplayCycleUpdate) 66 | { 67 | _lastDisplayCycleUpdate = currentMillis; 68 | 69 | if(_currentCyclePosition<_maxCyclePosition) 70 | _currentCyclePosition++; 71 | else 72 | _currentCyclePosition=0; 73 | } 74 | 75 | int pos = position + (_currentCyclePosition*_simultanValueCount); 76 | return _displayDataModel->getData(pos); 77 | } 78 | } 79 | 80 | return NULL; 81 | } 82 | 83 | void VisualisationHelper::updateSimultanValueCount(int simultanValueCount) 84 | { 85 | _simultanValueCount = simultanValueCount; 86 | disableDisplayCycle(); 87 | enableDisplayCycle(_lastDisplayCycleUpdate, _simultanValueCount, _displayCycleInterval); 88 | } 89 | -------------------------------------------------------------------------------- /src/output/VisualisationHelper.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file VisualisationHelper.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP32 firmware is used to connect ESP32 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v40 - New Display Structure to enable Display Rotation, different Styles etc. 15 | */ 16 | /**************************************************************************/ 17 | 18 | #include 19 | #include "model/DisplayDataModel.h" 20 | 21 | #ifndef _VISUALISATIONHELPER_h_ 22 | #define _VISUALISATIONHELPER_h_ 23 | 24 | class VisualisationHelper { 25 | private: 26 | DisplayDataModel* _displayDataModel; 27 | boolean _enableCycle = false; 28 | unsigned long _displayCycleInterval; 29 | int _simultanValueCount; 30 | unsigned long _lastDisplayCycleUpdate; 31 | int _currentCyclePosition = 0; 32 | int _maxCyclePosition = 0; 33 | public: 34 | VisualisationHelper(); 35 | DisplayDataModel* getDisplayDataModel(); 36 | void enableDisplayCycle(unsigned long, int, unsigned long); 37 | void disableDisplayCycle(); 38 | void updateSimultanValueCount(int); 39 | DisplayValueData* getDataForPosition(unsigned long, int); 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/output/display/Display.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Display.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensatio ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensatio Cloud and the Sensatio apps. 8 | 9 | ----> https://www.sensatio.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v41 - Abstract Display Class to support more types 15 | */ 16 | /**************************************************************************/ 17 | 18 | #include "Display.h" 19 | 20 | extern VisualisationHelper* vHelper; 21 | 22 | Display::Display(int _type) { 23 | 24 | type = _type; 25 | visibleDataCount = 0; 26 | 27 | } 28 | 29 | void Display::clear(boolean update) { 30 | } 31 | 32 | void Display::drawProductLogo() { 33 | } 34 | 35 | void Display::drawData(unsigned long currentMillis) { 36 | } 37 | 38 | void Display::drawString(int16_t x, int16_t y, String text) { 39 | } 40 | 41 | void Display::drawDisconnected(bool update) { 42 | 43 | } 44 | 45 | void Display::drawConnected(bool update) { 46 | 47 | } 48 | 49 | void Display::flip(int rotation) { 50 | 51 | } 52 | 53 | int Display::getType() { 54 | return type; 55 | } 56 | 57 | int Display::getSimultanValueCount() { 58 | return visibleDataCount; 59 | } 60 | -------------------------------------------------------------------------------- /src/output/display/Display.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Display.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensatio ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensatio Cloud and the Sensatio apps. 8 | 9 | ----> https://www.sensatio.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v41 - Abstract Display Class to support more types 15 | */ 16 | /**************************************************************************/ 17 | 18 | #ifndef _DISPLAY_h_ 19 | #define _DISPLAY_h_ 20 | 21 | #include "../VisualisationHelper.h" 22 | 23 | #define Product_Logo_width 128 24 | #define Product_Logo_height 64 25 | 26 | const uint8_t Product_Logo[] PROGMEM = { 27 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 28 | 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 29 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 30 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x1F, 31 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 32 | 0x00, 0xE0, 0x07, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 33 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 34 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 35 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 36 | 0x00, 0x38, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x07, 0x00, 39 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 40 | 0x00, 0x9E, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x00, 42 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x1F, 43 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 44 | 0x00, 0xCE, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x70, 47 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 48 | 0x00, 0xC6, 0x01, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x83, 0x63, 0x00, 0x00, 0x00, 0x00, 50 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0xE3, 51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 | 0x00, 0x00, 0x0F, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xE6, 0x00, 0x00, 0x00, 0x00, 54 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 55 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 56 | 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 57 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, 0x00, 58 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 59 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 60 | 0x00, 0xC0, 0x81, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 61 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE7, 0x79, 0x00, 0x00, 0x00, 0x00, 62 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x3C, 63 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 64 | 0x00, 0x00, 0x3E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 66 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x07, 67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 68 | 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 69 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 70 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 71 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 72 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 73 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 75 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 76 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 77 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 78 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 79 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 80 | 0x03, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 81 | 0x00, 0x00, 0x00, 0x80, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 82 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 83 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 84 | 0x01, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xE0, 0xFF, 0x81, 0xF9, 0x07, 0xFC, 85 | 0x3F, 0xF8, 0x1F, 0xF8, 0x3F, 0x1C, 0xF8, 0x7F, 0xF8, 0xFF, 0xF0, 0xFF, 86 | 0xC3, 0xFF, 0x0F, 0xFE, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0x1C, 0xFC, 0x7F, 87 | 0xF8, 0x7F, 0xF0, 0xFF, 0xC3, 0xFF, 0x1F, 0xFE, 0x1F, 0xFC, 0x7F, 0xFC, 88 | 0x1F, 0x1E, 0xFE, 0xFF, 0x3C, 0x00, 0x78, 0x80, 0xC3, 0x03, 0x1E, 0x0F, 89 | 0x00, 0x00, 0x78, 0xE0, 0x00, 0x1E, 0x0E, 0xF0, 0x3C, 0x00, 0x38, 0x80, 90 | 0xC3, 0x01, 0x1E, 0x0F, 0x00, 0x00, 0x70, 0xE0, 0x00, 0x0E, 0x0F, 0xF0, 91 | 0xFC, 0x00, 0x38, 0xC0, 0xC3, 0x01, 0x0E, 0x3F, 0x00, 0x00, 0x78, 0xF0, 92 | 0x00, 0x0E, 0x0F, 0xF0, 0xF8, 0x0F, 0xF8, 0xFF, 0xE3, 0x01, 0x0E, 0xFF, 93 | 0x03, 0xFC, 0x7F, 0x70, 0x00, 0x0E, 0x07, 0x70, 0xF0, 0x3F, 0xFC, 0xFF, 94 | 0xE1, 0x01, 0x0E, 0xFE, 0x0F, 0xFE, 0x3F, 0x70, 0x00, 0x0F, 0x07, 0x70, 95 | 0x80, 0x7F, 0xFC, 0xFF, 0xE1, 0x00, 0x0F, 0xE0, 0x1F, 0xFF, 0x3F, 0x70, 96 | 0x00, 0x0F, 0x07, 0x70, 0x00, 0x78, 0x1C, 0x00, 0xE0, 0x00, 0x0F, 0x00, 97 | 0x1E, 0x07, 0x38, 0x78, 0x00, 0x87, 0x07, 0x78, 0x00, 0x78, 0x1C, 0x00, 98 | 0xE0, 0x00, 0x07, 0x00, 0x9E, 0x07, 0x3C, 0x78, 0x00, 0x87, 0x07, 0x78, 99 | 0x00, 0x7C, 0x3C, 0x00, 0xF0, 0x00, 0x07, 0x00, 0x9F, 0x07, 0x3E, 0xF8, 100 | 0x00, 0x87, 0x07, 0x38, 0xFF, 0x3F, 0xFC, 0xFF, 0x70, 0x80, 0xC7, 0xFF, 101 | 0x0F, 0xFF, 0x1F, 0xF0, 0x8F, 0x87, 0xFF, 0x3F, 0xFF, 0x1F, 0xF8, 0x7F, 102 | 0x70, 0x80, 0xC7, 0xFF, 0x07, 0xFF, 0x1D, 0xF0, 0x87, 0x07, 0xFF, 0x1F, 103 | 0xFF, 0x0F, 0xF0, 0x7F, 0x70, 0x80, 0xC3, 0xFF, 0x03, 0xFE, 0x1C, 0xC0, 104 | 0x87, 0x03, 0xFE, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 105 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 106 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 107 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 108 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 109 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 110 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 111 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 112 | 0x00, 0x00, 0x00, 0x00 113 | }; 114 | 115 | class Display { 116 | protected: 117 | int type; 118 | int visibleDataCount; 119 | int displayWidth; 120 | int displayHeight; 121 | public: 122 | Display (int); 123 | virtual void drawProductLogo(); 124 | virtual void drawData(unsigned long currentMillis); 125 | virtual void clear(boolean update); 126 | virtual void drawString(int16_t x, int16_t y, String text); 127 | virtual void drawDisconnected(bool update); 128 | virtual void drawConnected(bool update); 129 | virtual void flip(int rotation); 130 | int getType(); 131 | virtual int getSimultanValueCount(); 132 | }; 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /src/output/display/DisplayOLED128.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file DisplayOLED128.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensatio ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensatio Cloud and the Sensatio apps. 8 | 9 | ----> https://www.sensatio.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v41 - Renamed Display Class to support more types, New Display Mode 15 | v40 - New Display Structure to enable Display Rotation, different Styles etc. 16 | v33 - Added Digital Sensor Switch Support 17 | v30 - Added Support for SSD1306 Displays 18 | v29 - First Public Release 19 | */ 20 | /**************************************************************************/ 21 | 22 | #include "DisplayOLED128.h" 23 | 24 | extern bool isResetting; 25 | extern VisualisationHelper* vHelper; 26 | 27 | extern int displayMode; 28 | extern boolean displayEnabled; 29 | extern bool firstSensorData; 30 | 31 | DisplayOLED128::DisplayOLED128(int width, int height, bool flip, int _type, String address, uint8_t PortSDA, uint8_t PortSCL) : Display(_type) { 32 | 33 | if(!isResetting) 34 | { 35 | OLEDDISPLAY_GEOMETRY g; 36 | 37 | displayWidth = width; 38 | displayHeight = height; 39 | 40 | if(displayWidth==128 && displayHeight==32) 41 | { 42 | g = GEOMETRY_128_32; 43 | visibleDataCount = 2; 44 | } 45 | else 46 | { 47 | g = GEOMETRY_128_64; 48 | visibleDataCount = 4; 49 | } 50 | 51 | firstSensorData=true; 52 | 53 | if(type==2) 54 | display = new SSD1306Wire(0x3c, PortSDA, PortSCL, g); 55 | else 56 | display = new SH1106Wire(0x3c, PortSDA, PortSCL, g); 57 | 58 | display->init(); 59 | if(flip) 60 | display->flipScreenVertically(); 61 | display->setContrast(255); 62 | display->clear(); 63 | 64 | } 65 | } 66 | 67 | void DisplayOLED128::clear(boolean update) { 68 | 69 | if(!isResetting) 70 | { 71 | display->clear(); 72 | if(update) 73 | display->display(); 74 | } 75 | } 76 | 77 | void DisplayOLED128::flip(int rotation) { 78 | display->resetDisplay(); 79 | display->setContrast(255); 80 | 81 | if(rotation==180) 82 | display->flipScreenVertically(); 83 | else 84 | display->resetOrientation(); 85 | } 86 | 87 | void DisplayOLED128::drawProductLogo() { 88 | 89 | // see http://blog.squix.org/2015/05/esp8266-nodemcu-how-to-create-xbm.html 90 | // on how to create xbm files 91 | // https://www.online-utility.org/image_converter.jsp --> XBM Mono 92 | 93 | if(!isResetting && displayEnabled) 94 | { 95 | display->drawXbm(0, 0, Product_Logo_width, Product_Logo_height, Product_Logo); 96 | display->display(); 97 | } 98 | } 99 | 100 | void DisplayOLED128::drawString(int16_t x, int16_t y, String text) { 101 | 102 | if(!isResetting && displayEnabled) 103 | { 104 | display->setColor(BLACK); 105 | display->fillRect(x, y, display->getStringWidth(text), 16); 106 | display->setColor(WHITE); 107 | display->drawString(x, y, text); 108 | display->display(); 109 | } 110 | 111 | } 112 | 113 | void DisplayOLED128::drawArrow() { 114 | if(!isResetting && displayEnabled) 115 | { 116 | display->drawLine(0, 0, 30, display->getHeight()/2); 117 | display->drawLine(4, 0, 34, display->getHeight()/2); 118 | display->drawLine(30, display->getHeight()/2, 0, display->getHeight()-1); 119 | display->drawLine(34, display->getHeight()/2, 4, display->getHeight()-1); 120 | display->drawLine(display->getWidth()-1, 0, display->getWidth()-30, display->getHeight()/2); 121 | display->drawLine(display->getWidth()-5, 0, display->getWidth()-34, display->getHeight()/2); 122 | display->drawLine(display->getWidth()-30, display->getHeight()/2, display->getWidth()-1, display->getHeight()-1); 123 | display->drawLine(display->getWidth()-34, display->getHeight()/2, display->getWidth()-5, display->getHeight()-1); 124 | display->display(); 125 | } 126 | 127 | } 128 | 129 | void DisplayOLED128::blinkArrow(int count) { 130 | 131 | for(int i=0;isetColor(BLACK); 147 | display->fillRect(112, 48, 16, 16); 148 | display->setColor(WHITE); 149 | 150 | display->drawLine(112, 53, 118, 53); 151 | display->drawLine(112, 59, 116, 59); 152 | display->drawLine(116, 63, 119, 49); 153 | display->drawLine(120, 63, 123, 49); 154 | 155 | display->drawLine(122, 53, 127, 53); 156 | display->drawLine(121, 59, 127, 59); 157 | 158 | if(update) 159 | display->display(); 160 | } 161 | } 162 | 163 | void DisplayOLED128::drawConnected(bool update) { 164 | 165 | if(!isResetting && displayEnabled) 166 | { 167 | display->setColor(BLACK); 168 | display->fillRect(112, 48, 16, 16); 169 | if(update) 170 | display->display(); 171 | } 172 | } 173 | 174 | void DisplayOLED128::drawData(unsigned long currentMillis) { 175 | 176 | for(int i=0;igetDataForPosition(currentMillis, i); 179 | if(displayValueData!=NULL) 180 | drawValue(i, displayValueData->getName(), displayValueData->getShortName(), displayValueData->getValue(), displayValueData->getUnit()); 181 | else 182 | clearValue(i); 183 | } 184 | 185 | } 186 | 187 | void DisplayOLED128::clearValue(int position) { 188 | 189 | switch(displayMode) 190 | { 191 | case 1: 192 | clearValueQuad(position); 193 | break; 194 | default: 195 | clearValueClassic(position); 196 | break; 197 | } 198 | 199 | } 200 | 201 | void DisplayOLED128::drawValue(int position, String name, String shortName, String value, String unit) { 202 | 203 | if(firstSensorData) 204 | { 205 | clear(true); 206 | firstSensorData=false; 207 | } 208 | 209 | String valueString = value + " " + unit; 210 | 211 | switch(displayMode) 212 | { 213 | case 1: 214 | drawValueQuad(position, name, shortName, valueString); 215 | break; 216 | case 2: 217 | drawValueClassicRA(position, name, shortName, valueString); 218 | break; 219 | default: 220 | drawValueClassic(position, name, shortName, valueString); 221 | break; 222 | } 223 | 224 | } 225 | 226 | //void DisplayOLED128::drawValue(int position, String name, String shortName, float value, String unit) { 227 | // 228 | // if(firstSensorData) 229 | // { 230 | // clear(true); 231 | // firstSensorData=false; 232 | // } 233 | // 234 | // String valueString = String(value) + " " + unit; 235 | // 236 | // switch(displayMode) 237 | // { 238 | // case 1: 239 | // drawValueQuad(position, name, shortName, valueString); 240 | // break; 241 | // default: 242 | // drawValueClassic(position, name, shortName, valueString); 243 | // break; 244 | // } 245 | // 246 | //} 247 | // 248 | //void DisplayOLED128::drawValue(int position, String name, String shortName, bool value, String onString, String offString) { 249 | // 250 | // if(firstSensorData) 251 | // { 252 | // clear(true); 253 | // firstSensorData=false; 254 | // } 255 | // 256 | // String boolString; 257 | // if(value) 258 | // boolString = onString; 259 | // else 260 | // boolString = offString; 261 | // 262 | // switch(displayMode) 263 | // { 264 | // case 1: 265 | // drawValueQuad(position, name, shortName, boolString); 266 | // break; 267 | // default: 268 | // drawValueClassic(position, name, shortName, boolString); 269 | // break; 270 | // } 271 | // 272 | //} 273 | 274 | void DisplayOLED128::drawValueClassic(int position, String name, String shortName, String valueString) { 275 | 276 | if(!isResetting && displayEnabled) 277 | { 278 | String text = name+": "+valueString; 279 | if(display->getStringWidth(text)>=128) 280 | text = shortName+": "+valueString; 281 | 282 | display->setColor(BLACK); 283 | display->fillRect(0, position*16, 128, 16); 284 | display->setColor(WHITE); 285 | display->drawString(0, position*16, text); 286 | display->display(); 287 | } 288 | 289 | } 290 | 291 | void DisplayOLED128::drawValueClassicRA(int position, String name, String shortName, String valueString) { 292 | 293 | if(!isResetting && displayEnabled) 294 | { 295 | display->setColor(BLACK); 296 | display->fillRect(0, position*16, 128, 16); 297 | display->setColor(WHITE); 298 | 299 | int valueWidth = display->getStringWidth(valueString); 300 | int valuePosition = displayWidth-valueWidth; 301 | 302 | display->drawString(valuePosition, position*16, valueString); 303 | 304 | String text = name+":"; 305 | if(display->getStringWidth(text)>=valuePosition) 306 | { 307 | text = shortName+":"; 308 | } 309 | 310 | display->drawString(0, position*16, text); 311 | display->display(); 312 | } 313 | 314 | } 315 | 316 | void DisplayOLED128::drawValueQuad(int position, String name, String shortName, String valueString) { 317 | 318 | if(!isResetting && displayEnabled) 319 | { 320 | int x=0; 321 | int rectX=0; 322 | int y=0; 323 | int rectY=0; 324 | int w = 64; 325 | int h = 32; 326 | 327 | switch(position) 328 | { 329 | case 0: 330 | break; 331 | case 1: 332 | x = w+3; 333 | rectX = w+1; 334 | break; 335 | case 2: 336 | y = h+3; 337 | rectY = h+1; 338 | break; 339 | case 3: 340 | x = w+3; 341 | rectX = w+1; 342 | y = h+3; 343 | rectY = h+1; 344 | break; 345 | } 346 | 347 | display->setColor(BLACK); 348 | display->fillRect(rectX, rectY, w, h); 349 | display->setColor(WHITE); 350 | 351 | String label = name + ":"; 352 | if(display->getStringWidth(label)>62) 353 | label = shortName + ":"; 354 | 355 | display->drawString(x, y, label); 356 | 357 | String text = valueString; 358 | x = x+(w/2)-(display->getStringWidth(text)/2); 359 | 360 | display->drawString(x,y+16,text); 361 | 362 | display->drawLine(0, h, 2*w-1, h); 363 | display->drawLine(w, 0, w, 2*h-1); 364 | 365 | display->display(); 366 | } 367 | 368 | } 369 | 370 | void DisplayOLED128::clearValueClassic(int position) { 371 | 372 | if(!isResetting && displayEnabled) 373 | { 374 | display->setColor(BLACK); 375 | display->fillRect(0, position*16, 128, 16); 376 | } 377 | 378 | } 379 | 380 | void DisplayOLED128::clearValueQuad(int position) { 381 | 382 | if(!isResetting && displayEnabled) 383 | { 384 | int rectX=0; 385 | int rectY=0; 386 | int w = 63; 387 | int h = 31; 388 | 389 | switch(position) 390 | { 391 | case 0: 392 | break; 393 | case 1: 394 | rectX = w+2; 395 | break; 396 | case 2: 397 | rectY = h+2; 398 | break; 399 | case 3: 400 | rectX = w+2; 401 | rectY = h+2; 402 | break; 403 | } 404 | 405 | display->setColor(BLACK); 406 | display->fillRect(rectX, rectY, w, h); 407 | 408 | display->display(); 409 | } 410 | 411 | } 412 | 413 | int DisplayOLED128::getSimultanValueCount() { 414 | return visibleDataCount; 415 | } 416 | -------------------------------------------------------------------------------- /src/output/display/DisplayOLED128.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file DisplayOLED128.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensatio ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensatio Cloud and the Sensatio apps. 8 | 9 | ----> https://www.sensatio.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v41 - Renamed Display Class to support more types, New Display Mode 15 | v40 - New Display Structure to enable Display Rotation, different Styles etc. 16 | v33 - Added Digital Sensor Switch Support 17 | v30 - Added Support for SSD1306 Displays 18 | v29 - First Public Release 19 | */ 20 | /**************************************************************************/ 21 | 22 | #ifndef _DisplayOLED128_h_ 23 | #define _DisplayOLED128_h_ 24 | 25 | #include "Display.h" 26 | #include "SSD1306Wire.h" 27 | #include "SH1106Wire.h" 28 | 29 | class DisplayOLED128 : public Display { 30 | private: 31 | OLEDDisplay *display; 32 | int type; 33 | public: 34 | DisplayOLED128 (int, int, bool, int, String, uint8_t, uint8_t); 35 | void drawProductLogo(); 36 | void clear(boolean update); 37 | void drawString(int16_t x, int16_t y, String text); 38 | void drawArrow(); 39 | void blinkArrow(int count); 40 | void drawDisconnected(bool update); 41 | void drawConnected(bool update); 42 | void flip(int rotation); 43 | void drawData(unsigned long currentMillis); 44 | void clearValue(int position); 45 | void drawValue(int position, String name, String shortName, String value, String unit); 46 | void drawValueClassic(int position, String name, String shortName, String valueString); 47 | void drawValueClassicRA(int position, String name, String shortName, String valueString); 48 | void drawValueQuad(int position, String name, String shortName, String valueString); 49 | void clearValueClassic(int position); 50 | void clearValueQuad(int position); 51 | int getSimultanValueCount(); 52 | }; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/output/display/DisplayST7735.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file DisplayST7735.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensatio ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensatio Cloud and the Sensatio apps. 8 | 9 | ----> https://www.sensatio.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v42 - Fixed Umlaut Handling 15 | v41 - New Display Type ST7735, New Display Mode 16 | */ 17 | /**************************************************************************/ 18 | 19 | #include "DisplayST7735.h" 20 | 21 | extern bool isResetting; 22 | extern VisualisationHelper* vHelper; 23 | 24 | extern int displayMode; 25 | extern boolean displayEnabled; 26 | extern bool firstSensorData; 27 | 28 | DisplayST7735::DisplayST7735(bool flip, int _type) : Display(_type) { 29 | 30 | if(!isResetting) 31 | { 32 | display = new Adafruit_ST7735(15, 0, 2); 33 | display->initR(INITR_BLACKTAB); 34 | 35 | if(flip) 36 | display->setRotation(3); 37 | else 38 | display->setRotation(1); 39 | 40 | displayWidth = display->width(); // @suppress("Method cannot be resolved") 41 | displayHeight = display->height(); // @suppress("Method cannot be resolved") 42 | 43 | Serial.println("displayWidth "+String(displayWidth)); 44 | Serial.println("displayHeight "+String(displayHeight)); 45 | 46 | visibleDataCount = displayHeight/16; 47 | 48 | Serial.println("visibleDataCount "+String(visibleDataCount)); 49 | 50 | display->fillScreen(ST7735_BLACK); // @suppress("Method cannot be resolved") 51 | 52 | firstSensorData=true; 53 | 54 | } 55 | 56 | } 57 | 58 | void DisplayST7735::clear(boolean update) { 59 | if(!isResetting) 60 | { 61 | display->fillScreen(ST7735_BLACK); // @suppress("Method cannot be resolved") 62 | } 63 | } 64 | 65 | void DisplayST7735::drawProductLogo() { 66 | 67 | int posX = (displayWidth - Product_Logo_width) / 2; 68 | int posY = (displayHeight - Product_Logo_height) / 2; 69 | 70 | display->drawXBitmap(posX, posY, Product_Logo, Product_Logo_width, Product_Logo_height, ST7735_WHITE); // @suppress("Method cannot be resolved") 71 | 72 | } 73 | 74 | void DisplayST7735::drawData(unsigned long currentMillis) { 75 | 76 | for(int i=0;igetDataForPosition(currentMillis, i); 79 | if(displayValueData!=NULL) 80 | drawValue(i, displayValueData->getName(), displayValueData->getShortName(), displayValueData->getValue(), displayValueData->getUnit()); 81 | else 82 | clearValue(i); 83 | } 84 | 85 | } 86 | 87 | void DisplayST7735::drawValue(int position, String name, String shortName, String value, String unit) { 88 | 89 | if(firstSensorData) 90 | { 91 | clear(true); 92 | firstSensorData=false; 93 | } 94 | 95 | String valueString = value + " " + unit; 96 | 97 | switch(displayMode) 98 | { 99 | case 2: 100 | drawValueClassicRA(position, name, shortName, valueString); 101 | break; 102 | default: 103 | drawValueClassic(position, name, shortName, valueString); 104 | break; 105 | } 106 | 107 | } 108 | 109 | void DisplayST7735::drawValueClassic(int position, String name, String shortName, String valueString) { 110 | 111 | if(!isResetting && displayEnabled) 112 | { 113 | 114 | valueString.replace("°",String((char)0xF7)); 115 | 116 | String text = replaceUmlauts(name)+": "+valueString; 117 | 118 | if(getStringWidth(text,8)>=displayWidth) 119 | { 120 | text = replaceUmlauts(shortName)+": "+valueString; 121 | } 122 | 123 | display->setCursor(0, position*16); // @suppress("Method cannot be resolved") 124 | display->setTextColor(ST7735_WHITE, ST7735_BLACK); // @suppress("Method cannot be resolved") 125 | display->print(text); // @suppress("Method cannot be resolved") 126 | 127 | int diffWidth = displayWidth - getStringWidth(text,8); 128 | if(diffWidth>0) 129 | { 130 | display->fillRect(displayWidth-diffWidth, position*16, diffWidth, 16, ST7735_BLACK); // @suppress("Method cannot be resolved") 131 | } 132 | 133 | } 134 | 135 | } 136 | 137 | void DisplayST7735::drawValueClassicRA(int position, String name, String shortName, String valueString) { 138 | 139 | if(!isResetting && displayEnabled) 140 | { 141 | 142 | display->setTextColor(ST7735_WHITE, ST7735_BLACK); // @suppress("Method cannot be resolved") 143 | 144 | valueString.replace("°",String((char)0xF7)); 145 | 146 | int valueWidth = getStringWidth(valueString,8); 147 | int valuePosition = displayWidth-valueWidth; 148 | 149 | display->setCursor(valuePosition, position*16); // @suppress("Method cannot be resolved") 150 | display->print(valueString); // @suppress("Method cannot be resolved") 151 | 152 | String text = replaceUmlauts(name)+":"; 153 | if(getStringWidth(text,8)>=valuePosition) 154 | { 155 | text = replaceUmlauts(shortName)+":"; 156 | } 157 | 158 | display->setCursor(0, position*16); // @suppress("Method cannot be resolved") 159 | display->print(text); // @suppress("Method cannot be resolved") 160 | 161 | int nameWidth = getStringWidth(text,8); 162 | 163 | int diffWidth = displayWidth - nameWidth - valueWidth; 164 | if(diffWidth>0) 165 | { 166 | display->fillRect(nameWidth, position*16, diffWidth, 16, ST7735_BLACK); // @suppress("Method cannot be resolved") 167 | } 168 | 169 | } 170 | 171 | } 172 | 173 | void DisplayST7735::clearValue(int position) { 174 | 175 | switch(displayMode) 176 | { 177 | default: 178 | clearValueClassic(position); 179 | break; 180 | } 181 | 182 | } 183 | 184 | void DisplayST7735::clearValueClassic(int position) { 185 | 186 | if(!isResetting && displayEnabled) 187 | { 188 | display->fillRect(0, position*16, displayWidth, 16, ST7735_BLACK); // @suppress("Method cannot be resolved") 189 | } 190 | 191 | } 192 | 193 | void DisplayST7735::drawString(int16_t x, int16_t y, String text) { 194 | 195 | if(!isResetting && displayEnabled) 196 | { 197 | display->setCursor(x, y); // @suppress("Method cannot be resolved") 198 | display->setTextColor(ST77XX_CYAN, ST7735_BLACK); // @suppress("Method cannot be resolved") 199 | display->print(text); // @suppress("Method cannot be resolved") 200 | } 201 | 202 | } 203 | 204 | void DisplayST7735::drawDisconnected(bool update) { 205 | 206 | if(!isResetting && displayEnabled) 207 | { 208 | display->fillRect(144, 112, 16, 16, ST7735_BLACK); // @suppress("Method cannot be resolved") 209 | 210 | display->drawLine(144, 117, 150, 117, ST7735_CYAN); 211 | display->drawLine(144, 123, 148, 123, ST7735_CYAN); 212 | display->drawLine(148, 127, 151, 113, ST7735_CYAN); 213 | display->drawLine(152, 127, 155, 113, ST7735_CYAN); 214 | 215 | display->drawLine(154, 117, 195, 117, ST7735_CYAN); 216 | display->drawLine(153, 123, 195, 123, ST7735_CYAN); 217 | 218 | } 219 | } 220 | 221 | void DisplayST7735::drawConnected(bool update) { 222 | 223 | if(!isResetting && displayEnabled) 224 | { 225 | display->fillRect(144, 112, 16, 16, ST7735_BLACK); 226 | } 227 | } 228 | 229 | int DisplayST7735::getSimultanValueCount() { 230 | return visibleDataCount; 231 | } 232 | 233 | void DisplayST7735::flip(int rotation) { 234 | if(rotation==0) 235 | display->setRotation(1); 236 | else 237 | display->setRotation(3); 238 | clear(true); 239 | } 240 | 241 | int DisplayST7735::getStringWidth(String text, int textHeight) { 242 | 243 | int16_t x,y; 244 | uint16_t w,h; 245 | 246 | display->getTextBounds(text, 0, 0, &x, &y, &w, &h); // @suppress("Method cannot be resolved") 247 | 248 | if(h>textHeight) 249 | w = w*h/textHeight; 250 | 251 | return w; 252 | 253 | } 254 | 255 | String DisplayST7735::replaceUmlauts(String original) 256 | { 257 | original.replace("ä", String((char)0x84)); 258 | original.replace("ü", String((char)0x81)); 259 | original.replace("ö", String((char)0x94)); 260 | original.replace("ß", String((char)0xE0)); 261 | original.replace("Ä", String((char)0x8E)); 262 | original.replace("Ü", String((char)0x9A)); 263 | original.replace("Ö", String((char)0x99)); 264 | 265 | return original; 266 | } 267 | -------------------------------------------------------------------------------- /src/output/display/DisplayST7735.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file DisplayST7735.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensatio ESP8266 firmware is used to connect ESP8266 based hardware 7 | with the Sensatio Cloud and the Sensatio apps. 8 | 9 | ----> https://www.sensatio.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v42 - Fixed Umlaut Handling 15 | v41 - New Display Type ST7735, New Display Mode 16 | */ 17 | /**************************************************************************/ 18 | 19 | #ifndef _DisplayST7735_h_ 20 | #define _DisplayST7735_h_ 21 | 22 | #include "Display.h" 23 | #include "Adafruit_ST7735.h" 24 | #include 25 | 26 | class DisplayST7735 : public Display { 27 | private: 28 | Adafruit_ST7735 *display; 29 | int type; 30 | String replaceUmlauts(String original); 31 | public: 32 | DisplayST7735 (bool, int); 33 | void drawProductLogo(); 34 | void clear(boolean update); 35 | // void drawString(int16_t x, int16_t y, String text); 36 | // void drawArrow(); 37 | // void blinkArrow(int count); 38 | void drawDisconnected(bool update); 39 | void drawConnected(bool update); 40 | void flip(int rotation); 41 | void drawData(unsigned long currentMillis); 42 | void drawString(int16_t x, int16_t y, String text); 43 | void drawValue(int position, String name, String shortName, String value, String unit); 44 | void clearValue(int position); 45 | int getSimultanValueCount(); 46 | void drawValueClassic(int position, String name, String shortName, String valueString); 47 | void drawValueClassicRA(int position, String name, String shortName, String valueString); 48 | void clearValueClassic(int position); 49 | void clearValueQuad(int position); 50 | int getStringWidth(String text, int); 51 | int getType(); 52 | }; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/output/model/DisplayDataModel.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file DisplayDataModel.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP32 firmware is used to connect ESP32 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v40 - New Display Structure to enable Display Rotation, different Styles etc. 15 | */ 16 | /**************************************************************************/ 17 | 18 | #include "DisplayDataModel.h" 19 | 20 | DisplayDataModel::DisplayDataModel () 21 | { 22 | _count = 0; 23 | } 24 | 25 | int DisplayDataModel::getCount() 26 | { 27 | return _count; 28 | } 29 | 30 | void DisplayDataModel::setData(int position, DisplayValueData* newValueData) 31 | { 32 | if(_count<=position) 33 | { 34 | _count=position+1; 35 | _displayValueData[position] = newValueData; 36 | } 37 | } 38 | 39 | void DisplayDataModel::updateData(int position, float value, String unit) 40 | { 41 | if(position<_count) 42 | _displayValueData[position]->update(value, unit); 43 | } 44 | 45 | void DisplayDataModel::updateData(int position, boolean value, String unit) 46 | { 47 | if(position<_count) 48 | _displayValueData[position]->update(value, unit); 49 | } 50 | 51 | void DisplayDataModel::updateData(int position, String value, String unit) 52 | { 53 | if(position<_count) 54 | _displayValueData[position]->update(value, unit); 55 | } 56 | 57 | DisplayValueData* DisplayDataModel::getData(int position) 58 | { 59 | if(position<_count) 60 | return _displayValueData[position]; 61 | else 62 | return NULL; 63 | } 64 | -------------------------------------------------------------------------------- /src/output/model/DisplayDataModel.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file DisplayDataModel.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP32 firmware is used to connect ESP32 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v40 - New Display Structure to enable Display Rotation, different Styles etc. 15 | */ 16 | /**************************************************************************/ 17 | 18 | #include 19 | #include "DisplayValueData.h" 20 | 21 | #define maxSensorCount 25 22 | 23 | #ifndef _DISPLAYDATAMODEL_h_ 24 | #define _DISPLAYDATAMODEL_h_ 25 | 26 | class DisplayDataModel { 27 | private: 28 | int _count; 29 | DisplayValueData* _displayValueData[maxSensorCount]; 30 | public: 31 | DisplayDataModel (); 32 | int getCount(); 33 | void setData(int, DisplayValueData*); 34 | void updateData(int, float, String); 35 | void updateData(int, boolean, String); 36 | void updateData(int, String, String); 37 | DisplayValueData* getData(int); 38 | }; 39 | 40 | #endif -------------------------------------------------------------------------------- /src/output/model/DisplayValueData.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file DisplayValueData.cpp 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP32 firmware is used to connect ESP32 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v40 - New Display Structure to enable Display Rotation, different Styles etc. 15 | */ 16 | /**************************************************************************/ 17 | 18 | #include "DisplayValueData.h" 19 | 20 | DisplayValueData::DisplayValueData (int position, String name, String shortName, String initValue) 21 | { 22 | _position = position; 23 | _name = name; 24 | _shortName = shortName; 25 | _stringValue = initValue; 26 | _valueType = STRING; 27 | } 28 | 29 | void DisplayValueData::update(float value, String unit) 30 | { 31 | _valueType = FLOAT; 32 | _floatValue = value; 33 | _unit = unit; 34 | } 35 | 36 | void DisplayValueData::update(boolean value, String unit) 37 | { 38 | _valueType = BOOL; 39 | _boolValue = value; 40 | _unit = unit; 41 | } 42 | 43 | void DisplayValueData::update(String value, String unit) 44 | { 45 | _valueType = STRING; 46 | _stringValue = value; 47 | _unit = unit; 48 | } 49 | 50 | int DisplayValueData::getPosition() 51 | { 52 | return _position; 53 | } 54 | 55 | String DisplayValueData::getName() 56 | { 57 | return _name; 58 | } 59 | 60 | String DisplayValueData::getShortName() 61 | { 62 | return _shortName; 63 | } 64 | 65 | String DisplayValueData::getValue() 66 | { 67 | switch (_valueType) 68 | { 69 | case FLOAT: 70 | return String(_floatValue); 71 | case BOOL: 72 | { 73 | if(_boolValue) 74 | return "ON"; 75 | else 76 | return "OFF"; 77 | } 78 | case STRING: 79 | return _stringValue; 80 | } 81 | return ""; 82 | } 83 | 84 | String DisplayValueData::getUnit() 85 | { 86 | return _unit; 87 | } -------------------------------------------------------------------------------- /src/output/model/DisplayValueData.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file DisplayValueData.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP32 firmware is used to connect ESP32 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v40 - New Display Structure to enable Display Rotation, different Styles etc. 15 | */ 16 | /**************************************************************************/ 17 | 18 | #include 19 | #include "valuetype.h" 20 | 21 | #ifndef _DISPLAYVALUEDATA_h_ 22 | #define _DISPLAYVALUEDATA_h_ 23 | 24 | class DisplayValueData { 25 | private: 26 | int _position; 27 | String _name; 28 | String _shortName; 29 | valuetype _valueType; 30 | float _floatValue; 31 | boolean _boolValue; 32 | String _stringValue; 33 | String _unit; 34 | public: 35 | DisplayValueData (int, String, String, String); 36 | void update(float, String); 37 | void update(boolean, String); 38 | void update(String, String); 39 | int getPosition(); 40 | String getName(); 41 | String getShortName(); 42 | String getValue(); 43 | String getUnit(); 44 | }; 45 | 46 | #endif -------------------------------------------------------------------------------- /src/output/model/valuetype.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file valuetype.h 4 | @author M. Fegerl (Sensate Digital Solutions GmbH) 5 | @license GPL (see LICENSE file) 6 | The Sensate ESP32 firmware is used to connect ESP32 based hardware 7 | with the Sensate Cloud and the Sensate apps. 8 | 9 | ----> https://www.sensate.io 10 | 11 | SOURCE: https://github.com/sensate-io/firmware-esp8266.git 12 | 13 | @section HISTORY 14 | v40 - New Display Structure to enable Display Rotation, different Styles etc. 15 | */ 16 | /**************************************************************************/ 17 | 18 | #ifndef _valuetype_h_ 19 | #define _valuetype_h_ 20 | 21 | typedef enum 22 | { 23 | FLOAT, 24 | BOOL, 25 | STRING 26 | } valuetype; 27 | 28 | #endif --------------------------------------------------------------------------------