mirror of https://github.com/arendst/Tasmota.git
Merge pull request #2 from arendst/development
Pull request to catch up to arendst/Tasmota development branch.
This commit is contained in:
commit
676c3dd1f0
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue