mirror of https://github.com/arendst/Tasmota.git
184 lines
5.0 KiB
C++
184 lines
5.0 KiB
C++
#include <esp-knx-ip.h>
|
|
|
|
// WiFi config here
|
|
const char* ssid = "ssid";
|
|
const char* pass = "pass";
|
|
|
|
// Common
|
|
#define LED_PIN 13
|
|
|
|
// For Basic and S20
|
|
#define BTN1_PIN 0
|
|
#define CH1_PIN 12
|
|
|
|
// For 4CH
|
|
#define BTN2_PIN 9
|
|
#define CH2_PIN 5
|
|
#define BTN3_PIN 10
|
|
#define CH3_PIN 4
|
|
#define BTN4_PIN 14
|
|
#define CH4_PIN 15
|
|
|
|
typedef enum __type_option
|
|
{
|
|
SONOFF_TYPE_NONE = 0,
|
|
SONOFF_TYPE_BASIC = 1,
|
|
SONOFF_TYPE_S20 = 2,
|
|
SONOFF_TYPE_4CH = 3,
|
|
SONOFF_TYPE_4CH_PRO = 4,
|
|
} type_option_t;
|
|
|
|
option_entry_t type_options[] = {
|
|
{"Sonoff Basic", SONOFF_TYPE_BASIC},
|
|
{"Sonoff S20", SONOFF_TYPE_S20},
|
|
{"Sonoff 4CH", SONOFF_TYPE_4CH},
|
|
{"Sonoff 4CH Pro", SONOFF_TYPE_4CH_PRO},
|
|
{nullptr, 0}
|
|
};
|
|
|
|
config_id_t hostname_id;
|
|
config_id_t type_id;
|
|
|
|
typedef struct __sonoff_channel
|
|
{
|
|
int pin;
|
|
int btn_pin;
|
|
config_id_t status_ga_id;
|
|
bool state;
|
|
bool last_btn_state;
|
|
} sonoff_channel_t;
|
|
|
|
sonoff_channel_t channels[] = {
|
|
{CH1_PIN, BTN1_PIN, 0, false, false},
|
|
{CH2_PIN, BTN2_PIN, 0, false, false},
|
|
{CH3_PIN, BTN3_PIN, 0, false, false},
|
|
{CH4_PIN, BTN4_PIN, 0, false, false},
|
|
};
|
|
|
|
void setup()
|
|
{
|
|
pinMode(LED_PIN, OUTPUT);
|
|
pinMode(BTN1_PIN, INPUT_PULLUP);
|
|
pinMode(BTN2_PIN, INPUT_PULLUP);
|
|
pinMode(BTN3_PIN, INPUT_PULLUP);
|
|
pinMode(BTN4_PIN, INPUT_PULLUP);
|
|
pinMode(CH1_PIN, OUTPUT);
|
|
pinMode(CH2_PIN, OUTPUT);
|
|
pinMode(CH3_PIN, OUTPUT);
|
|
pinMode(CH4_PIN, OUTPUT);
|
|
Serial.begin(115200);
|
|
|
|
// Register the config options
|
|
hostname_id = knx.config_register_string("Hostname", 20, String("sonoff"));
|
|
type_id = knx.config_register_options("Type", type_options, SONOFF_TYPE_BASIC);
|
|
|
|
channels[0].status_ga_id = knx.config_register_ga("Channel 1 Status GA");
|
|
channels[1].status_ga_id = knx.config_register_ga("Channel 2 Status GA", is_4ch_or_4ch_pro);
|
|
channels[2].status_ga_id = knx.config_register_ga("Channel 3 Status GA", is_4ch_or_4ch_pro);
|
|
channels[3].status_ga_id = knx.config_register_ga("Channel 4 Status GA", is_4ch_or_4ch_pro);
|
|
|
|
knx.callback_register("Channel 1", channel_cb, &channels[0]);
|
|
knx.callback_register("Channel 2", channel_cb, &channels[1], is_4ch_or_4ch_pro);
|
|
knx.callback_register("Channel 3", channel_cb, &channels[2], is_4ch_or_4ch_pro);
|
|
knx.callback_register("Channel 4", channel_cb, &channels[3], is_4ch_or_4ch_pro);
|
|
|
|
knx.feedback_register_bool("Channel 1 is on", &(channels[0].state));
|
|
knx.feedback_register_action("Toogle channel 1", toggle_chan, &channels[0]);
|
|
knx.feedback_register_bool("Channel 2 is on", &(channels[1].state), is_4ch_or_4ch_pro);
|
|
knx.feedback_register_action("Toogle channel 2", toggle_chan, &channels[1], is_4ch_or_4ch_pro);
|
|
knx.feedback_register_bool("Channel 3 is on", &(channels[2].state), is_4ch_or_4ch_pro);
|
|
knx.feedback_register_action("Toogle channel 3", toggle_chan, &channels[2], is_4ch_or_4ch_pro);
|
|
knx.feedback_register_bool("Channel 4 is on", &(channels[3].state), is_4ch_or_4ch_pro);
|
|
knx.feedback_register_action("Toogle channel 4", toggle_chan, &channels[3], is_4ch_or_4ch_pro);
|
|
|
|
knx.load();
|
|
|
|
// Init WiFi
|
|
WiFi.hostname(knx.config_get_string(hostname_id));
|
|
WiFi.begin(ssid, pass);
|
|
|
|
Serial.println("");
|
|
Serial.print("[Connecting]");
|
|
Serial.print(ssid);
|
|
|
|
digitalWrite(LED_PIN, LOW);
|
|
while (WiFi.status() != WL_CONNECTED) {
|
|
digitalWrite(LED_PIN, HIGH);
|
|
delay(500);
|
|
Serial.print(".");
|
|
digitalWrite(LED_PIN, LOW);
|
|
}
|
|
digitalWrite(LED_PIN, HIGH);
|
|
|
|
// Start knx
|
|
knx.start();
|
|
|
|
Serial.println();
|
|
Serial.println("Connected to wifi");
|
|
Serial.println(WiFi.localIP());
|
|
}
|
|
|
|
void loop()
|
|
{
|
|
knx.loop();
|
|
|
|
// Check local buttons
|
|
check_button(&channels[0]);
|
|
if (is_4ch_or_4ch_pro())
|
|
{
|
|
check_button(&channels[1]);
|
|
check_button(&channels[2]);
|
|
check_button(&channels[3]);
|
|
}
|
|
|
|
delay(50);
|
|
}
|
|
|
|
bool is_basic_or_s20()
|
|
{
|
|
uint8_t type = knx.config_get_options(type_id);
|
|
return type == SONOFF_TYPE_BASIC || type == SONOFF_TYPE_S20;
|
|
}
|
|
|
|
bool is_4ch_or_4ch_pro()
|
|
{
|
|
uint8_t type = knx.config_get_options(type_id);
|
|
return type == SONOFF_TYPE_4CH ||type == SONOFF_TYPE_4CH_PRO;
|
|
}
|
|
|
|
void check_button(sonoff_channel_t *chan)
|
|
{
|
|
bool state_now = digitalRead(chan->btn_pin) == HIGH ? true : false;
|
|
if (state_now != chan->last_btn_state && state_now == LOW)
|
|
{
|
|
chan->state = !chan->state;
|
|
digitalWrite(chan->pin, chan->state ? HIGH : LOW);
|
|
knx.write_1bit(knx.config_get_ga(chan->status_ga_id), chan->state);
|
|
}
|
|
chan->last_btn_state = state_now;
|
|
}
|
|
|
|
void toggle_chan(void *arg)
|
|
{
|
|
sonoff_channel_t *chan = (sonoff_channel_t *)arg;
|
|
chan->state = !chan->state;
|
|
digitalWrite(chan->pin, chan->state ? HIGH : LOW);
|
|
knx.write_1bit(knx.config_get_ga(chan->status_ga_id), chan->state);
|
|
}
|
|
|
|
void channel_cb(message_t const &msg, void *arg)
|
|
{
|
|
sonoff_channel_t *chan = (sonoff_channel_t *)arg;
|
|
switch (msg.ct)
|
|
{
|
|
case KNX_CT_WRITE:
|
|
chan->state = msg.data[0];
|
|
Serial.println(chan->state ? "Toggle on" : "Toggle off");
|
|
digitalWrite(chan->pin, chan->state ? HIGH : LOW);
|
|
knx.write_1bit(knx.config_get_ga(chan->status_ga_id), chan->state);
|
|
break;
|
|
case KNX_CT_READ:
|
|
knx.answer_1bit(msg.received_on, chan->state);
|
|
}
|
|
}
|