#include <Arduino.h>
#include <WiFi.h>
#include <ESP_FlexyStepper.h> // https://github.com/pkerspe/ESP-FlexyStepper
#include <SinricPro.h>        // https://github.com/sinricpro/esp8266-esp32-sdk
#include <SinricProBlinds.h>  // https://github.com/sinricpro/esp8266-esp32-sdk

// *********** BEGIN OF CONFIGURATION ************ //
const int MOTOR_DIRECTION_PIN = 16;
const int MOTOR_STEP_PIN = 17;

const int LIMIT_SWITCH_PIN = 26;

const int MIN_POS_MM = 0;
const int MAX_POS_MM = 1000;

const int SPEED_MM_PER_SECOND = 10;
const int ACCEL_MM_PER_SECOND = 10;
const int STEPS_PER_MM = 1;

const char* WIFI_SSID = "Wokwi-GUEST";
const char* WIFI_PASS = "";

const char* BLINDS_ID = "";
const char* APP_KEY = "";
const char* APP_SECRET = "";

// ************ END OF CONFIGURATION ************* //

ESP_FlexyStepper stepper;
SinricProBlinds& blinds = SinricPro[BLINDS_ID];

volatile bool limitSwitchTriggered = false;

void ICACHE_RAM_ATTR limitSwitchHandler() {
  limitSwitchTriggered = true;
}

void MoveBlinds(const int percentage) {
  int destination_in_mm = map(percentage, 0, 100, MIN_POS_MM, MAX_POS_MM);
  stepper.setTargetPositionInMillimeters(destination_in_mm);
}

void handleLimitSwitches() {
  if (!limitSwitchTriggered) return;
  stepper.emergencyStop();
  limitSwitchTriggered = false;
}

void handleMotor() {
  handleLimitSwitches();
  stepper.processMovement();
}

void setupWiFi() {
  Serial.println("Connecting WiFi");
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(100);
  }
  Serial.println("connected!");
}

void setupSinricPro() {
  blinds.onRangeValue([](const String& deviceId, int& position) {
    Serial.print("Moving blinds to ");
    Serial.println(position);
    MoveBlinds(position);
    return true;
  });

  blinds.onPowerState([](const String& deviceId, bool & state) {
    Serial.print("Blinds turned ");
    Serial.println(state ? "On" : "Off");
    return true;
  });

  SinricPro.onConnected([]() {
    Serial.println("SirnicPro connected!");
  });
  SinricPro.onDisconnected([]() {
    Serial.println("SirnicPro disconnected!");
  });

  Serial.println("Connecting to SinricPro. Please wait...");
  SinricPro.begin(APP_KEY, APP_SECRET);
}

void setupStepper() {
  stepper.connectToPins(MOTOR_STEP_PIN, MOTOR_DIRECTION_PIN);
  stepper.setSpeedInMillimetersPerSecond(SPEED_MM_PER_SECOND);
  stepper.setAccelerationInMillimetersPerSecondPerSecond(ACCEL_MM_PER_SECOND);
  stepper.setStepsPerMillimeter(STEPS_PER_MM);
}

void setupLimitSwitch() {
  pinMode(LIMIT_SWITCH_PIN, INPUT_PULLUP);
  attachInterrupt(LIMIT_SWITCH_PIN, limitSwitchHandler, FALLING);
}

void setup() {
  Serial.begin(115200);
  setupWiFi();
  setupSinricPro();
  setupLimitSwitch();
  setupStepper();
}


void loop() {
  handleMotor();
  SinricPro.handle();
  delay(1); // Wokwi delay - not needed in production!
}
A4988