sonoff.ino 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #include <esp-knx-ip.h>
  2. // WiFi config here
  3. const char* ssid = "ssid";
  4. const char* pass = "pass";
  5. // Common
  6. #define LED_PIN 13
  7. // For Basic and S20
  8. #define BTN1_PIN 0
  9. #define CH1_PIN 12
  10. // For 4CH
  11. #define BTN2_PIN 9
  12. #define CH2_PIN 5
  13. #define BTN3_PIN 10
  14. #define CH3_PIN 4
  15. #define BTN4_PIN 14
  16. #define CH4_PIN 15
  17. typedef enum __type_option
  18. {
  19. SONOFF_TYPE_NONE = 0,
  20. SONOFF_TYPE_BASIC = 1,
  21. SONOFF_TYPE_S20 = 2,
  22. SONOFF_TYPE_4CH = 3,
  23. SONOFF_TYPE_4CH_PRO = 4,
  24. } type_option_t;
  25. option_entry_t type_options[] = {
  26. {"Sonoff Basic", SONOFF_TYPE_BASIC},
  27. {"Sonoff S20", SONOFF_TYPE_S20},
  28. {"Sonoff 4CH", SONOFF_TYPE_4CH},
  29. {"Sonoff 4CH Pro", SONOFF_TYPE_4CH_PRO},
  30. {nullptr, 0}
  31. };
  32. config_id_t hostname_id;
  33. config_id_t type_id;
  34. typedef struct __sonoff_channel
  35. {
  36. int pin;
  37. int btn_pin;
  38. config_id_t status_ga_id;
  39. bool state;
  40. bool last_btn_state;
  41. } sonoff_channel_t;
  42. sonoff_channel_t channels[] = {
  43. {CH1_PIN, BTN1_PIN, 0, false, false},
  44. {CH2_PIN, BTN2_PIN, 0, false, false},
  45. {CH3_PIN, BTN3_PIN, 0, false, false},
  46. {CH4_PIN, BTN4_PIN, 0, false, false},
  47. };
  48. void setup()
  49. {
  50. pinMode(LED_PIN, OUTPUT);
  51. pinMode(BTN1_PIN, INPUT_PULLUP);
  52. pinMode(BTN2_PIN, INPUT_PULLUP);
  53. pinMode(BTN3_PIN, INPUT_PULLUP);
  54. pinMode(BTN4_PIN, INPUT_PULLUP);
  55. pinMode(CH1_PIN, OUTPUT);
  56. pinMode(CH2_PIN, OUTPUT);
  57. pinMode(CH3_PIN, OUTPUT);
  58. pinMode(CH4_PIN, OUTPUT);
  59. Serial.begin(115200);
  60. // Register the config options
  61. hostname_id = knx.config_register_string("Hostname", 20, String("sonoff"));
  62. type_id = knx.config_register_options("Type", type_options, SONOFF_TYPE_BASIC);
  63. channels[0].status_ga_id = knx.config_register_ga("Channel 1 Status GA");
  64. channels[1].status_ga_id = knx.config_register_ga("Channel 2 Status GA", is_4ch_or_4ch_pro);
  65. channels[2].status_ga_id = knx.config_register_ga("Channel 3 Status GA", is_4ch_or_4ch_pro);
  66. channels[3].status_ga_id = knx.config_register_ga("Channel 4 Status GA", is_4ch_or_4ch_pro);
  67. knx.callback_register("Channel 1", channel_cb, &channels[0]);
  68. knx.callback_register("Channel 2", channel_cb, &channels[1], is_4ch_or_4ch_pro);
  69. knx.callback_register("Channel 3", channel_cb, &channels[2], is_4ch_or_4ch_pro);
  70. knx.callback_register("Channel 4", channel_cb, &channels[3], is_4ch_or_4ch_pro);
  71. knx.feedback_register_bool("Channel 1 is on", &(channels[0].state));
  72. knx.feedback_register_action("Toogle channel 1", toggle_chan, &channels[0]);
  73. knx.feedback_register_bool("Channel 2 is on", &(channels[1].state), is_4ch_or_4ch_pro);
  74. knx.feedback_register_action("Toogle channel 2", toggle_chan, &channels[1], is_4ch_or_4ch_pro);
  75. knx.feedback_register_bool("Channel 3 is on", &(channels[2].state), is_4ch_or_4ch_pro);
  76. knx.feedback_register_action("Toogle channel 3", toggle_chan, &channels[2], is_4ch_or_4ch_pro);
  77. knx.feedback_register_bool("Channel 4 is on", &(channels[3].state), is_4ch_or_4ch_pro);
  78. knx.feedback_register_action("Toogle channel 4", toggle_chan, &channels[3], is_4ch_or_4ch_pro);
  79. knx.load();
  80. // Init WiFi
  81. WiFi.hostname(knx.config_get_string(hostname_id));
  82. WiFi.begin(ssid, pass);
  83. Serial.println("");
  84. Serial.print("[Connecting]");
  85. Serial.print(ssid);
  86. digitalWrite(LED_PIN, LOW);
  87. while (WiFi.status() != WL_CONNECTED) {
  88. digitalWrite(LED_PIN, HIGH);
  89. delay(500);
  90. Serial.print(".");
  91. digitalWrite(LED_PIN, LOW);
  92. }
  93. digitalWrite(LED_PIN, HIGH);
  94. // Start knx
  95. knx.start();
  96. Serial.println();
  97. Serial.println("Connected to wifi");
  98. Serial.println(WiFi.localIP());
  99. }
  100. void loop()
  101. {
  102. knx.loop();
  103. // Check local buttons
  104. check_button(&channels[0]);
  105. if (is_4ch_or_4ch_pro())
  106. {
  107. check_button(&channels[1]);
  108. check_button(&channels[2]);
  109. check_button(&channels[3]);
  110. }
  111. delay(50);
  112. }
  113. bool is_basic_or_s20()
  114. {
  115. uint8_t type = knx.config_get_options(type_id);
  116. return type == SONOFF_TYPE_BASIC || type == SONOFF_TYPE_S20;
  117. }
  118. bool is_4ch_or_4ch_pro()
  119. {
  120. uint8_t type = knx.config_get_options(type_id);
  121. return type == SONOFF_TYPE_4CH ||type == SONOFF_TYPE_4CH_PRO;
  122. }
  123. void check_button(sonoff_channel_t *chan)
  124. {
  125. bool state_now = digitalRead(chan->btn_pin) == HIGH ? true : false;
  126. if (state_now != chan->last_btn_state && state_now == LOW)
  127. {
  128. chan->state = !chan->state;
  129. digitalWrite(chan->pin, chan->state ? HIGH : LOW);
  130. knx.write_1bit(knx.config_get_ga(chan->status_ga_id), chan->state);
  131. }
  132. chan->last_btn_state = state_now;
  133. }
  134. void toggle_chan(void *arg)
  135. {
  136. sonoff_channel_t *chan = (sonoff_channel_t *)arg;
  137. chan->state = !chan->state;
  138. digitalWrite(chan->pin, chan->state ? HIGH : LOW);
  139. knx.write_1bit(knx.config_get_ga(chan->status_ga_id), chan->state);
  140. }
  141. void channel_cb(message_t const &msg, void *arg)
  142. {
  143. sonoff_channel_t *chan = (sonoff_channel_t *)arg;
  144. switch (msg.ct)
  145. {
  146. case KNX_CT_WRITE:
  147. chan->state = msg.data[0];
  148. Serial.println(chan->state ? "Toggle on" : "Toggle off");
  149. digitalWrite(chan->pin, chan->state ? HIGH : LOW);
  150. knx.write_1bit(knx.config_get_ga(chan->status_ga_id), chan->state);
  151. break;
  152. case KNX_CT_READ:
  153. knx.answer_1bit(msg.received_on, chan->state);
  154. }
  155. }