Browse Source

KingArt WiFi Curtain Switch (#2063)

This will add support for the KingArt Wifi Curtain Switch. There are no buttons in the web interface as I could not figure out how to create them (any help on that is welcome).

For now the switch can be controlled over MQTT:
"{hostname}/curtain/set"
"{hostname}/curtain"
mcspr-patch-1
Albert Weterings 4 years ago
committed by GitHub
parent
commit
ff2718e8ca
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 246 additions and 9 deletions
  1. +2
    -1
      code/espurna/config/arduino.h
  2. +1
    -0
      code/espurna/config/general.h
  3. +17
    -1
      code/espurna/config/hardware.h
  4. +198
    -0
      code/espurna/curtain_kingart.cpp
  5. +12
    -0
      code/espurna/curtain_kingart.h
  6. +4
    -0
      code/espurna/main.cpp
  7. +4
    -0
      code/platformio.ini
  8. +8
    -7
      code/test/build/nondefault.h

+ 2
- 1
code/espurna/config/arduino.h View File

@ -105,6 +105,7 @@
//#define JANGOE_WIFI_RELAY_NO
//#define JINVOO_VALVE_SM_AW713
//#define JORGEGARCIA_WIFI_RELAYS
//#define KINGART_CURTAIN_SWITCH
//#define KMC_70011
//#define KOGAN_SMARTER_HOME_PLUG_W_POW
//#define LINGAN_SWA1
@ -126,8 +127,8 @@
//#define MAGICHOME_ZJ_WFMN_C_11
//#define MANCAVEMADE_ESPLIVE
//#define MAXCIO_WDE004
//#define MAXCIO_WUS002S
//#define MAXCIO_WUK007S
//#define MAXCIO_WUS002S
//#define MUVIT_IO_MIOBULB001
//#define NEO_COOLCAM_NAS_WR01W
//#define NEXETE_A19


+ 1
- 0
code/espurna/config/general.h View File

@ -1162,6 +1162,7 @@
#define MQTT_TOPIC_IROUT "irout"
#define MQTT_TOPIC_OTA "ota"
#define MQTT_TOPIC_TELNET_REVERSE "telnet_reverse"
#define MQTT_TOPIC_CURTAIN "curtain"
// Light module
#define MQTT_TOPIC_CHANNEL "channel"


+ 17
- 1
code/espurna/config/hardware.h View File

@ -4550,6 +4550,23 @@
#define SENSOR_ENERGY_UNITS ENERGY_KWH
#define SENSOR_POWER_UNITS POWER_WATTS
// -----------------------------------------------------------------------------
// KINGART_CURTAIN_SWITCH
// -----------------------------------------------------------------------------
#elif defined(KINGART_CURTAIN_SWITCH)
// Info
#define MANUFACTURER "KINGART"
#define DEVICE "CURTAIN_SWITCH"
// LEDs
#define LED1_PIN 13
#define LED1_PIN_INVERSE 1
// KINGART module handles the UART, can't print any debug messages
#define KINGART_CURTAIN_SUPPORT 1
#define DEBUG_SERIAL_SUPPORT 0
// -----------------------------------------------------------------------------
// LSC Smart LED Light Strip (Smart CXonnect Series) available ACTION (Germany)
// https://www.action.com/de-de/p/lsc-smart-connect-intelligenter-multicolor-led-strip-/
@ -4641,4 +4658,3 @@
#error "UNSUPPORTED HARDWARE!!"
#endif

+ 198
- 0
code/espurna/curtain_kingart.cpp View File

@ -0,0 +1,198 @@
/*
KingArt Cover/Shutter/Blind/Curtain support for ESPURNA
Based on xdrv_19_ps16dz.dimmer.ino, PS_16_DZ dimmer support for Tasmota
Copyright (C) 2019 by Albert Weterings
*/
#include "curtain_kingart.h"
#if KINGART_CURTAIN_SUPPORT
#include "ntp.h"
#include "mqtt.h"
#ifndef KINGART_CURTAIN_PORT
#define KINGART_CURTAIN_PORT Serial // Hardware serial port by default
#endif
#ifndef KINGART_CURTAIN_BUFFER_SIZE
#define KINGART_CURTAIN_BUFFER_SIZE 100 // Local UART buffer size
#endif
#define KINGART_CURTAIN_TERMINATION '\e' // Termination character after each message
#define KINGART_CURTAIN_BAUDRATE 19200 // Serial speed is fixed for the device
char _KACurtainBuffer[KINGART_CURTAIN_BUFFER_SIZE];
bool _KACurtainNewData = false;
// -----------------------------------------------------------------------------
// Private
// -----------------------------------------------------------------------------
void _KACurtainSend(const char * tx_buffer) {
KINGART_CURTAIN_PORT.print(tx_buffer);
KINGART_CURTAIN_PORT.print(KINGART_CURTAIN_TERMINATION);
KINGART_CURTAIN_PORT.flush();
}
void _KACurtainReceiveUART() {
static unsigned char ndx = 0;
while (KINGART_CURTAIN_PORT.available() > 0 && !_KACurtainNewData) {
char rc = KINGART_CURTAIN_PORT.read();
if (rc != KINGART_CURTAIN_TERMINATION) {
_KACurtainBuffer[ndx] = rc;
if (ndx < KINGART_CURTAIN_BUFFER_SIZE - 1) ndx++;
} else {
_KACurtainBuffer[ndx] = '\0';
_KACurtainNewData = true;
ndx = 0;
}
}
}
/*
Buttons on the device will move Cover/Shutter/Blind/Curtain up/open or down/close On the end of
every movement the unit reports the last action and posiston over MQTT topic {hostname}/curtain
RAW paylod format looks like:
AT+UPDATE="switch":"on","setclose":13
AT+UPDATE="switch":"off","setclose":38
AT+UPDATE="switch":"pause","setclose":75
The device is listening to MQTT topic {hostname}/curtain/set, to which you can send:
- position value, in range from 0 to 100
- "pause", to stop the movement.
The device will determine the direction all by itself.
# Set the Cover / Shutter / Blind / Curtain run time
The factory default Open and Close run time for the switch is 50 seconds, and it must be set to
an accurate run time for smooth working. Some motors do not have the resistance stop function,
so when the Cover/Shutter/Blind/Curtain track open or close to the maximum length, but the motor keeps on running.
This might cause damage on the motor and the switch, it also wastes a lot of energy. In order
to protect the motor, this switch designed with a time setting function. After setting up the run time,
the switch will automaticly stop when the track reaches its limits. The run time setting is also helpful
for the accurate control when manually controlling the device via the touch panel.
After installing the switch and connecting the switch for the very first time:
- First, it will automatically close the Cover/Shutter/Blind/Curtain to the maximum.
- Press and hold the touch interface pause button for around 4 seconds until the red background
led lights up and starts blinking. Then, press the open touch button so start the opening process.
- When cover is fully open, press the Open or Close button to stop the timer and save the calculated run time.
To configure the device:
- Press up/down for 5 seconds to bring device into AP mode. After pressing up/down again, device will restart in normal mode.
*/
void _KACurtainResult() {
if (_KACurtainNewData) {
// Need to send confiramtion to the N76E003AT20 that message is received
_KACurtainSend("AT+SEND=ok");
// We don't handle "setclose" any other way, simply redirect payload value
const String buffer(_KACurtainBuffer);
#if MQTT_SUPPORT
int setclose_idx = buffer.indexOf("setclose");
if (setclose_idx > 0) {
auto position = buffer.substring(setclose_idx + strlen("setclose") + 2, buffer.length());
int leftovers = position.indexOf(',');
if (leftovers > 0) {
position = position.substring(0, leftovers);
}
mqttSend(MQTT_TOPIC_CURTAIN, position.c_str());
}
#endif // MQTT_SUPPORT
// Handle configuration button presses
if (buffer.indexOf("enterESPTOUCH") > 0) {
wifiStartAP();
} else if (buffer.indexOf("exitESPTOUCH") > 0) {
deferredReset(100, CUSTOM_RESET_HARDWARE);
}
_KACurtainNewData = false;
}
}
// %d = now() / time_t / NTP timestamp in seconds
// %03u = millis() / uint32_t / we need last 3 digits
// %s = char strings for various actions
// Tell N76E003AT20 to stop moving and report current position
void _KACurtainPause(const char * message) {
char tx_buffer[80] = {0};
snprintf_P(
tx_buffer, sizeof(tx_buffer),
PSTR("AT+UPDATE=\"sequence\":\"%d%03u\",\"switch\":\"%s\""),
now(), millis() % 1000,
message
);
_KACurtainSend(tx_buffer);
}
// Tell N76E003AT20 to go to position X (based on X N76E003AT20 decides to go up or down)
void _KACurtainSetclose(const char * message) {
char tx_buffer[80] = {0};
snprintf_P(
tx_buffer, sizeof(tx_buffer),
PSTR("AT+UPDATE=\"sequence\":\"%d%03u\",\"switch\":\"%s\",\"setclose\":%s"),
now(), millis() % 1000,
"off", message
);
_KACurtainSend(tx_buffer);
}
#if MQTT_SUPPORT
void _KACurtainActionSelect(const char * message) {
if (strcmp(message, "pause") == 0) {
_KACurtainPause(message);
} else {
_KACurtainSetclose(message);
}
}
void _KACurtainCallback(unsigned int type, const char * topic, char * payload) {
if (type == MQTT_CONNECT_EVENT) {
mqttSubscribe(MQTT_TOPIC_CURTAIN);
}
if (type == MQTT_MESSAGE_EVENT) {
// Match topic
const String t = mqttMagnitude(const_cast<char*>(topic));
if (t.equals(MQTT_TOPIC_CURTAIN)) {
_KACurtainActionSelect(payload);
}
}
}
#endif // MQTT_SUPPORT
// -----------------------------------------------------------------------------
// SETUP & LOOP
// -----------------------------------------------------------------------------
void _KACurtainLoop() {
_KACurtainReceiveUART();
_KACurtainResult();
}
void kingartCurtainSetup() {
// Init port to receive and send messages
KINGART_CURTAIN_PORT.begin(KINGART_CURTAIN_BAUDRATE);
// Register MQTT callback only when supported
#if MQTT_SUPPORT
mqttRegister(_KACurtainCallback);
#endif // MQTT_SUPPORT
// Register loop to poll the UART for new messages
espurnaRegisterLoop(_KACurtainLoop);
}
#endif // KINGART_CURTAIN_SUPPORT

+ 12
- 0
code/espurna/curtain_kingart.h View File

@ -0,0 +1,12 @@
/*
KingArt Cover/Shutter/Blind/Curtain support for ESPURNA
Based on xdrv_19_ps16dz.dimmer.ino, PS_16_DZ dimmer support for Tasmota
Copyright (C) 2019 by Albert Weterings
*/
#include "espurna.h"
void kingartCurtainSetup();

+ 4
- 0
code/espurna/main.cpp View File

@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "broker.h"
#include "button.h"
#include "crash.h"
#include "curtain_kingart.h"
#include "debug.h"
#include "domoticz.h"
#include "encoder.h"
@ -279,6 +280,9 @@ void setup() {
#if TUYA_SUPPORT
Tuya::tuyaSetup();
#endif
#if KINGART_CURTAIN_SUPPORT
kingartCurtainSetup();
#endif
// 3rd party code hook
#if USE_EXTRA


+ 4
- 0
code/platformio.ini View File

@ -999,6 +999,10 @@ src_build_flags = -DEHOMEDIY_WT02
extends = env:esp8266-1m-base
src_build_flags = -DEHOMEDIY_WT03
[env:kingart-curtain-switch]
extends = env:esp8266-1m-base
src_build_flags = -DKINGART_CURTAIN_SWITCH
[env:aoycocr-x5p]
extends = env:esp8266-1m-base
src_build_flags = -DAOYCOCR_X5P

+ 8
- 7
code/test/build/nondefault.h View File

@ -1,12 +1,13 @@
#define INFLUXDB_SUPPORT 1
#define KINGART_CURTAIN_SUPPORT 1
#define LLMNR_SUPPORT 1
#define NETBIOS_SUPPORT 1
#define SSDP_SUPPORT 1
#define RF_SUPPORT 1
#define RFB_DIRECT 1
#define MDNS_CLIENT_SUPPORT 1
#define NETBIOS_SUPPORT 1
#define NOFUSS_SUPPORT 1
#define UART_MQTT_SUPPORT 1
#define INFLUXDB_SUPPORT 1
#define OTA_MQTT_SUPPORT 1
#define RPN_RULES_SUPPORT 1
#define RFB_DIRECT 1
#define RFM69_SUPPORT 1
#define RF_SUPPORT 1
#define RPN_RULES_SUPPORT 1
#define SSDP_SUPPORT 1
#define UART_MQTT_SUPPORT 1

Loading…
Cancel
Save