#define BLYNK_PRINT Serial
#define BLYNK_TEMPLATE_ID "TMPL3XvWT_aYr"
#define BLYNK_TEMPLATE_NAME "poject3"
#define BLYNK_AUTH_TOKEN "XYKIFdIPp4HCQCBr3t2amJ2RTJcUc58A"

#include <WiFi.h>              // Pustaka untuk koneksi Wi-Fi pada ESP32
#include <BlynkSimpleEsp32.h>   // Pustaka Blynk untuk ESP32
#include <ShiftRegister74HC595.h>  // Pustaka Shift Register 74HC595



// Pin konfigurasi untuk shift register
const int dataPin = 16;     // Pin untuk Data (DS) pada 74HC595
const int clockPin = 18;    // Pin untuk Clock (SH_CP) pada 74HC595
const int latchPin = 17;     // Pin untuk Latch (ST_CP) pada 74HC595

// Shift Register (mengontrol 2 shift register, 16 output)
const int numberOfShiftRegisters = 2;  // Kita menggunakan 2 shift register
ShiftRegister74HC595<2> sr(dataPin, clockPin, latchPin);  // Inisialisasi shift register dengan pin

// Menyimpan status LED dalam 2 byte (karena ada 16 LED, masing-masing LED 1 bit)
byte ledStatus[2] = {0, 0};  // Status LED disimpan dalam 2 byte untuk 16 LED

// Koneksi ke WiFi
char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "Wokwi-GUEST";
char pass[] = "";

// Setup virtual pin untuk setiap LED
// Misalkan kita menggunakan V0 hingga V15 untuk kontrol 16 LED
BLYNK_WRITE(V0) { setLED(0, param.asInt()); }
BLYNK_WRITE(V1) { setLED(1, param.asInt()); }
BLYNK_WRITE(V2) { setLED(2, param.asInt()); }
BLYNK_WRITE(V3) { setLED(3, param.asInt()); }
BLYNK_WRITE(V4) { setLED(4, param.asInt()); }
BLYNK_WRITE(V5) { setLED(5, param.asInt()); }
BLYNK_WRITE(V6) { setLED(6, param.asInt()); }
BLYNK_WRITE(V7) { setLED(7, param.asInt()); }
BLYNK_WRITE(V8) { setLED(8, param.asInt()); }
BLYNK_WRITE(V9) { setLED(9, param.asInt()); }
BLYNK_WRITE(V10) { setLED(10, param.asInt()); }
BLYNK_WRITE(V11) { setLED(11, param.asInt()); }
BLYNK_WRITE(V12) { setLED(12, param.asInt()); }
BLYNK_WRITE(V13) { setLED(13, param.asInt()); }
BLYNK_WRITE(V14) { setLED(14, param.asInt()); }
BLYNK_WRITE(V15) { setLED(15, param.asInt()); }

// Fungsi untuk mengatur LED sesuai input dari aplikasi Blynk
void setLED(int ledNumber, int state) {
  if (ledNumber >= 0 && ledNumber < 16) {  // Pastikan LED ada dalam jangkauan 0-15
    int byteIndex = ledNumber / 8;   // Tentukan byte mana yang harus diakses
    int bitIndex = ledNumber % 8;    // Tentukan bit mana dalam byte tersebut

    if (state == 1) {
      bitSet(ledStatus[byteIndex], bitIndex);  // Nyalakan LED
    } else {
      bitClear(ledStatus[byteIndex], bitIndex);  // Matikan LED
    }
    updateShiftRegister();
  }
}

// Fungsi untuk memperbarui status shift register
void updateShiftRegister() {
  for (int i = 0; i < 16; i++) {
    int byteIndex = i / 8;   // Tentukan byte mana yang harus diakses
    int bitIndex = i % 8;    // Tentukan bit mana dalam byte tersebut

    int state = bitRead(ledStatus[byteIndex], bitIndex);  // Baca status LED
    sr.set(i, state);  // Atur status pada shift register
  }
}

void setup() {
  // Inisialisasi Serial untuk debugging
  Serial.begin(115200);
  
  // Inisialisasi Blynk
 Blynk.begin(auth, ssid, pass, "iot.serangkota.go.id", 8080);
  
  // Set semua LED ke kondisi mati
  sr.setAllLow();
}

void loop() {
  Blynk.run();  // Jalankan fungsi Blynk
}
74HC595
74HC595