sinricpro / esp8266-esp32-sdk

Library for https://sinric.pro - simple way to connect your device to Alexa, Google Home, SmartThings and cloud
https://sinric.pro
228 stars 121 forks source link

Sinric Pro Custom Devices are really works with Alexa Voice Assistance? #250

Closed techvishalsingh closed 2 years ago

techvishalsingh commented 2 years ago

Hello There.

I have a Question about Sinric Pro Custom Devices Alexa Voice Assistance features,

Currently I am working on Automatic Curtains Project, and I create custom Template for it, and i am so glad and thankful to Sinric pro who's provide us such a great platform for custom devices.

But i am facing voice command related issues

everything working fine Sinric pro app, alexa app (Finding my device) create mode for it and my device working to good,

but actual problem are coming in voice command. is not working with voice Alexa Keep reply me device name not supported , or i don't know how to set device name setting.

So anyone can help me related to this Issus

some important details about this Project are giving below down,,,, Room- Bedroom, Device Name- Curtains / types others Mode name- Curtains Motor value- 1. Open

  1. Close
kakopappa commented 2 years ago

What's the voice command you have an issue with?

Usually, to set the mode, Eg: Alexa, set the Curtains [device name] to open [mode name].

why not use the built-in Blinds type? If you use Built-in type: Alexa, open the Curtains. Alexa, close the Curtains.

techvishalsingh commented 2 years ago

@kakopappa hello sir great to see you, and very thankful for your fast reply.

actually i try Eg: Alexa, set the Curtains [device name] to open [mode name]. this but after i got reply device name not supported , or i don't know how to set device name setting. from alexa.

second is related to blind example, i don't know, how to write or fit my coding part in blind example.

sivar2311 commented 2 years ago

Hi @techvishalsingh I recommend to use the blinds example, because this is based on predefined blinds device with utterances provided directly by alexa.

Basically your blinds sketch needs to handle the onRangeValue callback. The callback will be called with the parameter position of type int. The value will be between 0 to 100 (where 0 is closed and 100 is completely open, if I remember correctly).

Supported utterances: "Alexa, set the living room blinds to 20" (positon value is 20) "Alexa, open the bedroom blinds." (positon value is 100) "Alexa, close the bedroom blinds." (position value is 0)

Your callback only has to process values between 0 and 100 and decide what to do at which value.

techvishalsingh commented 2 years ago

Hey @sivar2311 great to see you too,

Yes you are wright, but problem is my mechanism off device,

I am using 12v dc motor and this moter rotate anti clockwise and counter clockwise with high and low pin configuration , so if i want to control my motor speed then your idea is good

But problem is in my mechanism of device I am trying something new

sivar2311 commented 2 years ago

The value is not related directly to your motorcontrol. It just tells you the desired position. The motor should be handled outside the callback with it's own logic. I am busy at the momment, but i think i will be back in 1 or 2 hours.

techvishalsingh commented 2 years ago
`
#define ENABLE_DEBUG

#ifdef ENABLE_DEBUG
  #define DEBUG_ESP_PORT Serial
  #define NODEBUG_WEBSOCKETS
  #define NDEBUG
#endif

#include <Arduino.h>
#ifdef ESP8266
  #include <ESP8266WiFi.h>
#endif
#ifdef ESP32
  #include <WiFi.h>
#endif

#include <SinricPro.h>
#include "AutoCurtains.h"

#define APP_KEY    ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
#define APP_SECRET ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
#define DEVICE_ID  ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"

#define SSID       ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
#define PASS       ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"

#define BAUD_RATE  9600

AutoCurtains &autoCurtains = SinricPro[DEVICE_ID];

int in1 = 18;
int in2 = 19;

std::map<String, String> globalModes;

// ModeController
bool onSetMode(const String& deviceId, const String& instance, String &mode) {
  Serial.printf("[Device: %s]: Modesetting for \"%s\" set to mode %s\r\n", deviceId.c_str(), instance.c_str(), mode.c_str());
  globalModes[instance] = mode;
   if (mode == "Open") {
    digitalWrite(in1, HIGH); digitalWrite(in2, LOW); delay(1500); digitalWrite(in1, LOW); digitalWrite(in2, LOW);  
  }

 if (mode == "Close") {
    digitalWrite(in1, LOW); digitalWrite(in2, HIGH); delay(1500); digitalWrite(in1, LOW); digitalWrite(in2, LOW);
  }

  if (mode == "Stop") {
   digitalWrite(in1, LOW); digitalWrite(in2, LOW);
  }
  return true;
}

// ModeController
void updateMode(String instance, String mode) {
  autoCurtains.sendModeEvent(instance, mode, "PHYSICAL_INTERACTION");
}

void setupSinricPro() {

  // ModeController
  autoCurtains.onSetMode("modeInstance1", onSetMode);

  SinricPro.onConnected([]{ Serial.printf("[SinricPro]: Connected\r\n"); });
  SinricPro.onDisconnected([]{ Serial.printf("[SinricPro]: Disconnected\r\n"); });
  SinricPro.begin(APP_KEY, APP_SECRET);
};

void setupWiFi() {
  WiFi.begin(SSID, PASS);
  Serial.printf("[WiFi]: Connecting to %s", SSID);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.printf(".");
    delay(250);
  }
  Serial.printf("connected\r\n");
}

void setup() {
  Serial.begin(BAUD_RATE);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);

  // Turn off motors - Initial state
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  setupWiFi();
  setupSinricPro();
}

void loop() {
  SinricPro.handle();
}`
techvishalsingh commented 2 years ago
#ifndef _AUTOCURTAINS_H_
#define _AUTOCURTAINS_H_

#include <SinricProDevice.h>
#include <Capabilities/ModeController.h>

class AutoCurtains 
: public SinricProDevice
, public ModeController<AutoCurtains> {
  friend class ModeController<AutoCurtains>;
public:
  AutoCurtains(const String &deviceId) : SinricProDevice(deviceId, "AutoCurtains") {};
};

#endif
sivar2311 commented 2 years ago

Can you explain the motor control more detailed, please? From your code i see it takes 1,5 seconds to open completely and also 1,5 seconds to close completely. Is this correct?

Edit: Maybe this is just a 1,5 seconds pulse to start the open / close process and it stops automatically when it is fully opened / closed?

techvishalsingh commented 2 years ago

Good Morning Boris,

Ok, I let you describe more about My Project mechanism

So I am using 12v dc motor and it controlled by L298n motor driver Module which have IN1 and IN2, in my case motor move Forward and backsword,

Motor moving condition is totally depend on IN1 & IN2 Pin (L298N) HIGH and LOW Signals

clockwise moving candition of motor // opwn digitalWrite(in1, HIGH); digitalWrite(in2, LOW); delay(1500); // After 1.5 sec motor will stop digitalWrite(in1, LOW); // when both in1 and in2 get low singnal motor stop digitalWrite(in2, LOW); //

anticlockwise moving candition of motor // colse digitalWrite(in1, LOW); digitalWrite(in2, HIGH); delay(1500); // After 1.5 sec motor will stop digitalWrite(in1, LOW); // when both in1 and in2 get low singnal motor stop digitalWrite(in2, LOW); //

For More details: please chq it this blog i hope you will understand whole thing https://lastminuteengineers.com/l298n-dc-stepper-driver-arduino-tutorial/

sivar2311 commented 2 years ago

Good morning :) Thanks for explenations!

So, the duration (currently fixed to 1,5 seconds) tells, where the blinds have to stop, right? Can you measure the maximum time from fully closed to fully open?

techvishalsingh commented 2 years ago

yes duration is fix and dont forget blind and curtains both are deferent ### mechanisms

sivar2311 commented 2 years ago

Please forget about SinricPro implementation for a momment (blinds, curtains, mode, range etc.)

For your project, you must know the duration, right? I am working on a sketch for you, that's why i am asking

techvishalsingh commented 2 years ago

2sec for opening its means move forwards same for closing

sivar2311 commented 2 years ago

yes. how long does your curtains need to move from closed position to fully open position?

techvishalsingh commented 2 years ago

same 2 sec

sivar2311 commented 2 years ago

Oh, that's very fast for a curtain. So, there is only fully open and fully close position? Nothing in between like 50% open or so?

techvishalsingh commented 2 years ago

yehhhhhhhhhhhhhh you got my point

techvishalsingh commented 2 years ago

i just want fully open and fully close

techvishalsingh commented 2 years ago

but i like your concept like only 50% open

sivar2311 commented 2 years ago

So 50% open would be duration of 1 second (50% of 2 seconds), right?

Security question: Do you have some feedback sensors that tells you when the curatain is open or close? Imagine the curatin is in closed position and you ask alexa to close the curtain...to motor will start (trying to close the curtains even further)

techvishalsingh commented 2 years ago

right now i don't have sensor for this feature but i will hard for make solution for live feedback (curtains are open or close)

techvishalsingh commented 2 years ago

i am planning for it i think a ir proximity sensor will help me

sivar2311 commented 2 years ago

Ok, so the sketch must take into account the current position so that the motor does not turn too far.

techvishalsingh commented 2 years ago

yes you are right.

sivar2311 commented 2 years ago

Thanks for answering my questions. Now i have a better view on your project.

Ok, i am working on a sketch (using SinricProBlinds device) in backround and let you know when i am finish.

techvishalsingh commented 2 years ago

Ok, Thankyou so much for it, i hope this problem not will longer. wishing you all the best for it.

https://lastminuteengineers.com/l298n-dc-stepper-driver-arduino-tutorial/

this link just for reference

sivar2311 commented 2 years ago

While implementing i found a bug inside the SDK :grimacing: I will fix this issue and update the SDK to Version 2.9.16

sivar2311 commented 2 years ago

Here is the implementation using SinricProBlinds device.

Supported utterances "Alexa, open devicename." "Alexa, close devicename." "Alexa, set devicename to x percent." "Alexa, open devicename by x percent." (relative percentage - see note below!) "Alexa, close devicename by x percent." (relative percentage - see note below!)

Note: Due to a bug, SDK version 2.9.16 is required!

Sketch-Notes:

#include <Arduino.h>
#include <WiFi.h>
#include <SinricPro.h>
#include <SinricProBlinds.h>

#define WIFI_SSID "YOUR_WIFI_SSID"
#define WIFI_PASS "YOUR_WIFI_PASS"

#define APP_KEY    "YOUR_APPKEY"
#define APP_SECRET "YOUR_APPSECRET"

#define DEVICE_ID "YOUR_DEVICEID"

#define MOTOR_GPIO1 18
#define MOTOR_GPIO2 19

// time to move from closed position to fully open position (and vice versa)
#define MAXIMUM_DURATION 2000 

// current position in percent. assume curtains are in closed position at boot
int current_position = 0; 

// MOTOR IMPLEMENTATION

unsigned long motor_move_duration = 0;

/**
 * Start moving the motor and set the duration time
 * 
 * direction: true = MOTOR_GPIO1 HIGH, MOTOR_GPIO2 LOW
 * direction: false = MOTOR_GPIO1 LOW, MOTOR_GPIO2 HIGH
 * 
 * duration: duration in milliseconds how long the motor should run
 */
void startMotor(bool direction, int duration) {
  digitalWrite(MOTOR_GPIO1, direction); 
  digitalWrite(MOTOR_GPIO2, !direction);
  motor_move_duration = millis() + duration;
}

// Stop moving the motor and set duration time to 0
void stopMotor() {
  digitalWrite(MOTOR_GPIO1, LOW);
  digitalWrite(MOTOR_GPIO2, LOW);
  motor_move_duration = 0;
}

// check's the duration and stop if duration is reached
// must be called in loop()
void handleMotor() {
  if (motor_move_duration && millis() < motor_move_duration) return;
  stopMotor();
}

// calculates the duration to reach the new position
// new_position: percentage value 0..100
// return: duration in milliseconds
unsigned long calculate_duration(int new_position) {
  if (new_position == 0) return (MAXIMUM_DURATION / 100 * current_position);

  // calculate the difference
  int difference = new_position > current_position ? new_position - current_position : current_position - new_position; 

  // difference (in percent) to milliseconds
  unsigned long duration = MAXIMUM_DURATION / 100 * difference; 
  return duration; 
}

// calculates the direction to reach the new position
// new_position: percentage value 0..100
// return: true when move in direction of OPEN position
// return: false when move in direction of CLOSE position
bool calculate_direction(int new_position) {
  return new_position > current_position;
}

// SINRICPRO IMPLEMENTATION

SinricProBlinds& myBlinds = SinricPro[DEVICE_ID];

bool onRangeValue(const String &deviceId, int &new_position) {
  if (new_position == current_position) return true;

  bool direction = calculate_direction(new_position);
  int duration = calculate_duration(new_position);

  startMotor(direction, duration);
  current_position = new_position;

  return true; 
}

bool onAdjustRangeValue(const String &deviceId, int &relative_position) {
  int new_position = current_position + relative_position;

  // Ensure that the new position does not "overshoot the mark".
  if (new_position > 100) new_position = 100;
  if (new_position < 0) new_position = 0;

  bool direction = calculate_direction(new_position);
  int duration = calculate_duration(new_position);

  startMotor(direction, duration);

  relative_position = new_position; // this returns the return new position to SinricPro server
  current_position = new_position;
  return true; 
}

bool onPowerState(const String &deviceId, bool &state) {
  return true; 
}

void setup() {
  pinMode(MOTOR_GPIO1, OUTPUT);
  pinMode(MOTOR_GPIO2, OUTPUT);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  myBlinds.onPowerState(onPowerState);
  myBlinds.onRangeValue(onRangeValue);
  myBlinds.onAdjustRangeValue(onAdjustRangeValue);
  SinricPro.begin(APP_KEY, APP_SECRET);
}

void loop() {
  SinricPro.handle();
  handleMotor();
}
techvishalsingh commented 2 years ago

Thanks Boris, for now my all necessary project needs is fulfilling.

And I thank @sivar2311 @kakopappa also whole Sinric pro team,
We always said Sinric Pro is the one of best Iot Implement platform providers

sivar2311 commented 2 years ago

Thanks @techvishalsingh for the kind words :) It would be nice if you could show a video or pictures of your device at work :)

techvishalsingh commented 2 years ago

Sure, but whare i post my video or send to you

sivar2311 commented 2 years ago

You can drag & drop the video / pictures directly in the comment field.

techvishalsingh commented 2 years ago

I really feel very sorry about my late reply , I was working on my mechanical setup of curtains project.

Unfortunately project failed. Just because of my dc motor, it have high RPM and low torque , that's why after applying load it not move, so I decided to make some mechanism changes in my project at this time I will use low RPM and high torque moter or stepper motor.

sivar2311 commented 2 years ago

Hi @techvishalsingh !

I think using a stepper motor is a good idea. Because you're independent on timings (how long it takes to open / close the curtain). Instead you can use the precisely stepping counts. In #208 i posted 2 example codes how a stepper motor can be handled. Please see the 2nd example (you have to click to expand the source code). This example explains how to write a non-blocking stepper motor control. Basically it's similar to the code you use, but using step counts instead of timing.

techvishalsingh commented 2 years ago

Hello @sivar2311 yes you are right stepper motor is good idea, first i will do work on my mechanism of curtains project then get back to you

One again thanks from my bottom of heart you are still here for my help let's make some changes in my mechanism them get back to you as soon as possible