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

How to set onPowerState and onPowerLevel on SinricPro server? #299

Closed easyyu closed 1 year ago

easyyu commented 1 year ago

Hi,

I would like to implement in code rotary encoder and to set the value from the rotary encoder as a powerLevel and the switch from the rotary encode as a powerState, and set those values to the Sinric server. Is this possible? What is the limitation? How many values I can send per minute? I tried to understand from examples but without success. How can I use functions: setManualyBrigtnessLevel and setManualyPowerLevel to interact with rotaryEncoder function? When is and how it is called function: onAdjustPowerLevel() ?

Thank you in advance for your help!

// Uncomment the following line to enable serial debug output
//#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 "SinricProDimSwitch.h"
#include <RotaryEncoder.h>
#include <map>

#define WIFI_SSID         ""    
#define WIFI_PASS         ""
#define APP_KEY           ""      // Should look like "de0bxxxx-1x3x-4x3x-ax2x-5dabxxxxxxxx"
#define APP_SECRET        ""   // Should look like "5f36xxxx-x3x7-4x3x-xexe-e86724a9xxxx-4c4axxxx-3x3x-x5xe-x9x3-333d65xxxxxx"
#define DIMSWITCH_ID      ""    // Should look like "5dc1564130xxxxxxxxxxxxxx"
#define BAUD_RATE         9600                // Change baudrate to your need

#define ledPin 13  //D7
#define device_ID_1   ""

#define PIN_IN1 D5
#define PIN_IN2 D6

int analogValue;
int lastAnalogValue;

RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::TWO03); 

// Uncomment the following line to enable serial debug output
//#define ENABLE_DEBUG

// we use a struct to store all states and values for our dimmable switch
struct {
  bool powerState = false;
  int powerLevel = 0;
} device_state;

bool onPowerState(const String &deviceId, bool &state) {
  Serial.printf("Device %s power turned %s \r\n", deviceId.c_str(), state?"on":"off");
  device_state.powerState = state;
  pinMode(ledPin, OUTPUT);
    if (state == 0){
    pinMode(ledPin, OUTPUT);
    digitalWrite (ledPin, state);
     Serial.println((String)"----------------------------------------------------------------");
   }else{
     analogWrite(ledPin, lastAnalogValue);             // set the last power level
     Serial.println((String)"----------------------------------------------------------------");
   }
  Serial.println((String)"State is: "+state+" and the power level is: "+analogValue);
  return true; // request handled properly
}

bool onPowerLevel(const String &deviceId, int &powerLevel) {
  device_state.powerLevel = powerLevel;
  analogValue = map(powerLevel, 0, 100, 0, 255); 
  Serial.printf("Device %s power level changed to %d\r\n", deviceId.c_str(), device_state.powerLevel);
  analogWrite (ledPin, analogValue);
  Serial.println((String)"analogValue is: "+analogValue);
  lastAnalogValue=analogValue;
  return true;
}

bool onAdjustPowerLevel(const String &deviceId, int &levelDelta) {
  device_state.powerLevel += levelDelta;
  Serial.printf("Device %s power level changed about %i to %d\r\n", deviceId.c_str(), levelDelta, device_state.powerLevel);
  levelDelta = device_state.powerLevel;
  return true;
}

void rotaryEncoder(){
  static int pos = 0;
  encoder.tick();

  int newPos = encoder.getPosition();
  if (pos != newPos) {
    int analogValue = map(newPos, 0, 100, 0, 255);
    Serial.print("pos:");
    Serial.print(analogValue);
    Serial.print(" dir:");
    Serial.println((int)(encoder.getDirection()));
    pos = newPos;
  } // if
// Read the current position of the encoder and print out when changed.
}

void setupWiFi() {
  Serial.printf("\r\n[Wifi]: Connecting");
  WiFi.begin(WIFI_SSID, WIFI_PASS);

  while (WiFi.status() != WL_CONNECTED) {
    Serial.printf(".");
    delay(250);
  }
  IPAddress localIP = WiFi.localIP();
  Serial.printf("connected!\r\n[WiFi]: IP-Address is %d.%d.%d.%d\r\n", localIP[0], localIP[1], localIP[2], localIP[3]);
}

void setManualyBrigtnessLevel(const String &deviceId, int &powerLevel){ //set manulay power level on Sinric server
//????????????????
//????????????????
}

void setManualyPowerLevel(const String &deviceId, int &powerLevel){ //set manulay power state on Sinric server
//????????????????
//????????????????
}

void setupSinricPro() {
  SinricProDimSwitch &myDimSwitch = SinricPro[DIMSWITCH_ID];

  // set callback function to device
  myDimSwitch.onPowerState(onPowerState);
  myDimSwitch.onPowerLevel(onPowerLevel);
  myDimSwitch.onAdjustPowerLevel(onAdjustPowerLevel);

  // setup SinricPro
  SinricPro.onConnected([](){ Serial.printf("Connected to SinricPro\r\n"); }); 
  SinricPro.onDisconnected([](){ Serial.printf("Disconnected from SinricPro\r\n"); });
  SinricPro.begin(APP_KEY, APP_SECRET);
  SinricPro.restoreDeviceStates(true);
}

// main setup function
void setup() {
  Serial.begin(BAUD_RATE); Serial.printf("\r\n\r\n");
  setupWiFi();
  setupSinricPro();
}

void loop() {
  SinricPro.handle();
  rotaryEncoder();
}
kakopappa commented 1 year ago

Hi,

for setManualyBrigtnessLevel use sendBrightnessEvent

for setManualyPowerLevel use sendPowerLevelEvent

please check the documentation for more information here

Please send the new value to the server once when there is a significant change. If you exceed the rate limit, it will print a warning in the Arduino Serial / Portal Activity Log.

easyyu commented 1 year ago

Hi, Thank you for your quick response. I know for this documentation. The problem is that I tried to implement it without success.

I do not understand how to construct the function, nor when to call it. Does it need to be in void setupSinricPro() or in the loop()? I couldn't find it on google or in your examples how to use function sendBrightnessEvent().

Can you please, help me how to modify my code to be able to set a new value on the Sinricpro server for powerState and powerLevel (brightness)?

Thank you in advance.

kakopappa commented 1 year ago
void setBrigtnessLevel(const String &deviceId, int &newPos) {
   SinricProDimSwitch &myDimSwitch = SinricPro[DIMSWITCH_ID];
   myDimSwitch.sendPowerLevelEvent(newPos);
}

void setPowerState(bool powerState) {
   SinricProDimSwitch &myDimSwitch = SinricPro[DIMSWITCH_ID];
   myDimSwitch.sendPowerStateEvent(powerState);
} 

You can call setBrigtnessLevel when the pos changed in rotaryEncoder.

easyyu commented 1 year ago

Hi,

Sorry for the delay. Thank you for your time. I tried it, and it works! Thank you for the code.

I would like to know if it is possible to get the power level value from the Sinric server. I would like to use a getBrightnessLevel(DEVICE_ID) function in one another function. The whole logic is to read the last value of brightness from a Sinric server when I use a rotary encoder switch. For example, if the brightness level is 25% (previously set with 2 clicks on the switch) what do I set with setBrigtnessLevel function, and if I do the single click (power off) how can I get the value of the brightness level from Sinric if I do the single click (that means power on)?

Can you please write me a function because I couldn't find it in the example code. Thank you in advance.

sivar2311 commented 1 year ago

I recommend saving the current brightness value in a global variable. This way you can access the value at any time.

To get the last known brightness value (from the server) at start-up you can use the function SinricPro.restoreDeviceStates(true); (see Documentation)

easyyu commented 1 year ago

Hi,

Thx for your answer. Yes, I know for SinricPro.restoreDeviceStates(true);, but I thought there is a possibility to have even a value from getBrightnessLevel() function.. As I realized this function is void and doesn't return any value, therefore I can not set any variable with data. Correct?

sivar2311 commented 1 year ago

Correct, there is no getBrightnessLevel function inside the SDK. The SinricPro devices are stateless. The states (e.g. ) brightness level must be managed by your Sketch. The easiest way to do this is to use a global variable.

If you use SinricPro.restoreDeviceStates(true);, the respective callback function is called directly after establishing the connection to the SinricPro server with the last known value. In this way you receive the last known value.

stale[bot] commented 1 year ago

Hey again! It’s been 14 days since anything happened on this issue, so our friendly robot (that’s me!) is going to close it. Please keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m HUMAN_EMOTION_SORRY. Please feel free to comment on this issue or create a new one if you need anything else. As a friendly reminder, the best way to fix this or any other problem is to provide a detailed error description including a serial log. Thanks again for being a part of the SinricPro community!