/*
  Copyright (C) AC SOFTWARE SP. Z O.O.

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

/**
 * @supla-example
 * @file RollerShutter_595_166_io.ino
 * @brief Example of controlling a roller shutter with 74HC595 (outputs) and 74HC166 (inputs) shift registers on an Arduino Mega for SUPLA integration.
 * This example demonstrates an advanced setup for controlling a roller shutter. It utilizes 74HC595 shift registers
 * to expand output capabilities for motor control (via relays) and status LEDs, and 74HC166 shift registers
 * for reading multiple button inputs (open, close). The system is integrated with the SUPLA cloud
 * via an Ethernet shield (W5100 or ENC28J60) and stores roller shutter data persistently in EEPROM (or optionally FRAM).
 * Users need to adjust network settings, SUPLA GUID, AUTHKEY, and GPIO pins for the shift registers, buttons, and relays in the code.
 *
 * @tags roller_shutter, 74HC595, 74HC166, shift_register, output_expander, input_expander, button, relay, arduino_mega, ethernet, w5100, enc28j60, EEPROM, FRAM
 */

#define NUMBER_OF_SR595 \
  4  // number of shift registers eg 4 x 74HC595 = 32 outputs  pin 0 - 31
#define DATA_SR595_GPIO  14  // data pin 14 on 74HC595
#define CLOCK_SR595_GPIO 13  // clock pin 11 on 74HC595
#define LATCH_SR595_GPIO 12  // latch pin 12 on 74HC595

#define NUMBER_OF_SR166 \
  4  // number of shift registers eg 4 x 74HC166 = 32 intputs  pin 0 - 31
#define DATA_SR166_GPIO  4  // data pin 13 on 74HC166
#define CLOCK_SR166_GPIO 5  // clock pin 2 on 74HC166
#define LOAD_SR166_GPIO  0  // load pin 1 on 74HC166

#include <SuplaDevice.h>
#include <supla/control/EXT_SR166.h>
#include <supla/control/EXT_SR595.h>
#include <supla/control/button.h>
#include <supla/control/pin_status_led.h>
#include <supla/control/relay.h>
#include <supla/control/roller_shutter.h>

// Choose where Supla should store roller shutter data in persistant memory
// We recommend to use external FRAM memory
#define STORAGE_OFFSET 100
#include <supla/storage/eeprom.h>
Supla::Eeprom eeprom(STORAGE_OFFSET);
// #include <supla/storage/fram_spi.h>
// Supla::FramSpi fram(STORAGE_OFFSET);

// Choose proper network interface for your card:
// Arduino Mega with EthernetShield W5100:
#include <supla/network/ethernet_shield.h>
// Ethernet MAC address
uint8_t mac[6] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
Supla::EthernetShield ethernet(mac);

// Arduino Mega with ENC28J60:
// #include <supla/network/ENC28J60.h>
// Supla::ENC28J60 ethernet(mac);

void setup() {
  Serial.begin(115200);

  // Replace the falowing GUID with value that you can retrieve from
  // https://www.supla.org/arduino/get-guid
  char GUID[SUPLA_GUID_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

  // Replace the following AUTHKEY with value that you can retrieve from:
  // https://www.supla.org/arduino/get-authkey
  char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                      0x00, 0x00};

  /*
     Having your device already registered at cloud.supla.org,
     you want to change CHANNEL sequence or remove any of them,
     then you must also remove the device itself from cloud.supla.org.
     Otherwise you will get "Channel conflict!" error.
  */

  auto ExtSr595 = new Supla::Control::ExtSR595(
      NUMBER_OF_SR595, DATA_SR595_GPIO, CLOCK_SR595_GPIO, LATCH_SR595_GPIO);
  auto ExtSr166 = new Supla::Control::ExtSR166(
      NUMBER_OF_SR166, DATA_SR166_GPIO, CLOCK_SR166_GPIO, LOAD_SR166_GPIO);

  auto r1 = new Supla::Control::Relay(ExtSr595, 0, true);
  auto r2 = new Supla::Control::Relay(ExtSr595, 14, false);
  auto r3 = new Supla::Control::Relay(ExtSr595, 27, true);

  Supla::Control::RollerShutter *rs = new Supla::Control::RollerShutter(
      ExtSr595, 3, 4, true);  // Q3 and Q4 from first 74HC595

  Supla::Control::Button *buttonOpen = new Supla::Control::Button(ExtSr166, 4);
  Supla::Control::Button *buttonClose = new Supla::Control::Button(ExtSr166, 5);

  // Add two LEDs to inform about roller shutter relay status
  // If inverted value is required, please add parameter with true value
  new Supla::Control::PinStatusLed(
      NULL,
      ExtSr595,
      15,
      30,
      true);  // gpio 15 on ESP status to be informed on pin 30 of 74HC595
  new Supla::Control::PinStatusLed(
      ExtSr595,
      ExtSr595,
      4,
      31,
      true);  // pin 4 on 74HC595 status to be informed on pin 31 of 74HC595

  buttonOpen->addAction(Supla::OPEN_OR_STOP, *rs, Supla::ON_PRESS);
  buttonClose->addAction(Supla::CLOSE_OR_STOP, *rs, Supla::ON_PRESS);

  /*
     SuplaDevice Initialization.
     Server address is available at https://cloud.supla.org
     If you do not have an account, you can create it at
     https://cloud.supla.org/account/create SUPLA and SUPLA CLOUD are free of
     charge

  */

  SuplaDevice.begin(
      GUID,              // Global Unique Identifier
      "svr1.supla.org",  // SUPLA server address
      "email@address",   // Email address used to login to Supla Cloud
      AUTHKEY);          // Authorization key
}

void loop() {
  SuplaDevice.iterate();
}
