Merge pull request #2 from arendst/development

Pull request to catch up to arendst/Tasmota development branch.
This commit is contained in:
Khoa Ton 2020-07-14 01:40:53 -07:00 committed by GitHub
commit 676c3dd1f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 714 additions and 537 deletions

View File

@ -21,7 +21,7 @@ While fallback or downgrading is common practice it was never supported due to S
## Supported Core versions
This release will be supported from ESP8266/Arduino library Core version **2.7.1** due to reported security and stability issues on previous Core version. This will also support gzipped binaries.
This release will be supported from ESP8266/Arduino library Core version **2.7.2** due to reported security and stability issues on previous Core version. This will also support gzipped binaries.
Although it might still compile on previous Core versions all support will be removed in the near future.
@ -35,7 +35,7 @@ For initial configuration this release supports Webserver based **WifiManager**
## Provided Binary Downloads
The following binary downloads have been compiled with ESP8266/Arduino library core version **2.7.1**.
The following binary downloads have been compiled with ESP8266/Arduino library core version **2.7.2**.
- **tasmota.bin** = The Tasmota version with most drivers. **RECOMMENDED RELEASE BINARY**
- **tasmota-BG.bin** to **tasmota-TW.bin** = The Tasmota version in different languages.
@ -52,7 +52,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
## Changelog
### Version 8.4.0 George
### Version 8.3.1.6
- Change IRremoteESP8266 library updated to v2.7.7
- Change Adafruit_SGP30 library from v1.0.3 to v1.2.0 (#8519)
@ -94,4 +94,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
- Add compile time interlock parameters (#8759)
- Add compile time user template (#8766)
- Add rotary encoder support for light dimmer and optional color temperature if button1 still pressed (#8670)
- Add support for switches/relays using an AC detection circuitry e.g. MOES MS-104B / BlitzWolf SS5 / etc. (#8606)
- Add support for switches/relays using an AC detection circuitry e.g. MOES MS-104B or BlitzWolf SS5 (#8606)

View File

@ -1,9 +1,3 @@
## Released
### 8.4.0 20200716
- Release George
## Unreleased (development)
### 8.3.1.6 20200617
@ -17,6 +11,7 @@
- Add compile time interlock parameters (#8759)
- Add compile time user template (#8766)
- Add rotary encoder support for light dimmer and optional color temperature if button1 still pressed (#8670)
- Add support for switches/relays using an AC detection circuitry e.g. MOES MS-104B or BlitzWolf SS5 (#8606)
- Fix exception or watchdog on rule re-entry (#8757)
- Change ESP32 USER GPIO template representation decreasing template message size
- Change define USE_TASMOTA_SLAVE into USE_TASMOTA_CLIENT
@ -67,6 +62,8 @@
- Add support for VEML6075 UVA/UVB/UVINDEX Sensor by device111 (#8432)
- Add support for VEML7700 Ambient light intensity Sensor by device111 (#8432)
## Released
### 8.3.1 20200518
- Release Fred
@ -83,6 +80,8 @@
- Change Quick Power Cycle detection from 4 to 7 power interrupts (#4066)
- Fix default state of ``SetOption73 0`` for button decoupling and send multi-press and hold MQTT messages
## Released
### 8.3.0 20200514
- Release Fred
@ -167,6 +166,8 @@
- Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa
- Add support for 64x48 SSD1306 OLED (#6740)
## Released
### 8.2.0 20200321
- Release Elliot

View File

@ -303,7 +303,7 @@ void ButtonHandler(void)
}
}
#ifdef ROTARY_V1
if (!((0 == button_index) && RotaryButtonPressed())) {
if (!RotaryButtonPressed(button_index)) {
#endif
if (!Settings.flag3.mqtt_buttons && single_press && SendKey(KEY_BUTTON, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
// Success

View File

@ -34,212 +34,98 @@
\*********************************************************************************************/
#ifndef ROTARY_MAX_STEPS
#define ROTARY_MAX_STEPS 10 // Rotary step boundary
#define ROTARY_MAX_STEPS 10 // Rotary step boundary
#endif
//#define ROTARY_OPTION1 // Up to 4 interrupts and pulses per step
//#define ROTARY_OPTION2 // Up to 4 interrupts but 1 pulse per step
#define ROTARY_OPTION3 // 1 interrupt and pulse per step
#ifdef ROTARY_OPTION1
// up to 4 pulses per step
const uint8_t rotary_dimmer_increment = 100 / (ROTARY_MAX_STEPS * 3); // Dimmer 1..100 = 100
const uint8_t rotary_ct_increment = 350 / (ROTARY_MAX_STEPS * 3); // Ct 153..500 = 347
const uint8_t rotary_color_increment = 360 / (ROTARY_MAX_STEPS * 3); // Hue 0..359 = 360
#endif // ROTARY_OPTION1
#ifdef ROTARY_OPTION2
// 1 pulse per step
const uint8_t rotary_dimmer_increment = 100 / ROTARY_MAX_STEPS; // Dimmer 1..100 = 100
const uint8_t rotary_ct_increment = 350 / ROTARY_MAX_STEPS; // Ct 153..500 = 347
const uint8_t rotary_color_increment = 360 / ROTARY_MAX_STEPS; // Hue 0..359 = 360
#endif // ROTARY_OPTION2
const uint8_t rotary_dimmer_increment = 100 / ROTARY_MAX_STEPS; // Dimmer 1..100 = 100
const uint8_t rotary_ct_increment = 350 / ROTARY_MAX_STEPS; // Ct 153..500 = 347
const uint8_t rotary_color_increment = 360 / ROTARY_MAX_STEPS; // Hue 0..359 = 360
#ifdef ROTARY_OPTION3
// 1 pulse per step
const uint8_t rotary_dimmer_increment = 100 / ROTARY_MAX_STEPS; // Dimmer 1..100 = 100
const uint8_t rotary_ct_increment = 350 / ROTARY_MAX_STEPS; // Ct 153..500 = 347
const uint8_t rotary_color_increment = 360 / ROTARY_MAX_STEPS; // Hue 0..359 = 360
#endif // ROTARY_OPTION3
const uint8_t ROTARY_TIMEOUT = 10; // 10 * RotaryHandler() call which is usually 10 * 0.05 seconds
const uint8_t ROTARY_TIMEOUT = 10; // 10 * RotaryHandler() call which is usually 10 * 0.05 seconds
struct ROTARY {
#ifdef ROTARY_OPTION1
uint8_t state = 0;
#endif // ROTARY_OPTION1
#ifdef ROTARY_OPTION2
uint16_t store;
uint8_t prev_next_code;
#endif // ROTARY_OPTION2
#ifdef ROTARY_OPTION3
bool present = false;
} Rotary;
struct ENCODER {
uint32_t debounce = 0;
#endif // ROTARY_OPTION3
int8_t abs_position1 = 0;
int8_t abs_position2 = 0;
int8_t direction = 0; // Control consistent direction
uint8_t present = 0;
int8_t direction = 0; // Control consistent direction
int8_t pin = -1;
uint8_t position = 128;
uint8_t last_position = 128;
uint8_t timeout = 0; // Disallow direction change within 0.5 second
uint8_t timeout = 0; // Disallow direction change within 0.5 second
bool changed = false;
bool busy = false;
} Rotary;
} Encoder[MAX_ROTARIES];
/********************************************************************************************/
void update_rotary(void) ICACHE_RAM_ATTR;
void update_rotary(void) {
if (Rotary.busy) { return; }
bool powered_on = (power);
#ifdef USE_LIGHT
if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control
powered_on = (LightPowerIRAM());
}
#endif // USE_LIGHT
if (!powered_on) { return; }
void ICACHE_RAM_ATTR RotaryIsr(uint32_t index) {
if (Encoder[index].busy) { return; }
#ifdef ROTARY_OPTION1
// https://github.com/PaulStoffregen/Encoder/blob/master/Encoder.h
/*
uint8_t p1val = digitalRead(Pin(GPIO_ROT1A));
uint8_t p2val = digitalRead(Pin(GPIO_ROT1B));
uint8_t state = Rotary.state & 3;
if (p1val) { state |= 4; }
if (p2val) { state |= 8; }
Rotary.state = (state >> 2);
switch (state) {
case 1: case 7: case 8: case 14:
Rotary.position++;
return;
case 2: case 4: case 11: case 13:
Rotary.position--;
return;
case 3: case 12:
Rotary.position += 2;
return;
case 6: case 9:
Rotary.position -= 2;
return;
}
*/
uint8_t p1val = digitalRead(Pin(GPIO_ROT1A));
uint8_t p2val = digitalRead(Pin(GPIO_ROT1B));
uint8_t state = Rotary.state & 3;
if (p1val) { state |= 4; }
if (p2val) { state |= 8; }
Rotary.state = (state >> 2);
int direction = 0;
int multiply = 1;
switch (state) {
case 3: case 12:
multiply = 2;
case 1: case 7: case 8: case 14:
direction = 1;
break;
case 6: case 9:
multiply = 2;
case 2: case 4: case 11: case 13:
direction = -1;
break;
}
if ((0 == Rotary.direction) || (direction == Rotary.direction)) {
Rotary.position += (direction * multiply);
Rotary.direction = direction;
}
#endif // ROTARY_OPTION1
#ifdef ROTARY_OPTION2
// https://github.com/FrankBoesing/EncoderBounce/blob/master/EncoderBounce.h
/*
const uint16_t rot_enc = 0b0110100110010110;
uint8_t p1val = digitalRead(Pin(GPIO_ROT1B));
uint8_t p2val = digitalRead(Pin(GPIO_ROT1A));
uint8_t t = Rotary.prev_next_code;
t <<= 2;
if (p1val) { t |= 0x02; }
if (p2val) { t |= 0x01; }
t &= 0x0f;
Rotary.prev_next_code = t;
// If valid then store as 16 bit data.
if (rot_enc & (1 << t)) {
Rotary.store = (Rotary.store << 4) | Rotary.prev_next_code;
if (Rotary.store == 0xd42b) { Rotary.position++; }
else if (Rotary.store == 0xe817) { Rotary.position--; }
else if ((Rotary.store & 0xff) == 0x2b) { Rotary.position--; }
else if ((Rotary.store & 0xff) == 0x17) { Rotary.position++; }
}
*/
const uint16_t rot_enc = 0b0110100110010110;
uint8_t p1val = digitalRead(Pin(GPIO_ROT1B));
uint8_t p2val = digitalRead(Pin(GPIO_ROT1A));
uint8_t t = Rotary.prev_next_code;
t <<= 2;
if (p1val) { t |= 0x02; }
if (p2val) { t |= 0x01; }
t &= 0x0f;
Rotary.prev_next_code = t;
// If valid then store as 16 bit data.
if (rot_enc & (1 << t)) {
Rotary.store = (Rotary.store << 4) | Rotary.prev_next_code;
int direction = 0;
if (Rotary.store == 0xd42b) { direction = 1; }
else if (Rotary.store == 0xe817) { direction = -1; }
else if ((Rotary.store & 0xff) == 0x2b) { direction = -1; }
else if ((Rotary.store & 0xff) == 0x17) { direction = 1; }
if ((0 == Rotary.direction) || (direction == Rotary.direction)) {
Rotary.position += direction;
Rotary.direction = direction;
}
}
#endif // ROTARY_OPTION2
#ifdef ROTARY_OPTION3
// Theo Arends
uint32_t time = micros();
if (Rotary.debounce < time) {
int direction = (digitalRead(Pin(GPIO_ROT1B))) ? 1 : -1;
if ((0 == Rotary.direction) || (direction == Rotary.direction)) {
Rotary.position += direction;
Rotary.direction = direction;
if (Encoder[index].debounce < time) {
int direction = (digitalRead(Encoder[index].pin)) ? -1 : 1;
if ((0 == Encoder[index].direction) || (direction == Encoder[index].direction)) {
Encoder[index].position += direction;
Encoder[index].direction = direction;
}
Rotary.debounce = time +20; // Experimental debounce
Encoder[index].debounce = time +50; // Experimental debounce in microseconds
}
#endif // ROTARY_OPTION3
}
bool RotaryButtonPressed(void) {
void ICACHE_RAM_ATTR RotaryIsr1(void) {
RotaryIsr(0);
}
void ICACHE_RAM_ATTR RotaryIsr2(void) {
RotaryIsr(1);
}
bool RotaryButtonPressed(uint32_t button_index) {
if (!Rotary.present) { return false; }
bool powered_on = (power);
for (uint32_t index = 0; index < MAX_ROTARIES; index++) {
if (-1 == Encoder[index].pin) { continue; }
if (index != button_index) { continue; }
bool powered_on = (power);
#ifdef USE_LIGHT
if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control
powered_on = LightPower();
}
if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control
powered_on = LightPower();
}
#endif // USE_LIGHT
if (Rotary.changed && powered_on) {
Rotary.changed = false; // Color (temp) changed, no need to turn of the light
return true;
if (Encoder[index].changed && powered_on) {
Encoder[index].changed = false; // Color (temp) changed, no need to turn of the light
return true;
}
return false;
}
return false;
}
void RotaryInit(void) {
Rotary.present = 0;
if (PinUsed(GPIO_ROT1A) && PinUsed(GPIO_ROT1B)) {
Rotary.present++;
pinMode(Pin(GPIO_ROT1A), INPUT_PULLUP);
pinMode(Pin(GPIO_ROT1B), INPUT_PULLUP);
#ifdef ROTARY_OPTION3
attachInterrupt(Pin(GPIO_ROT1A), update_rotary, RISING);
#else
attachInterrupt(Pin(GPIO_ROT1A), update_rotary, CHANGE);
attachInterrupt(Pin(GPIO_ROT1B), update_rotary, CHANGE);
#endif
Rotary.present = false;
for (uint32_t index = 0; index < MAX_ROTARIES; index++) {
#ifdef ESP8266
uint32_t idx = index *2;
#else // ESP32
uint32_t idx = index;
#endif // ESP8266 or ESP32
if (PinUsed(GPIO_ROT1A, idx) && PinUsed(GPIO_ROT1B, idx)) {
Encoder[index].pin = Pin(GPIO_ROT1B, idx);
pinMode(Encoder[index].pin, INPUT_PULLUP);
pinMode(Pin(GPIO_ROT1A, idx), INPUT_PULLUP);
if (0 == index) {
attachInterrupt(Pin(GPIO_ROT1A, idx), RotaryIsr1, FALLING);
} else {
attachInterrupt(Pin(GPIO_ROT1A, idx), RotaryIsr2, FALLING);
}
}
Rotary.present |= (Encoder[index].pin > -1);
}
}
@ -250,56 +136,80 @@ void RotaryInit(void) {
void RotaryHandler(void) {
if (!Rotary.present) { return; }
if (Rotary.timeout) {
Rotary.timeout--;
if (!Rotary.timeout) {
Rotary.direction = 0;
for (uint32_t index = 0; index < MAX_ROTARIES; index++) {
if (-1 == Encoder[index].pin) { continue; }
if (Encoder[index].timeout) {
Encoder[index].timeout--;
if (!Encoder[index].timeout) {
#ifdef USE_LIGHT
if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control
ResponseLightState(0);
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_STATE));
XdrvRulesProcess();
}
#endif // USE_LIGHT
Encoder[index].direction = 0;
}
}
}
if (Rotary.last_position == Rotary.position) { return; }
Rotary.busy = true;
if (Encoder[index].last_position == Encoder[index].position) { continue; }
Encoder[index].busy = true;
Rotary.timeout = ROTARY_TIMEOUT; // Prevent fast direction changes within 0.5 second
Encoder[index].timeout = ROTARY_TIMEOUT; // Prevent fast direction changes within 0.5 second
int rotary_position = Rotary.position - Rotary.last_position;
int rotary_position = Encoder[index].position - Encoder[index].last_position;
if (Settings.save_data && (save_data_counter < 2)) {
save_data_counter = 2; // Postpone flash writes while rotary is turned
}
if (Settings.save_data && (save_data_counter < 2)) {
save_data_counter = 2; // Postpone flash writes while rotary is turned
}
bool button_pressed = (Button.hold_timer[0]); // Button1 is pressed: set color temperature
if (button_pressed) { Rotary.changed = true; }
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ROT: Button1 %d, Position %d"), button_pressed, rotary_position);
bool button_pressed = (Button.hold_timer[index]); // Button is pressed: set color temperature
if (button_pressed) { Encoder[index].changed = true; }
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ROT: Button1 %d, Position %d"), button_pressed, rotary_position);
#ifdef USE_LIGHT
if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control
if (button_pressed) {
if (!LightColorTempOffset(rotary_position * rotary_ct_increment)) {
LightColorOffset(rotary_position * rotary_color_increment);
if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control
bool second_rotary = (Encoder[1].pin > -1);
if (0 == index) { // Rotary1
if (button_pressed) {
if (second_rotary) { // Color RGB
LightColorOffset(rotary_position * rotary_color_increment);
} else { // Color Temperature or Color RGB
if (!LightColorTempOffset(rotary_position * rotary_ct_increment)) {
LightColorOffset(rotary_position * rotary_color_increment);
}
}
} else { // Dimmer RGBCW or RGB only if second rotary
LightDimmerOffset(second_rotary ? 1 : 0, rotary_position * rotary_dimmer_increment);
}
} else { // Rotary2
if (button_pressed) { // Color Temperature
LightColorTempOffset(rotary_position * rotary_ct_increment);
} else { // Dimmer CW
LightDimmerOffset(2, rotary_position * rotary_dimmer_increment);
}
}
} else {
LightDimmerOffset(rotary_position * rotary_dimmer_increment);
}
} else {
#endif // USE_LIGHT
if (button_pressed) {
Rotary.abs_position2 += rotary_position;
if (Rotary.abs_position2 < 0) { Rotary.abs_position2 = 0; }
if (Rotary.abs_position2 > ROTARY_MAX_STEPS) { Rotary.abs_position2 = ROTARY_MAX_STEPS; }
} else {
Rotary.abs_position1 += rotary_position;
if (Rotary.abs_position1 < 0) { Rotary.abs_position1 = 0; }
if (Rotary.abs_position1 > ROTARY_MAX_STEPS) { Rotary.abs_position1 = ROTARY_MAX_STEPS; }
}
Response_P(PSTR("{\"Rotary1\":{\"Pos1\":%d,\"Pos2\":%d}}"), Rotary.abs_position1, Rotary.abs_position2);
XdrvRulesProcess();
if (button_pressed) {
Encoder[index].abs_position2 += rotary_position;
if (Encoder[index].abs_position2 < 0) { Encoder[index].abs_position2 = 0; }
if (Encoder[index].abs_position2 > ROTARY_MAX_STEPS) { Encoder[index].abs_position2 = ROTARY_MAX_STEPS; }
} else {
Encoder[index].abs_position1 += rotary_position;
if (Encoder[index].abs_position1 < 0) { Encoder[index].abs_position1 = 0; }
if (Encoder[index].abs_position1 > ROTARY_MAX_STEPS) { Encoder[index].abs_position1 = ROTARY_MAX_STEPS; }
}
Response_P(PSTR("{\"Rotary%d\":{\"Pos1\":%d,\"Pos2\":%d}}"), index +1, Encoder[index].abs_position1, Encoder[index].abs_position2);
XdrvRulesProcess();
#ifdef USE_LIGHT
}
}
#endif // USE_LIGHT
Rotary.last_position = 128;
Rotary.position = 128;
Rotary.busy = false;
Encoder[index].last_position = 128;
Encoder[index].position = 128;
Encoder[index].busy = false;
}
}
#endif // ROTARY_V1

View File

@ -663,7 +663,7 @@ void MqttShowState(void)
for (uint32_t i = 1; i <= devices_present; i++) {
#ifdef USE_LIGHT
if ((LightDevice()) && (i >= LightDevice())) {
if (i == LightDevice()) { LightState(1); } // call it only once
if (i == LightDevice()) { ResponseLightState(1); } // call it only once
} else {
#endif
ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), // SetOption26 - Switch between POWER or POWER1

View File

@ -84,6 +84,7 @@ const uint8_t MAX_GROUP_TOPICS = 4; // Max number of Group Topics
const uint8_t MAX_DEV_GROUP_NAMES = 4; // Max number of Device Group names
const uint8_t MAX_HUE_DEVICES = 15; // Max number of Philips Hue device per emulation
const uint8_t MAX_ROTARIES = 2; // Max number of Rotary Encoders
const char MQTT_TOKEN_PREFIX[] PROGMEM = "%prefix%"; // To be substituted by mqtt_prefix[x]
const char MQTT_TOKEN_TOPIC[] PROGMEM = "%topic%"; // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic

View File

@ -373,6 +373,12 @@ const uint8_t kGpioNiceList[] PROGMEM = {
GPIO_SWT7_NP,
GPIO_SWT8,
GPIO_SWT8_NP,
#ifdef ROTARY_V1
GPIO_ROT1A, // Rotary switch1 A Pin
GPIO_ROT1B, // Rotary switch1 B Pin
GPIO_ROT2A, // Rotary switch2 A Pin
GPIO_ROT2B, // Rotary switch2 B Pin
#endif
GPIO_REL1, // Relays
GPIO_REL1_INV,
GPIO_REL2,
@ -665,12 +671,6 @@ const uint8_t kGpioNiceList[] PROGMEM = {
GPIO_MAX31855CLK, // MAX31855 Serial interface
GPIO_MAX31855DO, // MAX31855 Serial interface
#endif
#ifdef ROTARY_V1
GPIO_ROT1A, // Rotary switch1 A Pin
GPIO_ROT1B, // Rotary switch1 B Pin
GPIO_ROT2A, // Rotary switch2 A Pin
GPIO_ROT2B, // Rotary switch2 B Pin
#endif
#ifdef USE_HRE
GPIO_HRE_CLOCK,
GPIO_HRE_DATA,

View File

@ -88,7 +88,10 @@ enum UserSelectablePins {
GPIO_CSE7766_TX, GPIO_CSE7766_RX, // CSE7766 Serial interface (S31 and Pow R2)
GPIO_ARIRFRCV, GPIO_ARIRFSEL, // Arilux RF Receive input
GPIO_TXD, GPIO_RXD, // Serial interface
GPIO_ROT1A, GPIO_ROT1B, GPIO_ROT2A, GPIO_ROT2B, // Rotary switch
GPIO_ROT1A, GPIO_ROT1B, // Rotary switch
GPIO_SPARE1, GPIO_SPARE2, // Spare GPIOs
GPIO_HRE_CLOCK, GPIO_HRE_DATA, // HR-E Water Meter
GPIO_ADE7953_IRQ, // ADE7953 IRQ
GPIO_SOLAXX1_TX, GPIO_SOLAXX1_RX, // Solax Inverter Serial interface
@ -188,7 +191,10 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_CSE7766_TX "|" D_SENSOR_CSE7766_RX "|"
D_SENSOR_ARIRFRCV "|" D_SENSOR_ARIRFSEL "|"
D_SENSOR_TXD "|" D_SENSOR_RXD "|"
D_SENSOR_ROTARY "_1a|" D_SENSOR_ROTARY "_1b|" D_SENSOR_ROTARY "_2a|" D_SENSOR_ROTARY "_2b|"
D_SENSOR_ROTARY "_a|" D_SENSOR_ROTARY "_b|"
"Spare1|Spare2|"
D_SENSOR_HRE_CLOCK "|" D_SENSOR_HRE_DATA "|"
D_SENSOR_ADE7953_IRQ "|"
D_SENSOR_SOLAXX1_TX "|" D_SENSOR_SOLAXX1_RX "|"
@ -245,6 +251,10 @@ const uint16_t kGpioNiceList[] PROGMEM = {
AGPIO(GPIO_KEY1_TC) + MAX_KEYS, // Touch button
AGPIO(GPIO_SWT1) + MAX_SWITCHES, // User connected external switches
AGPIO(GPIO_SWT1_NP) + MAX_SWITCHES,
#ifdef ROTARY_V1
AGPIO(GPIO_ROT1A) + MAX_ROTARIES, // Rotary A Pin
AGPIO(GPIO_ROT1B) + MAX_ROTARIES, // Rotary B Pin
#endif
AGPIO(GPIO_REL1) + MAX_RELAYS, // Relays
AGPIO(GPIO_REL1_INV) + MAX_RELAYS,
AGPIO(GPIO_LED1) + MAX_LEDS, // Leds
@ -508,12 +518,6 @@ const uint16_t kGpioNiceList[] PROGMEM = {
AGPIO(GPIO_MAX31855CLK), // MAX31855 Serial interface
AGPIO(GPIO_MAX31855DO), // MAX31855 Serial interface
#endif
#ifdef ROTARY_V1
AGPIO(GPIO_ROT1A), // Rotary switch1 A Pin
AGPIO(GPIO_ROT1B), // Rotary switch1 B Pin
AGPIO(GPIO_ROT2A), // Rotary switch2 A Pin
AGPIO(GPIO_ROT2B), // Rotary switch2 B Pin
#endif
#ifdef USE_HRE
AGPIO(GPIO_HRE_CLOCK),
AGPIO(GPIO_HRE_DATA),

View File

@ -314,16 +314,6 @@ power_t LightPower(void)
return Light.power; // Make external
}
// IRAM variant for rotary
#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception
power_t LightPowerIRAM(void) ICACHE_RAM_ATTR;
#endif // ARDUINO_ESP8266_RELEASE_2_3_0
power_t LightPowerIRAM(void)
{
return Light.power; // Make external
}
uint8_t LightDevice(void)
{
return Light.device; // Make external
@ -1568,7 +1558,7 @@ void LightPowerOn(void)
}
}
void LightState(uint8_t append)
void ResponseLightState(uint8_t append)
{
char scolor[LIGHT_COLOR_SIZE];
char scommand[33];
@ -1718,7 +1708,7 @@ void LightPreparePower(power_t channels = 0xFFFFFFFF) { // 1 = only RGB, 2 =
AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower End power=%d Light.power=%d", power, Light.power);
#endif
Light.power = power >> (Light.device - 1); // reset next state, works also with unlinked RGB/CT
LightState(0);
ResponseLightState(0);
}
#ifdef USE_LIGHT_PALETTE
@ -1886,7 +1876,7 @@ void LightAnimate(void)
MqttPublishPrefixTopic_P(TELE, PSTR(D_CMND_WAKEUP));
*/
Response_P(PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\""));
LightState(1);
ResponseLightState(1);
ResponseJsonEnd();
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_WAKEUP));
XdrvRulesProcess();
@ -2689,7 +2679,7 @@ void CmndHsbColor(void)
light_controller.changeHSB(HSB[0], HSB[1], HSB[2]);
LightPreparePower(1);
} else {
LightState(0);
ResponseLightState(0);
}
}
}
@ -2774,12 +2764,12 @@ void CmndColorTemperature(void)
}
}
void LightDimmerOffset(int32_t offset) {
int32_t dimmer = light_state.getDimmer() + offset;
if (dimmer < 1) { dimmer = 1; }
void LightDimmerOffset(uint32_t index, int32_t offset) {
int32_t dimmer = light_state.getDimmer(index) + offset;
if (dimmer < 1) { dimmer = Settings.flag3.slider_dimmer_stay_on; } // SetOption77 - Do not power off if slider moved to far left
if (dimmer > 100) { dimmer = 100; }
XdrvMailbox.index = 0;
XdrvMailbox.index = index;
XdrvMailbox.payload = dimmer;
CmndDimmer();
}

View File

@ -375,12 +375,19 @@ bool Ds18x20Read(uint8_t sensor)
if (OneWireCrc8(data)) {
switch(ds18x20_sensor[index].address[0]) {
case DS18S20_CHIPID: {
/*
if (data[1] > 0x80) {
data[0] = (~data[0]) +1;
sign = -1; // App-Note fix possible sign error
}
float temp9 = (float)(data[0] >> 1) * sign;
ds18x20_sensor[index].temperature = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0));
Replaced by below based on issue #8777
*/
int16_t tempS = (((data[1] << 8) | (data[0] & 0xFE)) << 3) | ((0x10 - data[6]) & 0x0F);
ds18x20_sensor[index].temperature = ConvertTemp(tempS * 0.0625 - 0.250);
ds18x20_sensor[index].valid = SENSOR_MAX_MISS;
return true;
}

View File

@ -83,8 +83,9 @@
#define NLIGHT 7
#define MJYD2S 8
#define YEERC 9
#define MHOC401 10
#define MI_TYPES 9 //count this manually
#define MI_TYPES 10 //count this manually
#define D_CMND_NRF "NRF"
@ -119,7 +120,8 @@ const uint16_t kMINRFDeviceID[MI_TYPES]={ 0x0098, // Flora
0x0576, // CGD1
0x03dd, // NLIGHT
0x07f6, // MJYD2S
0x0153 // yee-rc
0x0153, // yee-rc
0x0387 // MHO-C401
};
const char kMINRFDeviceType1[] PROGMEM = "Flora";
@ -131,7 +133,8 @@ const char kMINRFDeviceType6[] PROGMEM = "CGD1";
const char kMINRFDeviceType7[] PROGMEM = "NLIGHT";
const char kMINRFDeviceType8[] PROGMEM = "MJYD2S";
const char kMINRFDeviceType9[] PROGMEM = "YEERC";
const char * kMINRFDeviceType[] PROGMEM = {kMINRFDeviceType1,kMINRFDeviceType2,kMINRFDeviceType3,kMINRFDeviceType4,kMINRFDeviceType5,kMINRFDeviceType6,kMINRFDeviceType7,kMINRFDeviceType8,kMINRFDeviceType9};
const char kMINRFDeviceType10[] PROGMEM = "MHOC401";
const char * kMINRFDeviceType[] PROGMEM = {kMINRFDeviceType1,kMINRFDeviceType2,kMINRFDeviceType3,kMINRFDeviceType4,kMINRFDeviceType5,kMINRFDeviceType6,kMINRFDeviceType7,kMINRFDeviceType8,kMINRFDeviceType9,kMINRFDeviceType10};
// PDU's or different channels 37-39
const uint32_t kMINRFFloPDU[3] = {0x3eaa857d,0xef3b8730,0x71da7b46};
@ -411,7 +414,7 @@ bool MINRFreceivePacket(void)
case 1: case 3:
MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_A[MINRF.currentChan]); // "flora" mode, "LYWSD02" mode
break;
case 2: case 4: case 5: case 6:
case 2: case 4: case 5: case 6: case MHOC401:
MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); // "MJ_HT_V1" mode, LYWSD03" mode, "CGG1" mode, "CGD1" mode
break;
case 9:
@ -919,7 +922,7 @@ void MINRFchangePacketModeTo(uint8_t _mode) {
case 3: // special LYWSD02 packet
NRF24radio.openReadingPipe(0,kMINRFL2PDU[_nextchannel]);// 95 fe 70 20 -> LYWSD02
break;
case 4: // special LYWSD03 packet
case 4: case MHOC401: // special LYWSD03 packet, MHOC401 has the same
NRF24radio.openReadingPipe(0,kMINRFL3PDU[_nextchannel]);// 95 fe 58 58 -> LYWSD03 (= encrypted data message)
break;
case 5: // special CGG1 packet
@ -1068,7 +1071,7 @@ void MINRFhandleMiBeaconPacket(void){
memcpy((uint8_t*)&MINRF.buffer.miBeacon.type,MINRFtempBuf, 32-9); // shift by one byte for the MJ_HT_V1 and CGG1
break;
#ifdef USE_MI_DECRYPTION
case LYWSD03:
case LYWSD03: case MHOC401:
decryptRet = MINRFdecryptPacket((char*)&MINRF.buffer); //start with PID
if(decryptRet==1) _sensorVec->showedUp=255; // if decryption worked, this must be a valid sensor
break;
@ -1324,7 +1327,7 @@ void MINRF_EVERY_50_MSECOND() { // Every 50mseconds
}
else MINRFhandleScan();
break;
case FLORA: case MJ_HT_V1: case LYWSD02: case CGG1: case LYWSD03: case YEERC:
case FLORA: case MJ_HT_V1: case LYWSD02: case CGG1: case LYWSD03: case YEERC: case MHOC401:
MINRFhandleMiBeaconPacket();
break;
case CGD1:

File diff suppressed because it is too large Load Diff