mirror of https://github.com/arendst/Tasmota.git
Merge branch 'arendst/development' into development
This commit is contained in:
commit
97dee49a93
|
@ -12,12 +12,3 @@ script:
|
|||
- platformio run
|
||||
before_deploy:
|
||||
- for file in .pioenvs/*/firmware.bin; do cp $file ${file%/*}.bin; done
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: I5x8qJ5+229qJv5jSnNPGERQHl0NSKvrVHdpVzr/HOo2zeZ/Q5sMhHWo3IBD3AKjGdSlpyNApDwYTaGvenMe+xtUWSSxYIy2ptWAWfkpOtUMx3lI3brZJRt8s98xS5m972SC9mlNT2ZU+i6hZ6srYv2w4nDuyX+j7Q6IGqvYtabxUWzza/Zg0yNpPScvvzscW1CVhdEd5qYH6OKfBfuVOj3ZG4pCycvbejhkUJwbCQ5m8+DEXUol8BKeh92+TPC3jDHXWIStdgLIrmkZ3YWxMQBgQ41QIkaf6X1/0WYEcY0DFW6hlDzg2GbJ8tPRRPC9dfgMs3ZMKJkc7e4x7wMvG2QXQ0aO6e7xTMw41JZ/OrIit0JDHB1M8bWDPUhHwjiCht4W77n7KWFk9sIUDzOdMdd69BIMt5IohtkjnIT2dXekB4xiNvfPLYUa70aOuSHWi3HXVSE1R7RX0brmNf/mH1Pm91uun3UqtIwhrpD0gteQnc0EAlHoOJOazdn3cohrtmECZJo+f+EiqFfEHT2hBrHPEvWknNfxAyPS7jYWKQ7pTMk+y/BUkLyIQkimvNz41azA6sA75nnQrZ+ZJQa+KP2cEObMBs/ekzA45nds1UXpolI1W8QIOxJ/Y10C1yxr6V5a3WWg1H8EbF0HaqiyIeQx/UCz7gl62CbLEDui9PA=
|
||||
file_glob: true
|
||||
file: ".pioenvs/*.bin"
|
||||
skip_cleanup: true
|
||||
on:
|
||||
tags: true
|
|
@ -15,7 +15,7 @@ If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute!
|
|||
### Development
|
||||
[![Build Status](https://img.shields.io/travis/arendst/Sonoff-Tasmota.svg)](https://travis-ci.org/arendst/Sonoff-Tasmota)
|
||||
|
||||
Current version is **6.1.1b** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for release information and [sonoff/_changelog.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_changelog.ino) for change information.
|
||||
Current version is **6.1.1c** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for release information and [sonoff/_changelog.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_changelog.ino) for change information.
|
||||
|
||||
### Disclaimer
|
||||
:warning: **DANGER OF ELECTROCUTION** :warning:
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
language: c
|
||||
sudo: false
|
||||
|
||||
# Blacklist
|
||||
branches:
|
||||
except:
|
||||
- gh-pages
|
||||
|
||||
env:
|
||||
global:
|
||||
- PRETTYNAME="Adafruit CCS811 Arduino Library"
|
||||
# Optional, will default to "$TRAVIS_BUILD_DIR/Doxyfile"
|
||||
# - DOXYFILE: $TRAVIS_BUILD_DIR/Doxyfile
|
||||
|
||||
before_install:
|
||||
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh)
|
||||
|
||||
install:
|
||||
- arduino --install-library "Adafruit SSD1306","Adafruit GFX Library"
|
||||
|
||||
script:
|
||||
- build_main_platforms
|
||||
|
||||
# Generate and deploy documentation
|
||||
after_success:
|
||||
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/library_check.sh)
|
||||
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/doxy_gen_and_deploy.sh)
|
|
@ -0,0 +1,280 @@
|
|||
#include "Adafruit_CCS811.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Setups the I2C interface and hardware and checks for communication.
|
||||
@param addr Optional I2C address the sensor can be found on. Default is 0x5A
|
||||
@returns True if device is set up, false on any failure
|
||||
*/
|
||||
/**************************************************************************/
|
||||
sint8_t Adafruit_CCS811::begin(uint8_t addr)
|
||||
{
|
||||
_i2caddr = addr;
|
||||
|
||||
_i2c_init();
|
||||
|
||||
SWReset();
|
||||
delay(100);
|
||||
|
||||
//check that the HW id is correct
|
||||
if(this->read8(CCS811_HW_ID) != CCS811_HW_ID_CODE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//try to start the app
|
||||
this->write(CCS811_BOOTLOADER_APP_START, NULL, 0);
|
||||
delay(100);
|
||||
|
||||
//make sure there are no errors and we have entered application mode
|
||||
if(checkError()) {
|
||||
return -2;
|
||||
}
|
||||
if(!_status.FW_MODE) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
disableInterrupt();
|
||||
|
||||
//default to read every second
|
||||
setDriveMode(CCS811_DRIVE_MODE_1SEC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief sample rate of the sensor.
|
||||
@param mode one of CCS811_DRIVE_MODE_IDLE, CCS811_DRIVE_MODE_1SEC, CCS811_DRIVE_MODE_10SEC, CCS811_DRIVE_MODE_60SEC, CCS811_DRIVE_MODE_250MS.
|
||||
*/
|
||||
void Adafruit_CCS811::setDriveMode(uint8_t mode)
|
||||
{
|
||||
_meas_mode.DRIVE_MODE = mode;
|
||||
this->write8(CCS811_MEAS_MODE, _meas_mode.get());
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief enable the data ready interrupt pin on the device.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void Adafruit_CCS811::enableInterrupt()
|
||||
{
|
||||
_meas_mode.INT_DATARDY = 1;
|
||||
this->write8(CCS811_MEAS_MODE, _meas_mode.get());
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief disable the data ready interrupt pin on the device
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void Adafruit_CCS811::disableInterrupt()
|
||||
{
|
||||
_meas_mode.INT_DATARDY = 0;
|
||||
this->write8(CCS811_MEAS_MODE, _meas_mode.get());
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief checks if data is available to be read.
|
||||
@returns True if data is ready, false otherwise.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool Adafruit_CCS811::available()
|
||||
{
|
||||
_status.set(read8(CCS811_STATUS));
|
||||
if(!_status.DATA_READY)
|
||||
return false;
|
||||
else return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief read and store the sensor data. This data can be accessed with getTVOC() and geteCO2()
|
||||
@returns 0 if no error, error code otherwise.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint8_t Adafruit_CCS811::readData()
|
||||
{
|
||||
if(!available())
|
||||
return false;
|
||||
else{
|
||||
uint8_t buf[8];
|
||||
this->read(CCS811_ALG_RESULT_DATA, buf, 8);
|
||||
|
||||
_eCO2 = ((uint16_t)buf[0] << 8) | ((uint16_t)buf[1]);
|
||||
_TVOC = ((uint16_t)buf[2] << 8) | ((uint16_t)buf[3]);
|
||||
|
||||
if(_status.ERROR)
|
||||
return buf[5];
|
||||
|
||||
else return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief set the humidity and temperature compensation for the sensor.
|
||||
@param humidity the humidity data as a percentage. For 55% humidity, pass in integer 55.
|
||||
@param temperature the temperature in degrees C as a decimal number. For 25.5 degrees C, pass in 25.5
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void Adafruit_CCS811::setEnvironmentalData(uint8_t humidity, double temperature)
|
||||
{
|
||||
/* Humidity is stored as an unsigned 16 bits in 1/512%RH. The
|
||||
default value is 50% = 0x64, 0x00. As an example 48.5%
|
||||
humidity would be 0x61, 0x00.*/
|
||||
|
||||
/* Temperature is stored as an unsigned 16 bits integer in 1/512
|
||||
degrees; there is an offset: 0 maps to -25°C. The default value is
|
||||
25°C = 0x64, 0x00. As an example 23.5% temperature would be
|
||||
0x61, 0x00.
|
||||
The internal algorithm uses these values (or default values if
|
||||
not set by the application) to compensate for changes in
|
||||
relative humidity and ambient temperature.*/
|
||||
|
||||
uint8_t hum_perc = humidity << 1;
|
||||
|
||||
float fractional = modf(temperature, &temperature);
|
||||
uint16_t temp_high = (((uint16_t)temperature + 25) << 9);
|
||||
uint16_t temp_low = ((uint16_t)(fractional / 0.001953125) & 0x1FF);
|
||||
|
||||
uint16_t temp_conv = (temp_high | temp_low);
|
||||
|
||||
uint8_t buf[] = {hum_perc, 0x00,
|
||||
(uint8_t)((temp_conv >> 8) & 0xFF), (uint8_t)(temp_conv & 0xFF)};
|
||||
|
||||
this->write(CCS811_ENV_DATA, buf, 4);
|
||||
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief calculate the temperature using the onboard NTC resistor.
|
||||
@returns temperature as a double.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
double Adafruit_CCS811::calculateTemperature()
|
||||
{
|
||||
uint8_t buf[4];
|
||||
this->read(CCS811_NTC, buf, 4);
|
||||
|
||||
uint32_t vref = ((uint32_t)buf[0] << 8) | buf[1];
|
||||
uint32_t vntc = ((uint32_t)buf[2] << 8) | buf[3];
|
||||
|
||||
//from ams ccs811 app note
|
||||
uint32_t rntc = vntc * CCS811_REF_RESISTOR / vref;
|
||||
|
||||
double ntc_temp;
|
||||
ntc_temp = log((double)rntc / CCS811_REF_RESISTOR); // 1
|
||||
ntc_temp /= 3380; // 2
|
||||
ntc_temp += 1.0 / (25 + 273.15); // 3
|
||||
ntc_temp = 1.0 / ntc_temp; // 4
|
||||
ntc_temp -= 273.15; // 5
|
||||
return ntc_temp - _tempOffset;
|
||||
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief set interrupt thresholds
|
||||
@param low_med the level below which an interrupt will be triggered.
|
||||
@param med_high the level above which the interrupt will ge triggered.
|
||||
@param hysteresis optional histeresis level. Defaults to 50
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void Adafruit_CCS811::setThresholds(uint16_t low_med, uint16_t med_high, uint8_t hysteresis)
|
||||
{
|
||||
uint8_t buf[] = {(uint8_t)((low_med >> 8) & 0xF), (uint8_t)(low_med & 0xF),
|
||||
(uint8_t)((med_high >> 8) & 0xF), (uint8_t)(med_high & 0xF), hysteresis};
|
||||
|
||||
this->write(CCS811_THRESHOLDS, buf, 5);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief trigger a software reset of the device
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void Adafruit_CCS811::SWReset()
|
||||
{
|
||||
//reset sequence from the datasheet
|
||||
uint8_t seq[] = {0x11, 0xE5, 0x72, 0x8A};
|
||||
this->write(CCS811_SW_RESET, seq, 4);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief read the status register and store any errors.
|
||||
@returns the error bits from the status register of the device.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool Adafruit_CCS811::checkError()
|
||||
{
|
||||
_status.set(read8(CCS811_STATUS));
|
||||
return _status.ERROR;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief write one byte of data to the specified register
|
||||
@param reg the register to write to
|
||||
@param value the value to write
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void Adafruit_CCS811::write8(byte reg, byte value)
|
||||
{
|
||||
this->write(reg, &value, 1);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief read one byte of data from the specified register
|
||||
@param reg the register to read
|
||||
@returns one byte of register data
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint8_t Adafruit_CCS811::read8(byte reg)
|
||||
{
|
||||
uint8_t ret;
|
||||
this->read(reg, &ret, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Adafruit_CCS811::_i2c_init()
|
||||
{
|
||||
Wire.begin();
|
||||
#ifdef ESP8266
|
||||
Wire.setClockStretchLimit(1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Adafruit_CCS811::read(uint8_t reg, uint8_t *buf, uint8_t num)
|
||||
{
|
||||
uint8_t value;
|
||||
uint8_t pos = 0;
|
||||
|
||||
//on arduino we need to read in 32 byte chunks
|
||||
while(pos < num){
|
||||
|
||||
uint8_t read_now = min((uint8_t)32, (uint8_t)(num - pos));
|
||||
Wire.beginTransmission((uint8_t)_i2caddr);
|
||||
Wire.write((uint8_t)reg + pos);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom((uint8_t)_i2caddr, read_now);
|
||||
|
||||
for(int i=0; i<read_now; i++){
|
||||
buf[pos] = Wire.read();
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Adafruit_CCS811::write(uint8_t reg, uint8_t *buf, uint8_t num)
|
||||
{
|
||||
Wire.beginTransmission((uint8_t)_i2caddr);
|
||||
Wire.write((uint8_t)reg);
|
||||
Wire.write((uint8_t *)buf, num);
|
||||
Wire.endTransmission();
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
#ifndef LIB_ADAFRUIT_CCS811_H
|
||||
#define LIB_ADAFRUIT_CCS811_H
|
||||
|
||||
#if (ARDUINO >= 100)
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
/*=========================================================================
|
||||
I2C ADDRESS/BITS
|
||||
-----------------------------------------------------------------------*/
|
||||
#define CCS811_ADDRESS (0x5A)
|
||||
/*=========================================================================*/
|
||||
|
||||
/*=========================================================================
|
||||
REGISTERS
|
||||
-----------------------------------------------------------------------*/
|
||||
enum
|
||||
{
|
||||
CCS811_STATUS = 0x00,
|
||||
CCS811_MEAS_MODE = 0x01,
|
||||
CCS811_ALG_RESULT_DATA = 0x02,
|
||||
CCS811_RAW_DATA = 0x03,
|
||||
CCS811_ENV_DATA = 0x05,
|
||||
CCS811_NTC = 0x06,
|
||||
CCS811_THRESHOLDS = 0x10,
|
||||
CCS811_BASELINE = 0x11,
|
||||
CCS811_HW_ID = 0x20,
|
||||
CCS811_HW_VERSION = 0x21,
|
||||
CCS811_FW_BOOT_VERSION = 0x23,
|
||||
CCS811_FW_APP_VERSION = 0x24,
|
||||
CCS811_ERROR_ID = 0xE0,
|
||||
CCS811_SW_RESET = 0xFF,
|
||||
};
|
||||
|
||||
//bootloader registers
|
||||
enum
|
||||
{
|
||||
CCS811_BOOTLOADER_APP_ERASE = 0xF1,
|
||||
CCS811_BOOTLOADER_APP_DATA = 0xF2,
|
||||
CCS811_BOOTLOADER_APP_VERIFY = 0xF3,
|
||||
CCS811_BOOTLOADER_APP_START = 0xF4
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CCS811_DRIVE_MODE_IDLE = 0x00,
|
||||
CCS811_DRIVE_MODE_1SEC = 0x01,
|
||||
CCS811_DRIVE_MODE_10SEC = 0x02,
|
||||
CCS811_DRIVE_MODE_60SEC = 0x03,
|
||||
CCS811_DRIVE_MODE_250MS = 0x04,
|
||||
};
|
||||
|
||||
/*=========================================================================*/
|
||||
|
||||
#define CCS811_HW_ID_CODE 0x81
|
||||
|
||||
#define CCS811_REF_RESISTOR 100000
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Class that stores state and functions for interacting with CCS811 gas sensor chips
|
||||
*/
|
||||
/**************************************************************************/
|
||||
class Adafruit_CCS811 {
|
||||
public:
|
||||
//constructors
|
||||
Adafruit_CCS811(void) {};
|
||||
~Adafruit_CCS811(void) {};
|
||||
|
||||
sint8_t begin(uint8_t addr = CCS811_ADDRESS);
|
||||
|
||||
void setEnvironmentalData(uint8_t humidity, double temperature);
|
||||
|
||||
//calculate temperature based on the NTC register
|
||||
double calculateTemperature();
|
||||
|
||||
void setThresholds(uint16_t low_med, uint16_t med_high, uint8_t hysteresis = 50);
|
||||
|
||||
void SWReset();
|
||||
|
||||
void setDriveMode(uint8_t mode);
|
||||
void enableInterrupt();
|
||||
void disableInterrupt();
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief returns the stored total volatile organic compounds measurement. This does does not read the sensor. To do so, call readData()
|
||||
@returns TVOC measurement as 16 bit integer
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint16_t getTVOC() { return _TVOC; }
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief returns the stored estimated carbon dioxide measurement. This does does not read the sensor. To do so, call readData()
|
||||
@returns eCO2 measurement as 16 bit integer
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint16_t geteCO2() { return _eCO2; }
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief set the temperature compensation offset for the device. This is needed to offset errors in NTC measurements.
|
||||
@param offset the offset to be added to temperature measurements.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void setTempOffset(float offset) { _tempOffset = offset; }
|
||||
|
||||
//check if data is available to be read
|
||||
bool available();
|
||||
uint8_t readData();
|
||||
|
||||
bool checkError();
|
||||
|
||||
private:
|
||||
uint8_t _i2caddr;
|
||||
float _tempOffset;
|
||||
|
||||
uint16_t _TVOC;
|
||||
uint16_t _eCO2;
|
||||
|
||||
void write8(byte reg, byte value);
|
||||
void write16(byte reg, uint16_t value);
|
||||
uint8_t read8(byte reg);
|
||||
|
||||
void read(uint8_t reg, uint8_t *buf, uint8_t num);
|
||||
void write(uint8_t reg, uint8_t *buf, uint8_t num);
|
||||
void _i2c_init();
|
||||
|
||||
/*=========================================================================
|
||||
REGISTER BITFIELDS
|
||||
-----------------------------------------------------------------------*/
|
||||
// The status register
|
||||
struct status {
|
||||
|
||||
/* 0: no error
|
||||
* 1: error has occurred
|
||||
*/
|
||||
uint8_t ERROR: 1;
|
||||
|
||||
// reserved : 2
|
||||
|
||||
/* 0: no samples are ready
|
||||
* 1: samples are ready
|
||||
*/
|
||||
uint8_t DATA_READY: 1;
|
||||
uint8_t APP_VALID: 1;
|
||||
|
||||
// reserved : 2
|
||||
|
||||
/* 0: boot mode, new firmware can be loaded
|
||||
* 1: application mode, can take measurements
|
||||
*/
|
||||
uint8_t FW_MODE: 1;
|
||||
|
||||
void set(uint8_t data){
|
||||
ERROR = data & 0x01;
|
||||
DATA_READY = (data >> 3) & 0x01;
|
||||
APP_VALID = (data >> 4) & 0x01;
|
||||
FW_MODE = (data >> 7) & 0x01;
|
||||
}
|
||||
};
|
||||
status _status;
|
||||
|
||||
//measurement and conditions register
|
||||
struct meas_mode {
|
||||
// reserved : 2
|
||||
|
||||
/* 0: interrupt mode operates normally
|
||||
* 1: Interrupt mode (if enabled) only asserts the nINT signal (driven low) if the new
|
||||
ALG_RESULT_DATA crosses one of the thresholds set in the THRESHOLDS register
|
||||
by more than the hysteresis value (also in the THRESHOLDS register)
|
||||
*/
|
||||
uint8_t INT_THRESH: 1;
|
||||
|
||||
/* 0: int disabled
|
||||
* 1: The nINT signal is asserted (driven low) when a new sample is ready in
|
||||
ALG_RESULT_DATA. The nINT signal will stop being driven low when
|
||||
ALG_RESULT_DATA is read on the I²C interface.
|
||||
*/
|
||||
uint8_t INT_DATARDY: 1;
|
||||
|
||||
uint8_t DRIVE_MODE: 3;
|
||||
|
||||
uint8_t get(){
|
||||
return (INT_THRESH << 2) | (INT_DATARDY << 3) | (DRIVE_MODE << 4);
|
||||
}
|
||||
};
|
||||
meas_mode _meas_mode;
|
||||
|
||||
struct error_id {
|
||||
/* The CCS811 received an I²C write request addressed to this station but with
|
||||
invalid register address ID */
|
||||
uint8_t WRITE_REG_INVALID: 1;
|
||||
|
||||
/* The CCS811 received an I²C read request to a mailbox ID that is invalid */
|
||||
uint8_t READ_REG_INVALID: 1;
|
||||
|
||||
/* The CCS811 received an I²C request to write an unsupported mode to
|
||||
MEAS_MODE */
|
||||
uint8_t MEASMODE_INVALID: 1;
|
||||
|
||||
/* The sensor resistance measurement has reached or exceeded the maximum
|
||||
range */
|
||||
uint8_t MAX_RESISTANCE: 1;
|
||||
|
||||
/* The Heater current in the CCS811 is not in range */
|
||||
uint8_t HEATER_FAULT: 1;
|
||||
|
||||
/* The Heater voltage is not being applied correctly */
|
||||
uint8_t HEATER_SUPPLY: 1;
|
||||
|
||||
void set(uint8_t data){
|
||||
WRITE_REG_INVALID = data & 0x01;
|
||||
READ_REG_INVALID = (data & 0x02) >> 1;
|
||||
MEASMODE_INVALID = (data & 0x04) >> 2;
|
||||
MAX_RESISTANCE = (data & 0x08) >> 3;
|
||||
HEATER_FAULT = (data & 0x10) >> 4;
|
||||
HEATER_SUPPLY = (data & 0x20) >> 5;
|
||||
}
|
||||
};
|
||||
error_id _error_id;
|
||||
|
||||
/*=========================================================================*/
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Adafruit Industries
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,13 @@
|
|||
# Adafruit CCS811 Library [![Build Status](https://travis-ci.org/adafruit/Adafruit_CCS811.svg?branch=master)](https://travis-ci.org/adafruit/Adafruit_CCS811)
|
||||
|
||||
<img src="https://cdn-shop.adafruit.com/970x728/3566-00.jpg" height="300"/>
|
||||
|
||||
This is a library for the Adafruit CCS811 gas sensor breakout board:
|
||||
* https://www.adafruit.com/product/3566
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams. This chip uses I2C to communicate
|
||||
|
||||
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
|
||||
|
||||
Written by Dean Miller for Adafruit Industries.
|
||||
MIT license, all text above must be included in any redistribution
|
|
@ -0,0 +1,80 @@
|
|||
/* This demo shows how to display the CCS811 readings on an Adafruit I2C OLED.
|
||||
* (We used a Feather + OLED FeatherWing)
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_GFX.h>
|
||||
|
||||
#include <Adafruit_SSD1306.h>
|
||||
#include "Adafruit_CCS811.h"
|
||||
|
||||
Adafruit_CCS811 ccs;
|
||||
Adafruit_SSD1306 display = Adafruit_SSD1306();
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if(!ccs.begin()){
|
||||
Serial.println("Failed to start sensor! Please check your wiring.");
|
||||
while(1);
|
||||
}
|
||||
|
||||
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
|
||||
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32)
|
||||
|
||||
// Show image buffer on the display hardware.
|
||||
// Since the buffer is intialized with an Adafruit splashscreen
|
||||
// internally, this will display the splashscreen.
|
||||
display.display();
|
||||
delay(500);
|
||||
|
||||
// Clear the buffer.
|
||||
display.clearDisplay();
|
||||
display.display();
|
||||
|
||||
//calibrate temperature sensor
|
||||
while(!ccs.available());
|
||||
float temp = ccs.calculateTemperature();
|
||||
ccs.setTempOffset(temp - 25.0);
|
||||
|
||||
Serial.println("IO test");
|
||||
|
||||
// text display tests
|
||||
display.setTextSize(1);
|
||||
display.setTextColor(WHITE);
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
display.setCursor(0,0);
|
||||
if(ccs.available()){
|
||||
display.clearDisplay();
|
||||
float temp = ccs.calculateTemperature();
|
||||
if(!ccs.readData()){
|
||||
display.print("eCO2: ");
|
||||
Serial.print("eCO2: ");
|
||||
float eCO2 = ccs.geteCO2();
|
||||
display.print(eCO2);
|
||||
Serial.print(eCO2);
|
||||
|
||||
display.print(" ppm\nTVOC: ");
|
||||
Serial.print(" ppm, TVOC: ");
|
||||
float TVOC = ccs.getTVOC();
|
||||
display.print(TVOC);
|
||||
Serial.print(TVOC);
|
||||
|
||||
Serial.print(" ppb Temp:");
|
||||
display.print(" ppb\nTemp: ");
|
||||
Serial.println(temp);
|
||||
display.println(temp);
|
||||
display.display();
|
||||
}
|
||||
else{
|
||||
Serial.println("ERROR!");
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
delay(500);
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/***************************************************************************
|
||||
This is a library for the CCS811 air
|
||||
|
||||
This sketch reads the sensor
|
||||
|
||||
Designed specifically to work with the Adafruit CCS811 breakout
|
||||
----> http://www.adafruit.com/products/3566
|
||||
|
||||
These sensors use I2C to communicate. The device's I2C address is 0x5A
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit andopen-source hardware by purchasing products
|
||||
from Adafruit!
|
||||
|
||||
Written by Dean Miller for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
***************************************************************************/
|
||||
|
||||
#include "Adafruit_CCS811.h"
|
||||
|
||||
Adafruit_CCS811 ccs;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
Serial.println("CCS811 test");
|
||||
|
||||
if(!ccs.begin()){
|
||||
Serial.println("Failed to start sensor! Please check your wiring.");
|
||||
while(1);
|
||||
}
|
||||
|
||||
//calibrate temperature sensor
|
||||
while(!ccs.available());
|
||||
float temp = ccs.calculateTemperature();
|
||||
ccs.setTempOffset(temp - 25.0);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if(ccs.available()){
|
||||
float temp = ccs.calculateTemperature();
|
||||
if(!ccs.readData()){
|
||||
Serial.print("CO2: ");
|
||||
Serial.print(ccs.geteCO2());
|
||||
Serial.print("ppm, TVOC: ");
|
||||
Serial.print(ccs.getTVOC());
|
||||
Serial.print("ppb Temp:");
|
||||
Serial.println(temp);
|
||||
}
|
||||
else{
|
||||
Serial.println("ERROR!");
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
delay(500);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
name=Adafruit CCS811 Library
|
||||
version=1.0.0
|
||||
author=Adafruit
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=This is a library for the Adafruit CCS811 I2C gas sensor breakout.
|
||||
paragraph=This is a library for the Adafruit CCS811 I2C gas sensor breakou.
|
||||
category=Sensors
|
||||
url=https://github.com/adafruit/Adafruit_CCS811
|
||||
architectures=*
|
|
@ -1,14 +1,14 @@
|
|||
# datatypes
|
||||
address_t DATA_TYPE
|
||||
message_t DATA_TYPE
|
||||
callback_id_t DATA_TYPE
|
||||
callback_assignment_id_t DATA_TYPE
|
||||
option_entry_t DATA_TYPE
|
||||
config_id_t DATA_TYPE
|
||||
enable_condition_t DATA_TYPE
|
||||
callback_fptr_t DATA_TYPE
|
||||
feedback_action_fptr_t DATA_TYPE
|
||||
knx_command_type_t DATA_TYPE
|
||||
address_t KEYWORD1 DATA_TYPE
|
||||
message_t KEYWORD1 DATA_TYPE
|
||||
callback_id_t KEYWORD1 DATA_TYPE
|
||||
callback_assignment_id_t KEYWORD1 DATA_TYPE
|
||||
option_entry_t KEYWORD1 DATA_TYPE
|
||||
config_id_t KEYWORD1 DATA_TYPE
|
||||
enable_condition_t KEYWORD1 DATA_TYPE
|
||||
callback_fptr_t KEYWORD1 DATA_TYPE
|
||||
feedback_action_fptr_t KEYWORD1 DATA_TYPE
|
||||
knx_command_type_t KEYWORD1 DATA_TYPE
|
||||
|
||||
# methods
|
||||
setup KEYWORD2
|
||||
|
@ -92,13 +92,13 @@ answer_4byte_int KEYWORD2
|
|||
answer_4byte_uint KEYWORD2
|
||||
answer_4byte_float KEYWORD2
|
||||
|
||||
data_to_1byte_int KEYWORD 2
|
||||
data_to_2byte_int KEYWORD 2
|
||||
data_to_2byte_float KEYWORD 2
|
||||
data_to_4byte_float KEYWORD 2
|
||||
data_to_3byte_color KEYWORD 2
|
||||
data_to_3byte_time KEYWORD 2
|
||||
data_to_3byte_data KEYWORD 2
|
||||
data_to_1byte_int KEYWORD2
|
||||
data_to_2byte_int KEYWORD2
|
||||
data_to_2byte_float KEYWORD2
|
||||
data_to_4byte_float KEYWORD2
|
||||
data_to_3byte_color KEYWORD2
|
||||
data_to_3byte_time KEYWORD2
|
||||
data_to_3byte_data KEYWORD2
|
||||
|
||||
# constants
|
||||
knx LITERAL1
|
||||
knx LITERAL1
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
/* 6.1.1b
|
||||
/* 6.1.1c
|
||||
* Add support for CCS811 sensor (#3309)
|
||||
* Add command Timers 0/1 to globally disable or enable armed timers (#3270)
|
||||
*
|
||||
* 6.1.1b
|
||||
* Add support for MPR121 controller in input mode for touch buttons (#3142)
|
||||
* Add support for MCP230xx for general purpose input expansion and command Sensor29 (#3188)
|
||||
* Fix command Scale buffer overflow (#3236)
|
||||
* Fix rules once regression from v6.1.0 (#3198, #3226)
|
||||
* Add default Wifi Configuration tool as define WIFI_CONFIG_NO_SSID in user_config.h if no SSID is configured (#3224)
|
||||
* Add user selection of Wifi Smartconfig as define USE_SMARTCONFIG in user_config.h
|
||||
* Add user selection of WPS as define USE_WPS in user_config.h in preparation for core v2.4.2 (#3221)
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Подтвърдете рестартирането"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Конфигурация на модула"
|
||||
#define D_CONFIGURE_MCP230XX "Конфигурация на MCP230xx"
|
||||
#define D_CONFIGURE_WIFI "Конфигурация на WiFi"
|
||||
#define D_CONFIGURE_MQTT "Конфигурация на MQTT"
|
||||
#define D_CONFIGURE_DOMOTICZ "Конфигурация на Domoticz"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Конфигуриране на таймер"
|
||||
#define D_TIMER_PARAMETERS "Параметри на таймера"
|
||||
#define D_TIMER_ENABLE "Активиране на таймера"
|
||||
#define D_TIMER_ARM "Arm"
|
||||
#define D_TIMER_TIME "Време"
|
||||
#define D_TIMER_DAYS "Дни"
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Potvrzení restartu"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Nastavení modulu"
|
||||
#define D_CONFIGURE_MCP230XX "Nastavení MCP230xx"
|
||||
#define D_CONFIGURE_WIFI "Nastavení WiFi"
|
||||
#define D_CONFIGURE_MQTT "Nastavení MQTT"
|
||||
#define D_CONFIGURE_DOMOTICZ "Nastavení Domoticz"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Nastavení Časovače"
|
||||
#define D_TIMER_PARAMETERS "Časovač"
|
||||
#define D_TIMER_ENABLE "Povol Časovače"
|
||||
#define D_TIMER_ARM "Aktivní"
|
||||
#define D_TIMER_TIME "Čas"
|
||||
#define D_TIMER_DAYS "Dny"
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Wirklich neustarten?"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Gerät konfigurieren"
|
||||
#define D_CONFIGURE_MCP230XX "MCP230xx konfigurieren"
|
||||
#define D_CONFIGURE_WIFI "WLAN konfigurieren"
|
||||
#define D_CONFIGURE_MQTT "MQTT konfigurieren"
|
||||
#define D_CONFIGURE_DOMOTICZ "Domoticz konfigurieren"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Zeitplan konfigurieren"
|
||||
#define D_TIMER_PARAMETERS "Zeitplan-Einstellungen"
|
||||
#define D_TIMER_ENABLE "Zeitpläne aktivieren"
|
||||
#define D_TIMER_ARM "Aktiv"
|
||||
#define D_TIMER_TIME "Uhrzeit"
|
||||
#define D_TIMER_DAYS "Wochentage"
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Επιβεβαίωση Επανεκκίνησης"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Ρύθμιση Module"
|
||||
#define D_CONFIGURE_MCP230XX "Ρύθμιση MCP230xx"
|
||||
#define D_CONFIGURE_WIFI "Ρύθμιση WiFi"
|
||||
#define D_CONFIGURE_MQTT "Ρύθμιση MQTT"
|
||||
#define D_CONFIGURE_DOMOTICZ "Ρύθμιση Domoticz"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Ρυθμίσεις Χρόνου"
|
||||
#define D_TIMER_PARAMETERS "Χρονικοί παράμετροι"
|
||||
#define D_TIMER_ENABLE "Ενεργοποιημένο Χρονικοί"
|
||||
#define D_TIMER_ARM "Arm"
|
||||
#define D_TIMER_TIME "Ωρα"
|
||||
#define D_TIMER_DAYS "Μέρες"
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Confirm Restart"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Configure Module"
|
||||
#define D_CONFIGURE_MCP230XX "Configure MCP230xx"
|
||||
#define D_CONFIGURE_WIFI "Configure WiFi"
|
||||
#define D_CONFIGURE_MQTT "Configure MQTT"
|
||||
#define D_CONFIGURE_DOMOTICZ "Configure Domoticz"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Configure Timer"
|
||||
#define D_TIMER_PARAMETERS "Timer parameters"
|
||||
#define D_TIMER_ENABLE "Enable Timers"
|
||||
#define D_TIMER_ARM "Arm"
|
||||
#define D_TIMER_TIME "Time"
|
||||
#define D_TIMER_DAYS "Days"
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Confirmar Reinicio"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Configuración del Módulo"
|
||||
#define D_CONFIGURE_MCP230XX "Configuración MCP230xx"
|
||||
#define D_CONFIGURE_WIFI "Configuración WiFi"
|
||||
#define D_CONFIGURE_MQTT "Configuración MQTT"
|
||||
#define D_CONFIGURE_DOMOTICZ "Configuración Domoticz"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Configuración Temporizadores"
|
||||
#define D_TIMER_PARAMETERS "Parámetros de Temporizadores"
|
||||
#define D_TIMER_ENABLE "Habilitar Temporizadores"
|
||||
#define D_TIMER_ARM "Activo"
|
||||
#define D_TIMER_TIME "Hora"
|
||||
#define D_TIMER_DAYS "Días"
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||
* Use online command Prefix to translate cmnd, stat and tele.
|
||||
*
|
||||
* Updated until v5.14.0a
|
||||
* Updated until v6.1.1b
|
||||
\*********************************************************************/
|
||||
|
||||
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Confirmer redémarrage"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Configuration du Module"
|
||||
#define D_CONFIGURE_MCP230XX "Configuration MCP230xx"
|
||||
#define D_CONFIGURE_WIFI "Configuration WiFi"
|
||||
#define D_CONFIGURE_MQTT "Configuration MQTT"
|
||||
#define D_CONFIGURE_DOMOTICZ "Configuration Domoticz"
|
||||
|
@ -241,8 +242,8 @@
|
|||
#define D_MODULE_PARAMETERS "Paramètres module"
|
||||
#define D_MODULE_TYPE "Type de module"
|
||||
#define D_GPIO "GPIO"
|
||||
#define D_SERIAL_IN "Serial In"
|
||||
#define D_SERIAL_OUT "Serial Out"
|
||||
#define D_SERIAL_IN "Entrée série"
|
||||
#define D_SERIAL_OUT "Sortie série"
|
||||
|
||||
#define D_WIFI_PARAMETERS "Paramètres Wifi"
|
||||
#define D_SCAN_FOR_WIFI_NETWORKS "Scan des réseaux wifi"
|
||||
|
@ -321,10 +322,10 @@
|
|||
#define D_UPLOAD_ERR_7 "Téléchargement annulé"
|
||||
#define D_UPLOAD_ERR_8 "Fichier invalide"
|
||||
#define D_UPLOAD_ERR_9 "Fichier trop grand"
|
||||
#define D_UPLOAD_ERR_10 "Failed to init RF chip"
|
||||
#define D_UPLOAD_ERR_11 "Failed to erase RF chip"
|
||||
#define D_UPLOAD_ERR_12 "Failed to write to RF chip"
|
||||
#define D_UPLOAD_ERR_13 "Failed to decode RF firmware"
|
||||
#define D_UPLOAD_ERR_10 "Erreur d'initialisation du chip RF"
|
||||
#define D_UPLOAD_ERR_11 "Erreur d'effacement du chip RF"
|
||||
#define D_UPLOAD_ERR_12 "Erreur d'accès en écriture au chip RF"
|
||||
#define D_UPLOAD_ERR_13 "Erreur de décodage du firmware RF"
|
||||
#define D_UPLOAD_ERROR_CODE "Code d'erreur téléchargement"
|
||||
|
||||
#define D_ENTER_COMMAND "Saisir une commande"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Configuration des Timers"
|
||||
#define D_TIMER_PARAMETERS "Paramètres Timer"
|
||||
#define D_TIMER_ENABLE "Activer des Timers"
|
||||
#define D_TIMER_ARM "Armer"
|
||||
#define D_TIMER_TIME "Temps"
|
||||
#define D_TIMER_DAYS "Jours"
|
||||
|
@ -405,7 +407,7 @@
|
|||
#define D_KNX_COMMAND_OTHER "Autre"
|
||||
#define D_SENT_TO "envoyé à"
|
||||
#define D_KNX_WARNING "L'Adresse de Groupe ( 0 / 0 / 0 ) est réservée et ne peut être utilisée."
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
#define D_KNX_ENHANCEMENT "Amélioration de la communication"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#define D_KNX_RX_SLOT "KNX RX"
|
||||
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Újraindítás megerősítése"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Eszköz konfiguráció"
|
||||
#define D_CONFIGURE_MCP230XX "MCP230xx konfiguráció"
|
||||
#define D_CONFIGURE_WIFI "WiFi konfiguráció"
|
||||
#define D_CONFIGURE_MQTT "MQTT konfiguráció"
|
||||
#define D_CONFIGURE_DOMOTICZ "Domoticz konfiguráció"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Configure Timer"
|
||||
#define D_TIMER_PARAMETERS "Timer parameters"
|
||||
#define D_TIMER_ENABLE "Enable Timers"
|
||||
#define D_TIMER_ARM "Arm"
|
||||
#define D_TIMER_TIME "Time"
|
||||
#define D_TIMER_DAYS "Days"
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Conferma Riavvio"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Configurazione Modulo"
|
||||
#define D_CONFIGURE_MCP230XX "Configurazione MCP230xx"
|
||||
#define D_CONFIGURE_WIFI "Configurazione WiFi"
|
||||
#define D_CONFIGURE_MQTT "Configurazione MQTT"
|
||||
#define D_CONFIGURE_DOMOTICZ "Configurazione Domoticz"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Configura Timer"
|
||||
#define D_TIMER_PARAMETERS "Parametri Timer"
|
||||
#define D_TIMER_ENABLE "Abilita Timers"
|
||||
#define D_TIMER_ARM "Attiva"
|
||||
#define D_TIMER_TIME "Ora"
|
||||
#define D_TIMER_DAYS "Giorni"
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Bevestig herstart"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Configureer Module"
|
||||
#define D_CONFIGURE_MCP230XX "Configureer MCP230xx"
|
||||
#define D_CONFIGURE_WIFI "Configureer WiFi"
|
||||
#define D_CONFIGURE_MQTT "Configureer MQTT"
|
||||
#define D_CONFIGURE_DOMOTICZ "Configureer Domoticz"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Configureer Tijdschakelaar"
|
||||
#define D_TIMER_PARAMETERS "Tijdschakelaar parameters"
|
||||
#define D_TIMER_ENABLE "Tijdschakelaars inschakelen"
|
||||
#define D_TIMER_ARM "Actief"
|
||||
#define D_TIMER_TIME "Tijd"
|
||||
#define D_TIMER_DAYS "Dagen"
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Potwierdź restart"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Konfiguruj moduł"
|
||||
#define D_CONFIGURE_MCP230XX "Konfiguruj MCP230xx"
|
||||
#define D_CONFIGURE_WIFI "Konfiguruj WiFi"
|
||||
#define D_CONFIGURE_MQTT "Konfiguruj MQTT"
|
||||
#define D_CONFIGURE_DOMOTICZ "Konfiguruj Domoticz"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Configure Timer"
|
||||
#define D_TIMER_PARAMETERS "Timer parameters"
|
||||
#define D_TIMER_ENABLE "Enable Timers"
|
||||
#define D_TIMER_ARM "Arm"
|
||||
#define D_TIMER_TIME "Time"
|
||||
#define D_TIMER_DAYS "Days"
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Confirmar o reinicio"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Configurar Módulo"
|
||||
#define D_CONFIGURE_MCP230XX "Configurar MCP230xx"
|
||||
#define D_CONFIGURE_WIFI "Configurar WiFi"
|
||||
#define D_CONFIGURE_MQTT "Configurar MQTT"
|
||||
#define D_CONFIGURE_DOMOTICZ "Configurar Domoticz"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Configurar temporizador"
|
||||
#define D_TIMER_PARAMETERS "Parâmetros"
|
||||
#define D_TIMER_ENABLE "Habilitar temporizadores"
|
||||
#define D_TIMER_ARM "Habilitar"
|
||||
#define D_TIMER_TIME "Horário"
|
||||
#define D_TIMER_DAYS "Dias"
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Confirmar o reinicio"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Configurar Módulo"
|
||||
#define D_CONFIGURE_MCP230XX "Configurar MCP230xx"
|
||||
#define D_CONFIGURE_WIFI "Configurar WiFi"
|
||||
#define D_CONFIGURE_MQTT "Configurar MQTT"
|
||||
#define D_CONFIGURE_DOMOTICZ "Configurar Domoticz"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Configure Timer"
|
||||
#define D_TIMER_PARAMETERS "Timer parameters"
|
||||
#define D_TIMER_ENABLE "Enable Timers"
|
||||
#define D_TIMER_ARM "Arm"
|
||||
#define D_TIMER_TIME "Time"
|
||||
#define D_TIMER_DAYS "Days"
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Подтвердить перезагрузку"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Конфигурация Модуля"
|
||||
#define D_CONFIGURE_MCP230XX "Конфигурация MCP230xx"
|
||||
#define D_CONFIGURE_WIFI "Конфигурация WiFi"
|
||||
#define D_CONFIGURE_MQTT "Конфигурация MQTT"
|
||||
#define D_CONFIGURE_DOMOTICZ "Конфигурация Domoticz"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Configure Timer"
|
||||
#define D_TIMER_PARAMETERS "Timer parameters"
|
||||
#define D_TIMER_ENABLE "Enable Timers"
|
||||
#define D_TIMER_ARM "Arm"
|
||||
#define D_TIMER_TIME "Time"
|
||||
#define D_TIMER_DAYS "Days"
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "Підтвердити перезавантаження"
|
||||
|
||||
#define D_CONFIGURE_MODULE "Конфігурація модуля"
|
||||
#define D_CONFIGURE_MCP230XX "Конфігурація MCP230xx"
|
||||
#define D_CONFIGURE_WIFI "Конфігурація WiFi"
|
||||
#define D_CONFIGURE_MQTT "Конфігурація MQTT"
|
||||
#define D_CONFIGURE_DOMOTICZ "Конфігурація Domoticz"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Конфігурація таймеру"
|
||||
#define D_TIMER_PARAMETERS "Налаштування таймеру"
|
||||
#define D_TIMER_ENABLE "Увімкнений таймеру"
|
||||
#define D_TIMER_ARM "Увімкнений"
|
||||
#define D_TIMER_TIME "Час"
|
||||
#define D_TIMER_DAYS "Дні"
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "确认重启"
|
||||
|
||||
#define D_CONFIGURE_MODULE "模块设置"
|
||||
#define D_CONFIGURE_MCP230XX "MCP230xx设置"
|
||||
#define D_CONFIGURE_WIFI "WiFi设置"
|
||||
#define D_CONFIGURE_MQTT "MQTT设置"
|
||||
#define D_CONFIGURE_DOMOTICZ "Domoticz设置"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "定时器设置"
|
||||
#define D_TIMER_PARAMETERS "定时器参数"
|
||||
#define D_TIMER_ENABLE "启用定时器"
|
||||
#define D_TIMER_ARM "启用"
|
||||
#define D_TIMER_TIME "时间"
|
||||
#define D_TIMER_DAYS "天"
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define D_CONFIRM_RESTART "確認重啟"
|
||||
|
||||
#define D_CONFIGURE_MODULE "模塊設置"
|
||||
#define D_CONFIGURE_MCP230XX "MCP230xx設置"
|
||||
#define D_CONFIGURE_WIFI "WiFi設置"
|
||||
#define D_CONFIGURE_MQTT "MQTT設置"
|
||||
#define D_CONFIGURE_DOMOTICZ "Domoticz設置"
|
||||
|
@ -379,6 +380,7 @@
|
|||
// xdrv_09_timers.ino
|
||||
#define D_CONFIGURE_TIMER "Configure Timer"
|
||||
#define D_TIMER_PARAMETERS "Timer parameters"
|
||||
#define D_TIMER_ENABLE "Enable Timers"
|
||||
#define D_TIMER_ARM "Arm"
|
||||
#define D_TIMER_TIME "Time"
|
||||
#define D_TIMER_DAYS "Days"
|
||||
|
|
|
@ -63,7 +63,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
|||
typedef union { // Restricted by MISRA-C Rule 18.4 but so usefull...
|
||||
uint32_t data; // Allow bit manipulation using SetOption
|
||||
struct { // SetOption50 .. SetOption81
|
||||
uint32_t spare00 : 1;
|
||||
uint32_t timers_enable : 1; // bit 0 (v6.1.1b)
|
||||
uint32_t spare01 : 1;
|
||||
uint32_t spare02 : 1;
|
||||
uint32_t spare03 : 1;
|
||||
|
@ -155,11 +155,9 @@ typedef union {
|
|||
typedef union {
|
||||
uint8_t data;
|
||||
struct {
|
||||
uint8_t enable : 1; // Enable INPUT
|
||||
uint8_t pinmode : 3; // Enable INPUT
|
||||
uint8_t pullup : 1; // Enable internal weak pull-up resistor
|
||||
uint8_t inten : 1; // Enable Interrupt on PIN
|
||||
uint8_t intmode : 1; // Change on STATE or match COMPARATOR
|
||||
uint8_t intcomp : 1; // Interrupt COMPARATOR
|
||||
uint8_t b4 : 1;
|
||||
uint8_t b5 : 1;
|
||||
uint8_t b6 : 1;
|
||||
uint8_t b7 : 1;
|
||||
|
@ -413,4 +411,4 @@ typedef union {
|
|||
ADC_MODE(ADC_VCC); // Set ADC input for Power Supply Voltage usage
|
||||
#endif
|
||||
|
||||
#endif // _SETTINGS_H_
|
||||
#endif // _SETTINGS_H_
|
||||
|
|
|
@ -782,6 +782,9 @@ void SettingsDelta()
|
|||
Settings.flag.rules_once = 0;
|
||||
Settings.flag3.data = 0;
|
||||
}
|
||||
if (Settings.version < 0x06010103) {
|
||||
Settings.flag3.timers_enable = 1;
|
||||
}
|
||||
|
||||
Settings.version = VERSION;
|
||||
SettingsSave(1);
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
- Select IDE Tools - Flash Size: "1M (no SPIFFS)"
|
||||
====================================================*/
|
||||
|
||||
#define VERSION 0x06010102 // 6.1.1b
|
||||
#define VERSION 0x06010103 // 6.1.1c
|
||||
|
||||
// Location specific includes
|
||||
#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
|
||||
|
@ -188,6 +188,9 @@ uint8_t ntp_force_sync = 0; // Force NTP sync
|
|||
StateBitfield global_state;
|
||||
RulesBitfield rules_flag;
|
||||
|
||||
uint8_t glob_humidity = 0;
|
||||
sint16_t glob_temperature = -9999;
|
||||
|
||||
char my_version[33]; // Composed version string
|
||||
char my_hostname[33]; // Composed Wifi hostname
|
||||
char mqtt_client[33]; // Composed MQTT Clientname
|
||||
|
|
|
@ -80,6 +80,7 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
|||
#define USE_INA219 // Add I2C code for INA219 Low voltage and current sensor (+1k code)
|
||||
#define USE_MGS // Add I2C code for Xadow and Grove Mutichannel Gas sensor using library Multichannel_Gas_Sensor (+10k code)
|
||||
//#define USE_APDS9960 // Add I2C code for APDS9960 Proximity Sensor. Disables SHT and VEML6070 (+4k7 code)
|
||||
//#define USE_CCS811 // Add I2C code for CCS811 sensor (+2k2 code)
|
||||
#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code)
|
||||
#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code)
|
||||
#ifndef CO2_LOW
|
||||
|
|
|
@ -130,6 +130,24 @@ size_t strchrspn(const char *str1, int character)
|
|||
return ret;
|
||||
}
|
||||
|
||||
// Function to return a substring defined by a delimiter at an index
|
||||
char* subStr(char* dest, char* str, const char *delim, int index)
|
||||
{
|
||||
char *act;
|
||||
char *sub;
|
||||
char *ptr;
|
||||
int i;
|
||||
|
||||
// Since strtok consumes the first arg, make a copy
|
||||
strncpy(dest, str, strlen(str));
|
||||
for (i = 1, act = dest; i <= index; i++, act = NULL) {
|
||||
sub = strtok_r(act, delim, &ptr);
|
||||
if (sub == NULL) break;
|
||||
}
|
||||
sub = Trim(sub);
|
||||
return sub;
|
||||
}
|
||||
|
||||
double CharToDouble(char *str)
|
||||
{
|
||||
// simple ascii to double, because atof or strtod are too large
|
||||
|
|
|
@ -237,7 +237,8 @@
|
|||
//#define USE_MQTT_TLS // Use TLS for MQTT connection (+53k code, +15k mem)
|
||||
|
||||
// -- KNX IP Protocol -----------------------------
|
||||
//#define USE_KNX // Enable KNX IP Protocol Support (+23k code, +3k3 mem)
|
||||
//#define USE_KNX // Enable KNX IP Protocol Support (+9.4k code, +3k7 mem)
|
||||
#define USE_KNX_WEB_MENU // Enable KNX WEB MENU (+8.3k code, +144 mem)
|
||||
|
||||
// -- HTTP ----------------------------------------
|
||||
#define USE_WEBSERVER // Enable web server and Wifi Manager (+66k code, +8k mem)
|
||||
|
@ -270,23 +271,26 @@
|
|||
// -- I2C sensors ---------------------------------
|
||||
#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram)
|
||||
#ifdef USE_I2C
|
||||
#define USE_SHT // Add I2C emulating code for SHT1X sensor (+1k4 code)
|
||||
#define USE_SHT3X // Add I2C code for SHT3x or SHTC3 sensor (+0k7 code)
|
||||
#define USE_HTU // Add I2C code for HTU21/SI7013/SI7020/SI7021 sensor (+1k5 code)
|
||||
#define USE_LM75AD // Add I2C code for LM75AD sensor (+0k5 code)
|
||||
#define USE_BMP // Add I2C code for BMP085/BMP180/BMP280/BME280 sensor (+4k code)
|
||||
// #define USE_BME680 // Add additional support for BME680 sensor using Bosch BME680 library (+4k code)
|
||||
#define USE_SGP30 // Add I2C code for SGP30 sensor (+1k1 code)
|
||||
#define USE_BH1750 // Add I2C code for BH1750 sensor (+0k5 code)
|
||||
// #define USE_VEML6070 // Add I2C code for VEML6070 sensor (+0k5 code)
|
||||
// #define USE_TSL2561 // Add I2C code for TSL2561 sensor using library Joba_Tsl2561 (+2k3 code)
|
||||
// #define USE_SI1145 // Add I2C code for SI1145/46/47 sensor (+1k code)
|
||||
// #define USE_ADS1115 // Add I2C code for ADS1115 16 bit A/D converter based on Adafruit ADS1x15 library (no library needed) (+0k7 code)
|
||||
// #define USE_ADS1115_I2CDEV // Add I2C code for ADS1115 16 bit A/D converter using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code)
|
||||
// #define USE_INA219 // Add I2C code for INA219 Low voltage and current sensor (+1k code)
|
||||
// #define USE_MGS // Add I2C code for Xadow and Grove Mutichannel Gas sensor using library Multichannel_Gas_Sensor (+10k code)
|
||||
#define USE_SHT // Enable SHT1X sensor (+1k4 code)
|
||||
#define USE_HTU // Enable HTU21/SI7013/SI7020/SI7021 sensor (I2C address 0x40) (+1k5 code)
|
||||
#define USE_BMP // Enable BMP085/BMP180/BMP280/BME280 sensor (I2C address 0x76 or 0x77) (+4k code)
|
||||
#define USE_BME680 // Enable support for BME680 sensor using Bosch BME680 library (+4k code)
|
||||
#define USE_BH1750 // Enable BH1750 sensor (I2C address 0x23 or 0x5C) (+0k5 code)
|
||||
// #define USE_VEML6070 // Enable VEML6070 sensor (I2C addresses 0x38 and 0x39) (+0k5 code)
|
||||
// #define USE_ADS1115 // Enable ADS1115 16 bit A/D converter (I2C address 0x48, 0x49, 0x4A or 0x4B) based on Adafruit ADS1x15 library (no library needed) (+0k7 code)
|
||||
// #define USE_ADS1115_I2CDEV // Enable ADS1115 16 bit A/D converter (I2C address 0x48, 0x49, 0x4A or 0x4B) using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code)
|
||||
// #define USE_INA219 // Enable INA219 (I2C address 0x40, 0x41 0x44 or 0x45) Low voltage and current sensor (+1k code)
|
||||
#define USE_SHT3X // Enable SHT3x (I2C address 0x44 or 0x45) or SHTC3 (I2C address 0x70) sensor (+0k7 code)
|
||||
// #define USE_TSL2561 // Enable TSL2561 sensor (I2C address 0x29, 0x39 or 0x49) using library Joba_Tsl2561 (+2k3 code)
|
||||
// #define USE_MGS // Enable Xadow and Grove Mutichannel Gas sensor using library Multichannel_Gas_Sensor (+10k code)
|
||||
#define MGS_SENSOR_ADDR 0x04 // Default Mutichannel Gas sensor i2c address
|
||||
// #define USE_APDS9960 // Add I2C code for APDS9960 Proximity Sensor. Disables SHT and VEML6070 (+4k7 code)
|
||||
#define USE_SGP30 // Enable SGP30 sensor (I2C address 0x58) (+1k1 code)
|
||||
// #define USE_SI1145 // Enable SI1145/46/47 sensor (I2C address 0x60) (+1k code)
|
||||
#define USE_LM75AD // Enable LM75AD sensor (I2C addresses 0x48 - 0x4F) (+0k5 code)
|
||||
// #define USE_APDS9960 // Enable APDS9960 Proximity Sensor (I2C address 0x39). Disables SHT and VEML6070 (+4k7 code)
|
||||
// #define USE_MCP230xx // Enable MCP23008/MCP23017 for GP INPUT ONLY (I2C addresses 0x20 - 0x27) providing command Sensor29 for configuration (+2k2 code)
|
||||
// #define USE_MPR121 // Enable MPR121 controller (I2C addresses 0x5A, 0x5B, 0x5C and 0x5D) in input mode for touch buttons (+1k3 code)
|
||||
// #define USE_CCS811 // Enable CCS811 sensor (I2C address 0x5A) (+2k2 code)
|
||||
#endif // USE_I2C
|
||||
|
||||
// -- SPI sensors ---------------------------------
|
||||
|
|
|
@ -204,7 +204,9 @@ const char HTTP_BTN_MENU_MQTT[] PROGMEM =
|
|||
"";
|
||||
const char HTTP_BTN_MENU4[] PROGMEM =
|
||||
#ifdef USE_KNX
|
||||
#ifdef USE_KNX_WEB_MENU
|
||||
"<br/><form action='kn' method='get'><button>" D_CONFIGURE_KNX "</button></form>"
|
||||
#endif // USE_KNX_WEB_MENU
|
||||
#endif // USE_KNX
|
||||
"<br/><form action='lg' method='get'><button>" D_CONFIGURE_LOGGING "</button></form>"
|
||||
"<br/><form action='co' method='get'><button>" D_CONFIGURE_OTHER "</button></form>"
|
||||
|
@ -391,7 +393,9 @@ void StartWebserver(int type, IPAddress ipweb)
|
|||
#endif // USE_DOMOTICZ
|
||||
}
|
||||
#ifdef USE_KNX
|
||||
#ifdef USE_KNX_WEB_MENU
|
||||
WebServer->on("/kn", HandleKNXConfiguration);
|
||||
#endif // USE_KNX_WEB_MENU
|
||||
#endif // USE_KNX
|
||||
WebServer->on("/lg", HandleLoggingConfiguration);
|
||||
WebServer->on("/co", HandleOtherConfiguration);
|
||||
|
|
|
@ -262,7 +262,7 @@ void TimerEverySecond()
|
|||
{
|
||||
if (RtcTime.valid) {
|
||||
if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second) { TimerSetRandomWindows(); } // Midnight
|
||||
if ((uptime > 60) && (RtcTime.minute != timer_last_minute)) { // Execute from one minute after restart every minute only once
|
||||
if (Settings.flag3.timers_enable && (uptime > 60) && (RtcTime.minute != timer_last_minute)) { // Execute from one minute after restart every minute only once
|
||||
timer_last_minute = RtcTime.minute;
|
||||
int16_t time = (RtcTime.hour *60) + RtcTime.minute;
|
||||
uint8_t days = 1 << (RtcTime.day_of_week -1);
|
||||
|
@ -451,11 +451,15 @@ boolean TimerCommand()
|
|||
}
|
||||
}
|
||||
else if (CMND_TIMERS == command_code) {
|
||||
if (XdrvMailbox.data_len && (XdrvMailbox.payload == 0)) {
|
||||
for (byte i = 0; i < MAX_TIMERS; i++) {
|
||||
Settings.timer[i].arm = 0; // Disable all timers
|
||||
if (XdrvMailbox.data_len) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
|
||||
Settings.flag3.timers_enable = XdrvMailbox.payload;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag3.timers_enable));
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, command);
|
||||
|
||||
byte jsflg = 0;
|
||||
byte lines = 1;
|
||||
for (byte i = 0; i < MAX_TIMERS; i++) {
|
||||
|
@ -633,7 +637,9 @@ const char HTTP_TIMER_STYLE[] PROGMEM =
|
|||
"</style>";
|
||||
const char HTTP_FORM_TIMER[] PROGMEM =
|
||||
"<fieldset style='min-width:470px;text-align:center;'><legend style='text-align:left;'><b> " D_TIMER_PARAMETERS " </b></legend><form method='post' action='sv'>"
|
||||
"<input id='w' name='w' value='7,0' hidden><input id='t0' name='t0' value='";
|
||||
"<input id='w' name='w' value='7,0' hidden>"
|
||||
"<br/><input style='width:5%;' id='e0' name='e0' type='checkbox'{e0><b>" D_TIMER_ENABLE "</b><br/><br/><hr/>"
|
||||
"<input id='t0' name='t0' value='";
|
||||
const char HTTP_FORM_TIMER1[] PROGMEM =
|
||||
"' hidden><div id='bt' name='bt'></div><br/><br/><br/>"
|
||||
"<div id='oa' name='oa'></div><br/>"
|
||||
|
@ -679,6 +685,7 @@ void HandleTimerConfiguration()
|
|||
page += FPSTR(HTTP_HEAD_STYLE);
|
||||
page.replace(F("</style>"), FPSTR(HTTP_TIMER_STYLE));
|
||||
page += FPSTR(HTTP_FORM_TIMER);
|
||||
page.replace(F("{e0"), (Settings.flag3.timers_enable) ? F(" checked") : F(""));
|
||||
for (byte i = 0; i < MAX_TIMERS; i++) {
|
||||
if (i > 0) { page += F(","); }
|
||||
page += String(Settings.timer[i].data);
|
||||
|
@ -702,9 +709,10 @@ void TimerSaveSettings()
|
|||
char tmp[MAX_TIMERS *12]; // Need space for MAX_TIMERS x 10 digit numbers separated by a comma
|
||||
Timer timer;
|
||||
|
||||
Settings.flag3.timers_enable = WebServer->hasArg("e0");
|
||||
WebGetArg("t0", tmp, sizeof(tmp));
|
||||
char *p = tmp;
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_TIMERS " "));
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_TIMERS " %d"), Settings.flag3.timers_enable);
|
||||
for (byte i = 0; i < MAX_TIMERS; i++) {
|
||||
timer.data = strtol(p, &p, 10);
|
||||
p++; // Skip comma
|
||||
|
@ -713,7 +721,7 @@ void TimerSaveSettings()
|
|||
Settings.timer[i].data = timer.data;
|
||||
if (flag) TimerSetRandomWindow(i);
|
||||
}
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("%s%s0x%08X"), log_data, (i > 0)?",":"", Settings.timer[i].data);
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("%s,0x%08X"), log_data, Settings.timer[i].data);
|
||||
}
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
}
|
||||
|
|
|
@ -253,7 +253,7 @@ bool RulesRuleMatch(byte rule_set, String &event, String &rule)
|
|||
}
|
||||
} else match = true;
|
||||
|
||||
if (Settings.flag.rules_once) {
|
||||
if (bitRead(Settings.rule_once, rule_set)) {
|
||||
if (match) { // Only allow match state changes
|
||||
if (!bitRead(rules_triggers[rule_set], rules_trigger_count[rule_set])) {
|
||||
bitSet(rules_triggers[rule_set], rules_trigger_count[rule_set]);
|
||||
|
@ -557,44 +557,38 @@ boolean RulesCommand()
|
|||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]);
|
||||
}
|
||||
else if ((CMND_ADD == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) {
|
||||
if ( XdrvMailbox.data_len > 0 ) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
double tempvar = CharToDouble(vars[index -1]) + CharToDouble(XdrvMailbox.data);
|
||||
dtostrfd(tempvar,2,vars[index -1]);
|
||||
dtostrfd(tempvar, 2, vars[index -1]);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]);
|
||||
}
|
||||
else if ((CMND_SUB == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) {
|
||||
if ( XdrvMailbox.data_len > 0 ){
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
double tempvar = CharToDouble(vars[index -1]) - CharToDouble(XdrvMailbox.data);
|
||||
dtostrfd(tempvar,2,vars[index -1]);
|
||||
dtostrfd(tempvar, 2, vars[index -1]);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]);
|
||||
}
|
||||
else if ((CMND_MULT == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) {
|
||||
if ( XdrvMailbox.data_len > 0 ){
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
double tempvar = CharToDouble(vars[index -1]) * CharToDouble(XdrvMailbox.data);
|
||||
dtostrfd(tempvar,2,vars[index -1]);
|
||||
dtostrfd(tempvar, 2, vars[index -1]);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]);
|
||||
}
|
||||
else if ((CMND_SCALE == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) {
|
||||
if ( XdrvMailbox.data_len > 0 ) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry
|
||||
double value = 0;
|
||||
double valueIN = 0;
|
||||
double fromLow = 0;
|
||||
double fromHigh = 0;
|
||||
double toLow = 0;
|
||||
double toHigh = 0;
|
||||
char sub_string[XdrvMailbox.data_len +1];
|
||||
|
||||
valueIN = CharToDouble(subStr(XdrvMailbox.data, ",", 1));
|
||||
fromLow = CharToDouble(subStr(XdrvMailbox.data, ",", 2));
|
||||
fromHigh = CharToDouble(subStr(XdrvMailbox.data, ",", 3));
|
||||
toLow = CharToDouble(subStr(XdrvMailbox.data, ",", 4));
|
||||
toHigh = CharToDouble(subStr(XdrvMailbox.data, ",", 5));
|
||||
|
||||
value = map_double(valueIN, fromLow, fromHigh, toLow, toHigh);
|
||||
dtostrfd(value,2,vars[index -1]);
|
||||
double valueIN = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 1));
|
||||
double fromLow = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 2));
|
||||
double fromHigh = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 3));
|
||||
double toLow = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 4));
|
||||
double toHigh = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 5));
|
||||
double value = map_double(valueIN, fromLow, fromHigh, toLow, toHigh);
|
||||
dtostrfd(value, 2, vars[index -1]);
|
||||
}
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]);
|
||||
|
@ -609,25 +603,6 @@ double map_double(double x, double in_min, double in_max, double out_min, double
|
|||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
|
||||
// Function to return a substring defined by a delimiter at an index
|
||||
char* subStr (char* str, const char *delim, int index) {
|
||||
char *act, *sub, *ptr;
|
||||
static char copy[10];
|
||||
int i;
|
||||
|
||||
// Since strtok consumes the first arg, make a copy
|
||||
strcpy(copy, str);
|
||||
|
||||
for (i = 1, act = copy; i <= index; i++, act = NULL) {
|
||||
sub = strtok_r(act, delim, &ptr);
|
||||
if (sub == NULL) break;
|
||||
}
|
||||
sub = LTrim(sub);
|
||||
sub = RTrim(sub);
|
||||
return sub;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
|
|
@ -196,9 +196,15 @@ const char *device_param_cb[] = {
|
|||
// Commands
|
||||
#define D_CMND_KNXTXCMND "KnxTx_Cmnd"
|
||||
#define D_CMND_KNXTXVAL "KnxTx_Val"
|
||||
enum KnxCommands { CMND_KNXTXCMND, CMND_KNXTXVAL };
|
||||
const char kKnxCommands[] PROGMEM = D_CMND_KNXTXCMND "|" D_CMND_KNXTXVAL ;
|
||||
|
||||
#define D_CMND_KNX_ENABLED "Knx_Enabled"
|
||||
#define D_CMND_KNX_ENHANCED "Knx_Enhanced"
|
||||
#define D_CMND_KNX_PA "Knx_PA"
|
||||
#define D_CMND_KNX_GA "Knx_GA"
|
||||
#define D_CMND_KNX_CB "Knx_CB"
|
||||
enum KnxCommands { CMND_KNXTXCMND, CMND_KNXTXVAL, CMND_KNX_ENABLED, CMND_KNX_ENHANCED, CMND_KNX_PA,
|
||||
CMND_KNX_GA, CMND_KNX_CB } ;
|
||||
const char kKnxCommands[] PROGMEM = D_CMND_KNXTXCMND "|" D_CMND_KNXTXVAL "|" D_CMND_KNX_ENABLED "|"
|
||||
D_CMND_KNX_ENHANCED "|" D_CMND_KNX_PA "|" D_CMND_KNX_GA "|" D_CMND_KNX_CB ;
|
||||
|
||||
byte KNX_GA_Search( byte param, byte start = 0 )
|
||||
{
|
||||
|
@ -517,14 +523,27 @@ void KNX_INIT()
|
|||
void KNX_CB_Action(message_t const &msg, void *arg)
|
||||
{
|
||||
device_parameters_t *chan = (device_parameters_t *)arg;
|
||||
|
||||
if (!(Settings.flag.knx_enabled)) { return; }
|
||||
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %d " D_TO " %s"),
|
||||
msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member,
|
||||
(msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER,
|
||||
msg.data[0],
|
||||
device_param_cb[(chan->type)-1]);
|
||||
char tempchar[25];
|
||||
|
||||
if (msg.data_len == 1) {
|
||||
// COMMAND
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %d " D_TO " %s"),
|
||||
msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member,
|
||||
(msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER,
|
||||
msg.data[0],
|
||||
device_param_cb[(chan->type)-1]);
|
||||
} else {
|
||||
// VALUE
|
||||
float tempvar = knx.data_to_2byte_float(msg.data);
|
||||
dtostrfd(tempvar,2,tempchar);
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %s " D_TO " %s"),
|
||||
msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member,
|
||||
(msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER,
|
||||
tempchar,
|
||||
device_param_cb[(chan->type)-1]);
|
||||
}
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
|
||||
switch (msg.ct)
|
||||
|
@ -548,7 +567,13 @@ void KNX_CB_Action(message_t const &msg, void *arg)
|
|||
{
|
||||
if (!toggle_inhibit) {
|
||||
char command[25];
|
||||
snprintf_P(command, sizeof(command), PSTR("event KNXRX_CMND%d=%d"), ((chan->type) - KNX_SLOT1 + 1 ), msg.data[0]);
|
||||
if (msg.data_len == 1) {
|
||||
// Command received
|
||||
snprintf_P(command, sizeof(command), PSTR("event KNXRX_CMND%d=%d"), ((chan->type) - KNX_SLOT1 + 1 ), msg.data[0]);
|
||||
} else {
|
||||
// Value received
|
||||
snprintf_P(command, sizeof(command), PSTR("event KNXRX_VAL%d=%s"), ((chan->type) - KNX_SLOT1 + 1 ), tempchar);
|
||||
}
|
||||
ExecuteCommand(command, SRC_KNX);
|
||||
if (Settings.flag.knx_enable_enhancement) {
|
||||
toggle_inhibit = TOGGLE_INHIBIT_TIME;
|
||||
|
@ -697,6 +722,7 @@ void KnxSensor(byte sensor_type, float value)
|
|||
\*********************************************************************************************/
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
#ifdef USE_KNX_WEB_MENU
|
||||
const char S_CONFIGURE_KNX[] PROGMEM = D_CONFIGURE_KNX;
|
||||
|
||||
const char HTTP_FORM_KNX[] PROGMEM =
|
||||
|
@ -1001,6 +1027,7 @@ void KNX_Save_Settings()
|
|||
}
|
||||
}
|
||||
|
||||
#endif // USE_KNX_WEB_MENU
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
|
||||
|
@ -1010,14 +1037,12 @@ boolean KnxCommand()
|
|||
uint8_t index = XdrvMailbox.index;
|
||||
int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kKnxCommands);
|
||||
|
||||
if (!(Settings.flag.knx_enabled)) { return false; }
|
||||
|
||||
if (-1 == command_code) { return false; } // Unknown command
|
||||
|
||||
else if ((CMND_KNXTXCMND == command_code) && (index > 0) && (index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0)) {
|
||||
// index <- KNX SLOT to use
|
||||
// XdrvMailbox.payload <- data to send
|
||||
|
||||
if (!(Settings.flag.knx_enabled)) { return false; }
|
||||
// Search all the registered GA that has that output (variable: KNX SLOTx) as parameter
|
||||
byte i = KNX_GA_Search(index + KNX_SLOT1 -1);
|
||||
while ( i != KNX_Empty ) {
|
||||
|
@ -1035,12 +1060,14 @@ boolean KnxCommand()
|
|||
|
||||
i = KNX_GA_Search(index + KNX_SLOT1 -1, i + 1);
|
||||
}
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\"}"),
|
||||
command, index, XdrvMailbox.data );
|
||||
}
|
||||
|
||||
else if ((CMND_KNXTXVAL == command_code) && (index > 0) && (index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0)) {
|
||||
// index <- KNX SLOT to use
|
||||
// XdrvMailbox.payload <- data to send
|
||||
|
||||
if (!(Settings.flag.knx_enabled)) { return false; }
|
||||
// Search all the registered GA that has that output (variable: KNX SLOTx) as parameter
|
||||
byte i = KNX_GA_Search(index + KNX_SLOT1 -1);
|
||||
while ( i != KNX_Empty ) {
|
||||
|
@ -1062,13 +1089,173 @@ boolean KnxCommand()
|
|||
|
||||
i = KNX_GA_Search(index + KNX_SLOT1 -1, i + 1);
|
||||
}
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\"}"),
|
||||
command, index, XdrvMailbox.data );
|
||||
}
|
||||
|
||||
else if (CMND_KNX_ENABLED == command_code) {
|
||||
if (!XdrvMailbox.data_len) {
|
||||
if (Settings.flag.knx_enabled) {
|
||||
snprintf_P(XdrvMailbox.data, sizeof(XdrvMailbox.data), PSTR("1"));
|
||||
} else {
|
||||
snprintf_P(XdrvMailbox.data, sizeof(XdrvMailbox.data), PSTR("0"));
|
||||
}
|
||||
} else {
|
||||
if (XdrvMailbox.payload == 1) {
|
||||
Settings.flag.knx_enabled = 1;
|
||||
} else if (XdrvMailbox.payload == 0) {
|
||||
Settings.flag.knx_enabled = 0;
|
||||
} else { return false; } // Incomplete command
|
||||
}
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"),
|
||||
command, XdrvMailbox.data );
|
||||
}
|
||||
|
||||
else if (CMND_KNX_ENHANCED == command_code) {
|
||||
if (!XdrvMailbox.data_len) {
|
||||
if (Settings.flag.knx_enable_enhancement) {
|
||||
snprintf_P(XdrvMailbox.data, sizeof(XdrvMailbox.data), PSTR("1"));
|
||||
} else {
|
||||
snprintf_P(XdrvMailbox.data, sizeof(XdrvMailbox.data), PSTR("0"));
|
||||
}
|
||||
} else {
|
||||
if (XdrvMailbox.payload == 1) {
|
||||
Settings.flag.knx_enable_enhancement = 1;
|
||||
} else if (XdrvMailbox.payload == 0) {
|
||||
Settings.flag.knx_enable_enhancement = 0;
|
||||
} else { return false; } // Incomplete command
|
||||
}
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"),
|
||||
command, XdrvMailbox.data );
|
||||
}
|
||||
|
||||
else if (CMND_KNX_PA == command_code) {
|
||||
if (XdrvMailbox.data_len) {
|
||||
if (strstr(XdrvMailbox.data, ".")) { // Process parameter entry
|
||||
char sub_string[XdrvMailbox.data_len +1];
|
||||
|
||||
int pa_area = atoi(subStr(sub_string, XdrvMailbox.data, ".", 1));
|
||||
int pa_line = atoi(subStr(sub_string, XdrvMailbox.data, ".", 2));
|
||||
int pa_member = atoi(subStr(sub_string, XdrvMailbox.data, ".", 3));
|
||||
|
||||
if ( ((pa_area == 0) && (pa_line == 0) && (pa_member == 0))
|
||||
|| (pa_area > 15) || (pa_line > 15) || (pa_member > 255) ) {
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_ERROR "\"}"),
|
||||
command );
|
||||
return true;
|
||||
} // Invalid command
|
||||
|
||||
KNX_addr.pa.area = pa_area;
|
||||
KNX_addr.pa.line = pa_line;
|
||||
KNX_addr.pa.member = pa_member;
|
||||
Settings.knx_physsical_addr = KNX_addr.value;
|
||||
}
|
||||
}
|
||||
KNX_addr.value = Settings.knx_physsical_addr;
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%d.%d.%d\"}"),
|
||||
command, KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member );
|
||||
}
|
||||
|
||||
else if ((CMND_KNX_GA == command_code) && (index > 0) && (index <= MAX_KNX_GA)) {
|
||||
if (XdrvMailbox.data_len) {
|
||||
if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry
|
||||
char sub_string[XdrvMailbox.data_len +1];
|
||||
|
||||
int ga_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1));
|
||||
int ga_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2));
|
||||
int ga_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3));
|
||||
int ga_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4));
|
||||
|
||||
if ( ((ga_area == 0) && (ga_line == 0) && (ga_member == 0))
|
||||
|| (ga_area > 31) || (ga_line > 7) || (ga_member > 255)
|
||||
|| (ga_option < 0) || ((ga_option > KNX_MAX_device_param ) && (ga_option != KNX_Empty))
|
||||
|| (!device_param[ga_option-1].show) ) {
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_ERROR "\"}"), command );
|
||||
return true;
|
||||
} // Invalid command
|
||||
|
||||
KNX_addr.ga.area = ga_area;
|
||||
KNX_addr.ga.line = ga_line;
|
||||
KNX_addr.ga.member = ga_member;
|
||||
|
||||
if ( index > Settings.knx_GA_registered ) {
|
||||
Settings.knx_GA_registered ++;
|
||||
index = Settings.knx_GA_registered;
|
||||
}
|
||||
|
||||
Settings.knx_GA_addr[index -1] = KNX_addr.value;
|
||||
Settings.knx_GA_param[index -1] = ga_option;
|
||||
} else {
|
||||
if ( (XdrvMailbox.payload <= Settings.knx_GA_registered) && (XdrvMailbox.payload > 0) ) {
|
||||
index = XdrvMailbox.payload;
|
||||
} else {
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_ERROR "\"}"), command );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ( index <= Settings.knx_GA_registered ) {
|
||||
KNX_addr.value = Settings.knx_GA_addr[index -1];
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"),
|
||||
command, index, device_param_ga[Settings.knx_GA_param[index-1]-1],
|
||||
KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member );
|
||||
}
|
||||
} else {
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%d\"}"),
|
||||
command, Settings.knx_GA_registered );
|
||||
}
|
||||
}
|
||||
|
||||
else if ((CMND_KNX_CB == command_code) && (index > 0) && (index <= MAX_KNX_CB)) {
|
||||
if (XdrvMailbox.data_len) {
|
||||
if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry
|
||||
char sub_string[XdrvMailbox.data_len +1];
|
||||
|
||||
int cb_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1));
|
||||
int cb_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2));
|
||||
int cb_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3));
|
||||
int cb_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4));
|
||||
|
||||
if ( ((cb_area == 0) && (cb_line == 0) && (cb_member == 0))
|
||||
|| (cb_area > 31) || (cb_line > 7) || (cb_member > 255)
|
||||
|| (cb_option < 0) || ((cb_option > KNX_MAX_device_param ) && (cb_option != KNX_Empty))
|
||||
|| (!device_param[cb_option-1].show) ) {
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_ERROR "\"}"), command );
|
||||
return true;
|
||||
} // Invalid command
|
||||
|
||||
KNX_addr.ga.area = cb_area;
|
||||
KNX_addr.ga.line = cb_line;
|
||||
KNX_addr.ga.member = cb_member;
|
||||
|
||||
if ( index > Settings.knx_CB_registered ) {
|
||||
Settings.knx_CB_registered ++;
|
||||
index = Settings.knx_CB_registered;
|
||||
}
|
||||
|
||||
Settings.knx_CB_addr[index -1] = KNX_addr.value;
|
||||
Settings.knx_CB_param[index -1] = cb_option;
|
||||
} else {
|
||||
if ( (XdrvMailbox.payload <= Settings.knx_CB_registered) && (XdrvMailbox.payload > 0) ) {
|
||||
index = XdrvMailbox.payload;
|
||||
} else {
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_ERROR "\"}"), command );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ( index <= Settings.knx_CB_registered ) {
|
||||
KNX_addr.value = Settings.knx_CB_addr[index -1];
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"),
|
||||
command, index, device_param_cb[Settings.knx_CB_param[index-1]-1],
|
||||
KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member );
|
||||
}
|
||||
} else {
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%d\"}"),
|
||||
command, Settings.knx_CB_registered );
|
||||
}
|
||||
}
|
||||
|
||||
else { return false; } // Incomplete command
|
||||
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\"}"),
|
||||
command, index, XdrvMailbox.data );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -459,6 +459,9 @@ void BmpRead()
|
|||
#endif // USE_BME680
|
||||
}
|
||||
if (bmp_temperature != 0.0) { bmp_temperature = ConvertTemp(bmp_temperature); }
|
||||
|
||||
glob_humidity = bmp_humidity;
|
||||
glob_temperature = bmp_temperature;
|
||||
}
|
||||
|
||||
void BmpEverySecond()
|
||||
|
|
|
@ -101,9 +101,16 @@ void Sht3xShow(boolean json)
|
|||
char types[11];
|
||||
for (byte i = 0; i < sht3x_count; i++) {
|
||||
if (Sht3xRead(t, h, sht3x_sensors[i].address)) {
|
||||
|
||||
if (0 == i) {
|
||||
glob_humidity = h;
|
||||
glob_temperature = t;
|
||||
}
|
||||
|
||||
dtostrfd(t, Settings.flag2.temperature_resolution, temperature);
|
||||
dtostrfd(h, Settings.flag2.humidity_resolution, humidity);
|
||||
snprintf_P(types, sizeof(types), PSTR("%s-0x%02X"), sht3x_sensors[i].types, sht3x_sensors[i].address); // "SHT3X-0xXX"
|
||||
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, types, temperature, humidity);
|
||||
#ifdef USE_DOMOTICZ
|
||||
|
@ -159,4 +166,4 @@ boolean Xsns14(byte function)
|
|||
}
|
||||
|
||||
#endif // USE_SHT3X
|
||||
#endif // USE_I2C
|
||||
#endif // USE_I2C
|
||||
|
|
|
@ -108,7 +108,7 @@ boolean Xsns26(byte function)
|
|||
|
||||
if (i2c_flg) {
|
||||
switch (function) {
|
||||
case FUNC_PREP_BEFORE_TELEPERIOD:
|
||||
case FUNC_EVERY_SECOND:
|
||||
LM75ADDetect();
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
|
|
|
@ -0,0 +1,336 @@
|
|||
/*
|
||||
xsns_29_mcp230xx.ino - Support for I2C MCP23008/MCP23017 GPIO Expander (INPUT ONLY!)
|
||||
|
||||
Copyright (C) 2018 Andre Thomas and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_I2C
|
||||
#ifdef USE_MCP230xx
|
||||
|
||||
/*********************************************************************************************\
|
||||
MCP23008/17 - I2C GPIO EXPANDER
|
||||
|
||||
Docs at https://www.microchip.com/wwwproducts/en/MCP23008
|
||||
https://www.microchip.com/wwwproducts/en/MCP23017
|
||||
|
||||
I2C Address: 0x20 - 0x27
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_29 29
|
||||
|
||||
#define MCP230xx_ADDRESS1 0x20
|
||||
#define MCP230xx_ADDRESS2 0x21
|
||||
#define MCP230xx_ADDRESS3 0x22
|
||||
#define MCP230xx_ADDRESS4 0x23
|
||||
#define MCP230xx_ADDRESS5 0x24
|
||||
#define MCP230xx_ADDRESS6 0x25
|
||||
#define MCP230xx_ADDRESS7 0x26
|
||||
#define MCP230xx_ADDRESS8 0x27
|
||||
|
||||
/*
|
||||
Default register locations for MCP23008 - They change for MCP23017 in default bank mode
|
||||
*/
|
||||
|
||||
uint8_t MCP230xx_IODIR = 0x00;
|
||||
uint8_t MCP230xx_GPINTEN = 0x02;
|
||||
uint8_t MCP230xx_IOCON = 0x05;
|
||||
uint8_t MCP230xx_GPPU = 0x06;
|
||||
uint8_t MCP230xx_INTF = 0x07;
|
||||
uint8_t MCP230xx_INTCAP = 0x08;
|
||||
uint8_t MCP230xx_GPIO = 0x09;
|
||||
|
||||
uint8_t mcp230xx_type = 0;
|
||||
uint8_t mcp230xx_address;
|
||||
uint8_t mcp230xx_addresses[] = { MCP230xx_ADDRESS1, MCP230xx_ADDRESS2, MCP230xx_ADDRESS3, MCP230xx_ADDRESS4, MCP230xx_ADDRESS5, MCP230xx_ADDRESS6, MCP230xx_ADDRESS7, MCP230xx_ADDRESS8 };
|
||||
uint8_t mcp230xx_pincount = 0;
|
||||
uint8_t mcp230xx_int_en = 0;
|
||||
|
||||
const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29\":{\"D\":%i,\"MODE\":%i,\"PULL-UP\":%i}}";
|
||||
|
||||
uint8_t MCP230xx_readGPIO(uint8_t port) {
|
||||
return I2cRead8(mcp230xx_address, MCP230xx_GPIO + port);
|
||||
}
|
||||
|
||||
void MCP230xx_ApplySettings(void) {
|
||||
uint8_t reg_gppu = 0;
|
||||
uint8_t reg_gpinten = 0;
|
||||
uint8_t reg_iodir = 0xFF;
|
||||
uint8_t int_en = 0;
|
||||
for (uint8_t idx = 0; idx < 8; idx++) {
|
||||
switch (Settings.mcp230xx_config[idx].pinmode) {
|
||||
case 0 ... 1:
|
||||
reg_iodir |= (1 << idx);
|
||||
break;
|
||||
case 2 ... 4:
|
||||
reg_iodir |= (1 << idx);
|
||||
reg_gpinten |= (1 << idx);
|
||||
int_en=1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (Settings.mcp230xx_config[idx].pullup) {
|
||||
reg_gppu |= (1 << idx);
|
||||
}
|
||||
}
|
||||
I2cWrite8(mcp230xx_address, MCP230xx_GPPU, reg_gppu);
|
||||
I2cWrite8(mcp230xx_address, MCP230xx_GPINTEN, reg_gpinten);
|
||||
I2cWrite8(mcp230xx_address, MCP230xx_IODIR, reg_iodir);
|
||||
if (mcp230xx_type == 2) { // We have a MCP23017
|
||||
reg_gppu = 0;
|
||||
reg_gpinten = 0;
|
||||
reg_iodir = 0xFF;
|
||||
for (uint8_t idx = 8; idx < 16; idx++) {
|
||||
switch (Settings.mcp230xx_config[idx].pinmode) {
|
||||
case 0 ... 1:
|
||||
reg_iodir |= (1 << idx - 8);
|
||||
break;
|
||||
case 2 ... 4:
|
||||
reg_iodir |= (1 << idx - 8);
|
||||
reg_gpinten |= (1 << idx - 8);
|
||||
int_en=1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (Settings.mcp230xx_config[idx].pullup) {
|
||||
reg_gppu |= (1 << idx - 8);
|
||||
}
|
||||
}
|
||||
I2cWrite8(mcp230xx_address, MCP230xx_GPPU + 1, reg_gppu);
|
||||
I2cWrite8(mcp230xx_address, MCP230xx_GPINTEN + 1, reg_gpinten);
|
||||
I2cWrite8(mcp230xx_address, MCP230xx_IODIR + 1, reg_iodir);
|
||||
}
|
||||
mcp230xx_int_en=int_en;
|
||||
}
|
||||
|
||||
void MCP230xx_Detect()
|
||||
{
|
||||
uint8_t buffer;
|
||||
|
||||
if (mcp230xx_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (byte i = 0; i < sizeof(mcp230xx_addresses); i++) {
|
||||
mcp230xx_address = mcp230xx_addresses[i];
|
||||
I2cWrite8(mcp230xx_address, MCP230xx_IOCON, 0x80); // attempt to set bank mode - this will only work on MCP23017, so its the best way to detect the different chips 23008 vs 23017
|
||||
if (I2cValidRead8(&buffer, mcp230xx_address, MCP230xx_IOCON)) {
|
||||
if (buffer == 0x00) {
|
||||
mcp230xx_type = 1; // We have a MCP23008
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "MCP23008", mcp230xx_address);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
mcp230xx_pincount = 8;
|
||||
MCP230xx_ApplySettings();
|
||||
} else {
|
||||
if (buffer == 0x80) {
|
||||
mcp230xx_type = 2; // We have a MCP23017
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "MCP23017", mcp230xx_address);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
mcp230xx_pincount = 16;
|
||||
// Reset bank mode to 0
|
||||
I2cWrite8(mcp230xx_address, MCP230xx_IOCON, 0x00);
|
||||
// Update register locations for MCP23017
|
||||
MCP230xx_GPINTEN = 0x04;
|
||||
MCP230xx_GPPU = 0x0C;
|
||||
MCP230xx_INTF = 0x0E;
|
||||
MCP230xx_INTCAP = 0x10;
|
||||
MCP230xx_GPIO = 0x12;
|
||||
MCP230xx_ApplySettings();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MCP230xx_CheckForInterrupt(void) {
|
||||
uint8_t intf;
|
||||
uint8_t mcp230xx_intcap = 0;
|
||||
uint8_t report_int;
|
||||
|
||||
if (I2cValidRead8(&intf, mcp230xx_address, MCP230xx_INTF)) {
|
||||
if (intf > 0) {
|
||||
if (I2cValidRead8(&mcp230xx_intcap, mcp230xx_address, MCP230xx_INTCAP)) {
|
||||
for (uint8_t intp = 0; intp < 8; intp++) {
|
||||
if ((intf >> intp) & 0x01) { // we know which pin caused interrupt
|
||||
report_int = 0;
|
||||
if (Settings.mcp230xx_config[intp].pinmode > 1) {
|
||||
switch (Settings.mcp230xx_config[intp].pinmode) {
|
||||
case 2:
|
||||
report_int = 1;
|
||||
break;
|
||||
case 3:
|
||||
if (((mcp230xx_intcap >> intp) & 0x01) == 0) report_int = 1; // Int on LOW
|
||||
break;
|
||||
case 4:
|
||||
if (((mcp230xx_intcap >> intp) & 0x01) == 1) report_int = 1; // Int on HIGH
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (report_int) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP230XX_INT\":{\"Pin\":\"D%i\", \"State\":%i}"), mqtt_data, intp, ((mcp230xx_intcap >> intp) & 0x01));
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mcp230xx_type == 2) { // We have a MCP23017 so we need to check the other 8 bits also
|
||||
if (I2cValidRead8(&intf, mcp230xx_address, MCP230xx_INTF+1)) {
|
||||
if (intf > 0) {
|
||||
if (I2cValidRead8(&mcp230xx_intcap, mcp230xx_address, MCP230xx_INTCAP+1)) {
|
||||
for (uint8_t intp = 0; intp < 8; intp++) {
|
||||
if ((intf >> intp) & 0x01) { // we know which pin caused interrupt
|
||||
report_int = 0;
|
||||
if (Settings.mcp230xx_config[intp+8].pinmode > 1) { // change on INT
|
||||
switch (Settings.mcp230xx_config[intp+8].pinmode) {
|
||||
case 2:
|
||||
report_int = 1;
|
||||
break;
|
||||
case 3:
|
||||
if (((mcp230xx_intcap >> intp) & 0x01) == 0) report_int = 1; // Int on LOW
|
||||
break;
|
||||
case 4:
|
||||
if (((mcp230xx_intcap >> intp) & 0x01) == 1) report_int = 1; // Int on HIGH
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (report_int) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP230XX_INT\":{\"Pin\":\"D%i\", \"State\":%i}"), mqtt_data, intp+8, ((mcp230xx_intcap >> intp) & 0x01));
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MCP230xx_Show(boolean json)
|
||||
{
|
||||
if (mcp230xx_type) {
|
||||
if (json) {
|
||||
if (mcp230xx_type == 1) {
|
||||
uint8_t gpio = MCP230xx_readGPIO(0);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP23008\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i}"),
|
||||
mqtt_data,(gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1);
|
||||
}
|
||||
if (mcp230xx_type == 2) {
|
||||
uint8_t gpio1 = MCP230xx_readGPIO(0);
|
||||
uint8_t gpio2 = MCP230xx_readGPIO(1);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP23017\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i,\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i}"),
|
||||
mqtt_data, (gpio1>>0)&1,(gpio1>>1)&1,(gpio1>>2)&1,(gpio1>>3)&1,(gpio1>>4)&1,(gpio1>>5)&1,(gpio1>>6)&1,(gpio1>>7)&1,(gpio2>>0)&1,(gpio2>>1)&1,(gpio2>>2)&1,(gpio2>>3)&1,(gpio2>>4)&1,(gpio2>>5)&1,(gpio2>>6)&1,(gpio2>>7)&1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MCP230xx_Command(void) {
|
||||
boolean serviced = true;
|
||||
uint8_t _a, _b = 0;
|
||||
uint8_t pin, pinmode, pullup = 0;
|
||||
String data = XdrvMailbox.data;
|
||||
data.toUpperCase();
|
||||
if (data == "RESET") { // we need to reset all pins to input
|
||||
for (uint8_t pinx=0;pinx<16;pinx++) {
|
||||
Settings.mcp230xx_config[pinx].pinmode=1;
|
||||
Settings.mcp230xx_config[pinx].pullup=0;
|
||||
Settings.mcp230xx_config[pinx].b4=0;
|
||||
Settings.mcp230xx_config[pinx].b5=0;
|
||||
Settings.mcp230xx_config[pinx].b6=0;
|
||||
Settings.mcp230xx_config[pinx].b7=0;
|
||||
}
|
||||
MCP230xx_ApplySettings();
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,99,99,99);
|
||||
return serviced;
|
||||
}
|
||||
_a = data.indexOf(",");
|
||||
pin = data.substring(0, _a).toInt();
|
||||
if (pin < mcp230xx_pincount) {
|
||||
String cmnd = data.substring(_a+1);
|
||||
if (cmnd == "?") {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,Settings.mcp230xx_config[pin].pullup);
|
||||
return serviced;
|
||||
}
|
||||
}
|
||||
_b = data.indexOf(",", _a + 1);
|
||||
if (_a < XdrvMailbox.data_len) {
|
||||
if (_b < XdrvMailbox.data_len) {
|
||||
pinmode = data.substring(_a+1, _b).toInt();
|
||||
pullup = data.substring(_b+1, XdrvMailbox.data_len).toInt();
|
||||
if ((pin < mcp230xx_pincount) && (pinmode < 5) && (pullup < 2)) {
|
||||
Settings.mcp230xx_config[pin].pinmode=pinmode;
|
||||
Settings.mcp230xx_config[pin].pullup=pullup;
|
||||
MCP230xx_ApplySettings();
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmode,pullup);
|
||||
} else {
|
||||
serviced = false;
|
||||
}
|
||||
} else {
|
||||
serviced = false;
|
||||
}
|
||||
} else {
|
||||
serviced = false;
|
||||
}
|
||||
return serviced;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
boolean Xsns29(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (i2c_flg) {
|
||||
switch (function) {
|
||||
case FUNC_EVERY_SECOND:
|
||||
MCP230xx_Detect();
|
||||
break;
|
||||
case FUNC_EVERY_50_MSECOND:
|
||||
if (mcp230xx_int_en) { // Only check for interrupts if its enabled on one of the pins
|
||||
MCP230xx_CheckForInterrupt();
|
||||
}
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
MCP230xx_Show(1);
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
if (XSNS_29 == XdrvMailbox.index) {
|
||||
result = MCP230xx_Command();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_MCP230xx
|
||||
#endif // USE_I2C
|
|
@ -0,0 +1,448 @@
|
|||
/**
|
||||
*
|
||||
* @file xsns_30_mpr121.ino
|
||||
*
|
||||
* @package Sonoff-Tasmota
|
||||
* @subpackage Sensors
|
||||
* @name MPR121
|
||||
*
|
||||
* @description Driver for up to 4x Freescale MPR121 Proximity Capacitive Touch Sensor Controllers (Only touch buttons).
|
||||
*
|
||||
* @author Rene 'Renne' Bartsch, B.Sc. Informatics, <rene@bartschnet.de>
|
||||
* @copyright Rene 'Renne' Bartsch 2018
|
||||
* @date $Date$
|
||||
* @version $Id$
|
||||
*
|
||||
* @link https://github.com/arendst/Sonoff-Tasmota/wiki/MPR121 \endlink
|
||||
* @link https://www.sparkfun.com/datasheets/Components/MPR121.pdf \endlink
|
||||
* @link http://cache.freescale.com/files/sensors/doc/app_note/AN3891.pdf \endlink
|
||||
* @link http://cache.freescale.com/files/sensors/doc/app_note/AN3892.pdf \endlink
|
||||
* @link http://cache.freescale.com/files/sensors/doc/app_note/AN3893.pdf \endlink
|
||||
* @link http://cache.freescale.com/files/sensors/doc/app_note/AN3894.pdf \endlink
|
||||
* @link http://cache.freescale.com/files/sensors/doc/app_note/AN3895.pdf \endlink
|
||||
*
|
||||
* @license GNU GPL v.3
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef USE_I2C
|
||||
#ifdef USE_MPR121
|
||||
|
||||
/** @defgroup group1 MPR121
|
||||
* MPR121 preprocessor directives
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Electrodes Status Register. */
|
||||
#define MPR121_ELEX_REG 0x00
|
||||
|
||||
/** ELEC0-11 Maximum Half Delta Rising Register. */
|
||||
#define MPR121_MHDR_REG 0x2B
|
||||
|
||||
/** ELEC0-11 Maximum Half Delta Rising Value. */
|
||||
#define MPR121_MHDR_VAL 0x01
|
||||
|
||||
/** ELEC0-11 Noise Half Delta Falling Register. */
|
||||
#define MPR121_NHDR_REG 0x2C
|
||||
|
||||
/** ELEC0-11 Noise Half Delta Falling Value. */
|
||||
#define MPR121_NHDR_VAL 0x01
|
||||
|
||||
/** ELEC0-11 Noise Count Limit Rising Register. */
|
||||
#define MPR121_NCLR_REG 0x2D
|
||||
|
||||
/** ELEC0-11 Noise Count Limit Rising Value. */
|
||||
#define MPR121_NCLR_VAL 0x0E
|
||||
|
||||
/** ELEC0-11 Maximum Half Delta Falling Register. */
|
||||
#define MPR121_MHDF_REG 0x2F
|
||||
|
||||
/** ELEC0-11 Maximum Half Delta Falling Value. */
|
||||
#define MPR121_MHDF_VAL 0x01
|
||||
|
||||
/** ELEC0-11 Noise Half Delta Falling Register. */
|
||||
#define MPR121_NHDF_REG 0x30
|
||||
|
||||
/** ELEC0-11 Noise Half Delta Falling Value. */
|
||||
#define MPR121_NHDF_VAL 0x05
|
||||
|
||||
/** ELEC0-11 Noise Count Limit Falling Register. */
|
||||
#define MPR121_NCLF_REG 0x31
|
||||
|
||||
/** ELEC0-11 Noise Count Limit Falling Value. */
|
||||
#define MPR121_NCLF_VAL 0x01
|
||||
|
||||
/** Proximity Maximum Half Delta Rising Register. */
|
||||
#define MPR121_MHDPROXR_REG 0x36
|
||||
|
||||
/** Proximity Maximum Half Delta Rising Value. */
|
||||
#define MPR121_MHDPROXR_VAL 0x3F
|
||||
|
||||
/** Proximity Noise Half Delta Rising Register. */
|
||||
#define MPR121_NHDPROXR_REG 0x37
|
||||
|
||||
/** Proximity Noise Half Delta Rising Value. */
|
||||
#define MPR121_NHDPROXR_VAL 0x5F
|
||||
|
||||
/** Proximity Noise Count Limit Rising Register. */
|
||||
#define MPR121_NCLPROXR_REG 0x38
|
||||
|
||||
/** Proximity Noise Count Limit Rising Value. */
|
||||
#define MPR121_NCLPROXR_VAL 0x04
|
||||
|
||||
/** Proximity Filter Delay Count Limit Rising Register. */
|
||||
#define MPR121_FDLPROXR_REG 0x39
|
||||
|
||||
/** Proximity Filter Delay Count Limit Rising Value. */
|
||||
#define MPR121_FDLPROXR_VAL 0x00
|
||||
|
||||
/** Proximity Maximum Half Delta Falling Register. */
|
||||
#define MPR121_MHDPROXF_REG 0x3A
|
||||
|
||||
/** Proximity Maximum Half Delta Falling Value. */
|
||||
#define MPR121_MHDPROXF_VAL 0x01
|
||||
|
||||
/** Proximity Noise Half Delta Falling Register. */
|
||||
#define MPR121_NHDPROXF_REG 0x3B
|
||||
|
||||
/** Proximity Noise Half Delta Falling Value. */
|
||||
#define MPR121_NHDPROXF_VAL 0x01
|
||||
|
||||
/** Proximity Noise Count Limit Falling Register. */
|
||||
#define MPR121_NCLPROXF_REG 0x3C
|
||||
|
||||
/** Proximity Noise Count Limit Falling Value. */
|
||||
#define MPR121_NCLPROXF_VAL 0x1F
|
||||
|
||||
/** Proximity Filter Delay Count Limit Falling Register. */
|
||||
#define MPR121_FDLPROXF_REG 0x3D
|
||||
|
||||
/** Proximity Filter Delay Count Limit Falling Value. */
|
||||
#define MPR121_FDLPROXF_VAL 0x04
|
||||
|
||||
/** First Electrode Touch Threshold Register. */
|
||||
#define MPR121_E0TTH_REG 0x41
|
||||
|
||||
/** First Electrode Touch Threshold Value. */
|
||||
#define MPR121_E0TTH_VAL 12
|
||||
|
||||
/** First Electrode Release Threshold Register. */
|
||||
#define MPR121_E0RTH_REG 0x42
|
||||
|
||||
/** First Electrode Release Threshold Value. */
|
||||
#define MPR121_E0RTH_VAL 6
|
||||
|
||||
/** Global CDC/CDT Configuration Register. */
|
||||
#define MPR121_CDT_REG 0x5D
|
||||
|
||||
/** Global CDC/CDT Configuration Value. */
|
||||
#define MPR121_CDT_VAL 0x20
|
||||
|
||||
/** Enable electrodes Register. */
|
||||
#define MPR121_ECR_REG 0x5E
|
||||
|
||||
/** Enable electrodes Value. */
|
||||
#define MPR121_ECR_VAL 0x8F // Start ELE0-11 with first 5 bits of baseline tracking
|
||||
//#define MPR121_ECR_VAL 0xBF // Start ELE0-11 + proximity with first 5 bits of baseline tracking
|
||||
|
||||
/** Soft-reset Register. */
|
||||
#define MPR121_SRST_REG 0x80
|
||||
|
||||
/** Soft-reset Value. */
|
||||
#define MPR121_SRST_VAL 0x63
|
||||
|
||||
/** Get bit of variable 'current' of sensor at position. */
|
||||
#define BITC(sensor, position) ((pS->current[sensor] >> position) & 1)
|
||||
|
||||
/** Get bit of variable 'previous' of sensor at position. */
|
||||
#define BITP(sensor, position) ((pS->previous[sensor] >> position) & 1)
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
||||
/**
|
||||
* MPR121 sensors status and data struct.
|
||||
*
|
||||
* The struct mpr121 uses the indices of i2c_addr and id to link the specific sensors to an I2C address and a human-readable ID
|
||||
* and the indices of the arrays connected, running, current and previous to store sensor status and data of a specific sensor.
|
||||
*
|
||||
*/
|
||||
typedef struct mpr121 mpr121;
|
||||
struct mpr121 {
|
||||
const uint8_t i2c_addr[4] = { 0x5A, 0x5B, 0x5C, 0x5D }; /** I2C addresses of MPR121 controller */
|
||||
const char id[4] = { 'A', 'B', 'C', 'D' }; /** Human-readable sensor IDs*/
|
||||
bool connected[4] = { false, false, false, false }; /** Status if sensor is connected at I2C address */
|
||||
bool running[4] = { false, false, false, false }; /** Running state of sensor */
|
||||
uint16_t current[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; /** Current values in electrode register of sensor */
|
||||
uint16_t previous[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; /** Current values in electrode register of sensor */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The function Mpr121Init() soft-resets, detects and configures up to 4x MPR121 sensors.
|
||||
*
|
||||
* @param struct *pS Struct with MPR121 status and data.
|
||||
* @return void
|
||||
* @pre None.
|
||||
* @post None.
|
||||
*
|
||||
*/
|
||||
void Mpr121Init(struct mpr121 *pS)
|
||||
{
|
||||
|
||||
// Loop through I2C addresses
|
||||
for (uint8_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) {
|
||||
|
||||
// Soft reset sensor and check if connected at I2C address
|
||||
pS->connected[i] = (I2cWrite8(pS->i2c_addr[i], MPR121_SRST_REG, MPR121_SRST_VAL)
|
||||
&& (0x24 == I2cRead8(pS->i2c_addr[i], 0x5D)));
|
||||
if (pS->connected[i]) {
|
||||
|
||||
// Log sensor found
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "MPR121(%c) " D_FOUND_AT " 0x%X"), pS->id[i], pS->i2c_addr[i]);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
|
||||
// Set thresholds for registers 0x41 - 0x5A (ExTTH and ExRTH)
|
||||
for (uint8_t j = 0; j < 13; j++) {
|
||||
|
||||
// Touch
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_E0TTH_REG + 2 * j, MPR121_E0TTH_VAL);
|
||||
|
||||
// Release
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_E0RTH_REG + 2 * j, MPR121_E0RTH_VAL);
|
||||
}
|
||||
|
||||
// ELEC0-11 Maximum Half Delta Rising
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_MHDR_REG, MPR121_MHDR_VAL);
|
||||
|
||||
// ELEC0-11 Noise Half Delta Rising
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_NHDR_REG, MPR121_NHDR_VAL);
|
||||
|
||||
// ELEC0-11 Noise Count Limit Rising
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_NCLR_REG, MPR121_NCLR_VAL);
|
||||
|
||||
// ELEC0-11 Maximum Half Delta Falling
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_MHDF_REG, MPR121_MHDF_VAL);
|
||||
|
||||
// ELEC0-11 Noise Half Delta Falling
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_NHDF_REG, MPR121_NHDF_VAL);
|
||||
|
||||
// ELEC0-11 Noise Count Limit Falling
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_NCLF_REG, MPR121_NCLF_VAL);
|
||||
|
||||
// Proximity Maximum Half Delta Rising
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_MHDPROXR_REG, MPR121_MHDPROXR_VAL);
|
||||
|
||||
// Proximity Noise Half Delta Rising
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_NHDPROXR_REG, MPR121_NHDPROXR_VAL);
|
||||
|
||||
// Proximity Noise Count Limit Rising
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_NCLPROXR_REG, MPR121_NCLPROXR_VAL);
|
||||
|
||||
// Proximity Filter Delay Count Limit Rising
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_FDLPROXR_REG, MPR121_FDLPROXR_VAL);
|
||||
|
||||
// Proximity Maximum Half Delta Falling
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_MHDPROXF_REG, MPR121_MHDPROXF_VAL);
|
||||
|
||||
// Proximity Noise Half Delta Falling
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_NHDPROXF_REG, MPR121_NHDPROXF_VAL);
|
||||
|
||||
// Proximity Noise Count Limit Falling
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_NCLPROXF_REG, MPR121_NCLPROXF_VAL);
|
||||
|
||||
// Proximity Filter Delay Count Limit Falling
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_FDLPROXF_REG, MPR121_FDLPROXF_VAL);
|
||||
|
||||
// Global CDC/CDT Configuration
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_CDT_REG, MPR121_CDT_VAL);
|
||||
|
||||
// Enable sensor
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_ECR_REG, MPR121_ECR_VAL);
|
||||
|
||||
// Check if sensor is running
|
||||
pS->running[i] = (0x00 != I2cRead8(pS->i2c_addr[i], MPR121_ECR_REG));
|
||||
if (pS->running[i]) {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "MPR121%c: Running"), pS->id[i]);
|
||||
} else {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "MPR121%c: NOT Running"), pS->id[i]);
|
||||
}
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
} else {
|
||||
|
||||
// Make sure running is false
|
||||
pS->running[i] = false;
|
||||
}
|
||||
} // for-loop
|
||||
|
||||
// Display no sensor found message
|
||||
if (!(pS->connected[0] || pS->connected[1] || pS->connected[2]
|
||||
|| pS->connected[3])) {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "MPR121: No sensors found"));
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
}
|
||||
} // void Mpr121Init(struct mpr121 *s)
|
||||
|
||||
|
||||
/**
|
||||
* Publishes the sensor information.
|
||||
*
|
||||
* The function Mpr121Show() reads sensor data, checks for over-current exceptions and
|
||||
* creates strings with button states for the web-interface and near real-time/ telemetriy MQTT.
|
||||
*
|
||||
* @param struct *pS Struct with MPR121 status and data.
|
||||
* @param byte function Tasmota function ID.
|
||||
* @return void
|
||||
* @pre Call Mpr121Init() once.
|
||||
* @post None.
|
||||
*
|
||||
*/
|
||||
void Mpr121Show(struct mpr121 *pS, byte function)
|
||||
{
|
||||
|
||||
// Loop through sensors
|
||||
for (uint8_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) {
|
||||
|
||||
// Check if sensor is connected
|
||||
if (pS->connected[i]) {
|
||||
|
||||
// Read data
|
||||
if (!I2cValidRead16LE(&pS->current[i], pS->i2c_addr[i], MPR121_ELEX_REG)) {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "MPR121%c: ERROR: Cannot read data!"), pS->id[i]);
|
||||
AddLog(LOG_LEVEL_ERROR);
|
||||
Mpr121Init(pS);
|
||||
return;
|
||||
}
|
||||
// Check if OVCF bit is set
|
||||
if (BITC(i, 15)) {
|
||||
|
||||
// Clear OVCF bit
|
||||
I2cWrite8(pS->i2c_addr[i], MPR121_ELEX_REG, 0x00);
|
||||
snprintf_P(log_data, sizeof(log_data),
|
||||
PSTR(D_LOG_I2C "MPR121%c: ERROR: Excess current detected! Fix circuits if it happens repeatedly! Soft-resetting MPR121 ..."), pS->id[i]);
|
||||
AddLog(LOG_LEVEL_ERROR);
|
||||
Mpr121Init(pS);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Check if sensor is running
|
||||
if (pS->running[i]) {
|
||||
|
||||
// Append sensor to JSON message string
|
||||
if (FUNC_JSON_APPEND == function) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MPR121%c\":{"), mqtt_data, pS->id[i]);
|
||||
}
|
||||
// Loop through buttons
|
||||
for (uint8_t j = 0; j < 13; j++) {
|
||||
|
||||
// Add sensor, button and state to MQTT JSON message string
|
||||
if ((FUNC_EVERY_50_MSECOND == function)
|
||||
&& (BITC(i, j) != BITP(i, j))) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"MPR121%c\":{\"Button%i\":%i}}"), pS->id[i], j, BITC(i, j));
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data);
|
||||
}
|
||||
// Add buttons to web string
|
||||
#ifdef USE_WEBSERVER
|
||||
if (FUNC_WEB_APPEND == function) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{s}MPR121%c Button%d{m}%d{e}"), mqtt_data, pS->id[i], j, BITC(i, j));
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
// Append JSON message string
|
||||
if (FUNC_JSON_APPEND == function) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"Button%i\":%i,"), mqtt_data, j, BITC(i, j));
|
||||
}
|
||||
} // for-loop j
|
||||
|
||||
// Save sensor data
|
||||
pS->previous[i] = pS->current[i];
|
||||
|
||||
// Append JSON message string
|
||||
if (FUNC_JSON_APPEND == function) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), "%s}", mqtt_data);
|
||||
}
|
||||
} // if->running
|
||||
} // for-loop i
|
||||
} // void Mpr121Show(byte function)
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
/**
|
||||
* @ingroup group1
|
||||
* Assign Tasmota sensor model ID
|
||||
*/
|
||||
#define XSNS_30
|
||||
|
||||
/**
|
||||
* The function Xsns30() interfaces Tasmota with the driver.
|
||||
*
|
||||
* It provides the function IDs
|
||||
* FUNC_INIT to initialize a driver,
|
||||
* FUNC_EVERY_50_MSECOND for near real-time operation,
|
||||
* FUNC_JSON_APPEND for telemetry data and
|
||||
* FUNC_WEB_APPEND for displaying data in the Tasmota web-interface
|
||||
*
|
||||
* @param byte function Tasmota function ID.
|
||||
* @return boolean ???
|
||||
* @pre None.
|
||||
* @post None.
|
||||
*
|
||||
*/
|
||||
boolean Xsns30(byte function)
|
||||
{
|
||||
// ???
|
||||
boolean result = false;
|
||||
|
||||
// Sensor state/data struct
|
||||
static struct mpr121 mpr121;
|
||||
|
||||
// Check if I2C is enabled
|
||||
if (i2c_flg) {
|
||||
switch (function) {
|
||||
|
||||
// Initialize Sensors
|
||||
case FUNC_INIT:
|
||||
Mpr121Init(&mpr121);
|
||||
break;
|
||||
|
||||
// Run ever 50 milliseconds (near real-time functions)
|
||||
case FUNC_EVERY_50_MSECOND:
|
||||
Mpr121Show(&mpr121, FUNC_EVERY_50_MSECOND);
|
||||
break;
|
||||
|
||||
// Generate JSON telemetry string
|
||||
case FUNC_JSON_APPEND:
|
||||
Mpr121Show(&mpr121, FUNC_JSON_APPEND);
|
||||
break;
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
// Show sensor data on main web page
|
||||
case FUNC_WEB_APPEND:
|
||||
Mpr121Show(&mpr121, FUNC_WEB_APPEND);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
// Return boolean result
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_MPR121
|
||||
#endif // USE_I2C
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
xsns_31_ccs811.ino - CCS811 gas and air quality sensor support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2018 Gerhard Mutz and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_I2C
|
||||
#ifdef USE_CCS811
|
||||
/*********************************************************************************************\
|
||||
* SGP30 - Gas (TVOC - Total Volatile Organic Compounds) and Air Quality (CO2)
|
||||
*
|
||||
* Source: Adafruit
|
||||
*
|
||||
* I2C Address: 0x5A assumes ADDR connected to Gnd, Wake also must be grounded
|
||||
\*********************************************************************************************/
|
||||
|
||||
#include "Adafruit_CCS811.h"
|
||||
|
||||
Adafruit_CCS811 ccs;
|
||||
uint8_t CCS811_ready;
|
||||
uint8_t CCS811_type;
|
||||
uint16_t eCO2;
|
||||
uint16_t TVOC;
|
||||
uint8_t tcnt = 0;
|
||||
uint8_t ecnt = 0;
|
||||
|
||||
/********************************************************************************************/
|
||||
#define EVERYNSECONDS 5
|
||||
|
||||
void CCS811Update() // Perform every n second
|
||||
{
|
||||
tcnt++;
|
||||
if (tcnt >= EVERYNSECONDS) {
|
||||
tcnt = 0;
|
||||
CCS811_ready = 0;
|
||||
if (!CCS811_type) {
|
||||
sint8_t res = ccs.begin(CCS811_ADDRESS);
|
||||
if (!res) {
|
||||
CCS811_type = 1;
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "CCS811", 0x5A);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
} else {
|
||||
//snprintf_P(log_data, sizeof(log_data), "CCS811 init failed: %d",res);
|
||||
//AddLog(LOG_LEVEL_DEBUG);
|
||||
}
|
||||
} else {
|
||||
if (ccs.available()) {
|
||||
if (!ccs.readData()){
|
||||
TVOC = ccs.getTVOC();
|
||||
eCO2 = ccs.geteCO2();
|
||||
CCS811_ready = 1;
|
||||
if ((glob_humidity != 0) && (glob_temperature != -9999)) {
|
||||
double gtmp = glob_temperature * 4;
|
||||
ccs.setEnvironmentalData(glob_humidity, gtmp / 4);
|
||||
}
|
||||
ecnt = 0;
|
||||
}
|
||||
} else {
|
||||
// failed, count up
|
||||
ecnt++;
|
||||
if (ecnt > 6) {
|
||||
// after 30 seconds, restart
|
||||
ccs.begin(CCS811_ADDRESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char HTTP_SNS_CCS811[] PROGMEM = "%s"
|
||||
"{s}CCS811 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
"{s}CCS811 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}";
|
||||
|
||||
void CCS811Show(boolean json)
|
||||
{
|
||||
if (CCS811_ready) {
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"CCS811\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), mqtt_data,eCO2,TVOC);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, eCO2);
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_CCS811, mqtt_data, eCO2, TVOC);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_31
|
||||
|
||||
boolean Xsns31(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (i2c_flg) {
|
||||
switch (function) {
|
||||
case FUNC_EVERY_SECOND:
|
||||
CCS811Update();
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
CCS811Show(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_WEB_APPEND:
|
||||
CCS811Show(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_CCS811
|
||||
#endif // USE_I2C
|
|
@ -146,41 +146,45 @@ else:
|
|||
def StartDecode():
|
||||
# print("Decoding\n{}".format(obj))
|
||||
|
||||
if ("Time" in obj["StatusSNS"]):
|
||||
time = str(" from status report taken at {}".format(obj["StatusSNS"]["Time"]))
|
||||
if ("FriendlyName" in obj["Status"]):
|
||||
print("\nDecoding information for device {}{}".format(obj["Status"]["FriendlyName"][0], time))
|
||||
if ("StatusSNS" in obj):
|
||||
if ("Time" in obj["StatusSNS"]):
|
||||
time = str(" from status report taken at {}".format(obj["StatusSNS"]["Time"]))
|
||||
|
||||
if ("SetOption" in obj["StatusLOG"]):
|
||||
options = []
|
||||
option = obj["StatusLOG"]["SetOption"][0]
|
||||
i_option = int(option,16)
|
||||
for i in range(len(a_setoption)):
|
||||
if (a_setoption[i]):
|
||||
state = (i_option >> i) & 1
|
||||
options.append(str("{0:2d} ({1}) {2}".format(i, a_on_off[state], a_setoption[i])))
|
||||
if ("Status" in obj):
|
||||
if ("FriendlyName" in obj["Status"]):
|
||||
print("\nDecoding information for device {}{}".format(obj["Status"]["FriendlyName"][0], time))
|
||||
|
||||
print("\nOptions")
|
||||
for i in range(len(options)):
|
||||
print(" {}".format(options[i]))
|
||||
if ("StatusLOG" in obj):
|
||||
if ("SetOption" in obj["StatusLOG"]):
|
||||
options = []
|
||||
option = obj["StatusLOG"]["SetOption"][0]
|
||||
i_option = int(option,16)
|
||||
for i in range(len(a_setoption)):
|
||||
if (a_setoption[i]):
|
||||
state = (i_option >> i) & 1
|
||||
options.append(str("{0:2d} ({1}) {2}".format(i, a_on_off[state], a_setoption[i])))
|
||||
|
||||
print("\nOptions")
|
||||
for i in range(len(options)):
|
||||
print(" {}".format(options[i]))
|
||||
|
||||
if ("Features" in obj["StatusMEM"]):
|
||||
features = []
|
||||
for f in range(5):
|
||||
feature = obj["StatusMEM"]["Features"][f]
|
||||
i_feature = int(feature,16)
|
||||
if (f == 0):
|
||||
features.append(str("Language LCID = {}".format(i_feature & 0xFFFF)))
|
||||
else:
|
||||
for i in range(len(a_features[f -1])):
|
||||
if ((i_feature >> i) & 1):
|
||||
features.append(a_features[f -1][i])
|
||||
if ("StatusMEM" in obj):
|
||||
if ("Features" in obj["StatusMEM"]):
|
||||
features = []
|
||||
for f in range(5):
|
||||
feature = obj["StatusMEM"]["Features"][f]
|
||||
i_feature = int(feature,16)
|
||||
if (f == 0):
|
||||
features.append(str("Language LCID = {}".format(i_feature & 0xFFFF)))
|
||||
else:
|
||||
for i in range(len(a_features[f -1])):
|
||||
if ((i_feature >> i) & 1):
|
||||
features.append(a_features[f -1][i])
|
||||
|
||||
features.sort()
|
||||
print("\nFeatures")
|
||||
for i in range(len(features)):
|
||||
print(" {}".format(features[i]))
|
||||
features.sort()
|
||||
print("\nFeatures")
|
||||
for i in range(len(features)):
|
||||
print(" {}".format(features[i]))
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
|
|
Loading…
Reference in New Issue