Why do we need this library
Many of us are using SinricPro SDK, which is so far written only for ESP8266/ESP32 boards, to connect to Alexa via SinricPro skills.
This SinricPro_Generic SDK library is based on and modified from SinricPro SDK to provide support to many boards such as Arduino SAMD21, Adafruit SAMD21/SAMD51, nRF52, Teensy, SAM DUE, STM32, etc. and enable those boards to use SinricPro services, including voice-control Alexa along with Blynk. The SinricPro_Generic SDK library can be used with ESPβs WiFi, WiFiNINA, W5x00 and ENC28J60 Ethernet.
Releases v2.4.0
- Add support to :
- Arduino SAMD21 (ZERO, MKR, NANO_33_IOT, M0, M0 Pro, AdaFruit CIRCUITPLAYGROUND_EXPRESS, etc.).
- Adafruit SAM21 (Itsy-Bitsy M0, Metro M0, Feather M0, Gemma M0, etc.).
- Adafruit SAM51 (Itsy-Bitsy M4, Metro M4, Grand Central M4, Feather M4 Express, etc.).
- AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc..
- Teensy 4.1, 4.0, 3.6, 3.5, 3.2/3.1, 3.0.
- STM32 (Nucleo-144, Nucleo-64, Nucleo-32, Discovery, STM32F1, STM32F3, STM32F4, STM32H7, STM32L0, etc.).
- SAM DUE
For more information, please have a look at
- SinricPro
- SinricPro Documentation
- SinricPro API Documentation
- How to use Alexa with SinricPro
- SinricPro Quick Start
- SinricPro Android APP
- SinricPro Apple APP
Sample code Generic_Ethernet_Light
#if defined(ESP8266) || defined(ESP32)
#error This code is not intended to run on the ESP32/ESP8266 boards ! Please check your Tools->Board setting.
#endif
// Uncomment the following line to enable serial debug output
#define ENABLE_DEBUG true
#if ENABLE_DEBUG
#define DEBUG_PORT Serial
#define NODEBUG_WEBSOCKETS
#define NDEBUG
#endif
#define LOGWARN(x) if(ENABLE_DEBUG) { Serial.print("[SINRIC_PRO] "); Serial.println(x); }
#define LOGWARN1(x,y) if(ENABLE_DEBUG) { Serial.print("[SINRIC_PRO] "); Serial.print(x);\
Serial.print(" "); Serial.println(y); }
// Use true for ENC28J60 and UIPEthernet library (https://github.com/UIPEthernet/UIPEthernet)
// Use false for W5x00 and Ethernetx library (https://www.arduino.cc/en/Reference/Ethernet)
#define USE_UIP_ETHERNET true
//#define USE_UIP_ETHERNET false
#if USE_UIP_ETHERNET
#define WEBSOCKETS_NETWORK_TYPE NETWORK_ENC28J60
#endif
//#define USE_CUSTOM_ETHERNET true
// Note: To rename ESP628266 Ethernet lib files to Ethernet_ESP8266.h and Ethernet_ESP8266.cpp
// In order to USE_ETHERNET_ESP8266
#if ( !defined(USE_UIP_ETHERNET) || !USE_UIP_ETHERNET )
// To override the default CS/SS pin. Don't use unless you know exactly which pin to use
//#define USE_THIS_SS_PIN 27//22 //21 //5 //4 //2 //15
// Only one if the following to be true
#define USE_ETHERNET2 false //true
#define USE_ETHERNET3 false //true
#define USE_ETHERNET_LARGE false //true
#define USE_ETHERNET_ESP8266 false //true
#if ( USE_ETHERNET2 || USE_ETHERNET3 || USE_ETHERNET_LARGE || USE_ETHERNET_ESP8266 )
#ifdef USE_CUSTOM_ETHERNET
#undef USE_CUSTOM_ETHERNET
#endif
#define USE_CUSTOM_ETHERNET true
#endif
#ifdef WEBSOCKETS_NETWORK_TYPE
#undef WEBSOCKETS_NETWORK_TYPE
#endif
#define WEBSOCKETS_NETWORK_TYPE NETWORK_W5100
#if USE_ETHERNET3
#include "Ethernet3.h"
#warning Use Ethernet3 lib
#elif USE_ETHERNET2
#include "Ethernet2.h"
#warning Use Ethernet2 lib
#elif USE_ETHERNET_LARGE
#include "EthernetLarge.h"
#warning Use EthernetLarge lib
#elif USE_ETHERNET_ESP8266
#include "Ethernet_ESP8266.h"
#warning Use Ethernet_ESP8266 lib
#elif USE_CUSTOM_ETHERNET
#include "Ethernet_XYZ.h"
#warning Use Custom Ethernet library from EthernetWrapper. You must include a library here or error.
#else
#define USE_ETHERNET true
#include "Ethernet.h"
#warning Use Ethernet lib
#endif
// Ethernet_Shield_W5200, EtherCard, EtherSia not supported
// Select just 1 of the following #include if uncomment #define USE_CUSTOM_ETHERNET
// Otherwise, standard Ethernet library will be used for W5x00
#endif //#if !USE_UIP_ETHERNET
// Enter a MAC address and IP address for your controller below.
#define NUMBER_OF_MAC 20
byte mac[][NUMBER_OF_MAC] =
{
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x01 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x02 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x03 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x04 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x05 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x06 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x07 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x08 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x09 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0A },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0B },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0C },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0D },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0E },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0F },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x10 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x11 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x12 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x13 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x14 },
};
#include "SinricPro_Generic.h"
#include "SinricProLight.h"
// Select the IP address according to your local network
IPAddress ip(192, 168, 2, 222);
#define APP_KEY "YOUR-APP-KEY" // Should look like "de0bxxxx-1x3x-4x3x-ax2x-5dabxxxxxxxx"
#define APP_SECRET "YOUR-APP-SECRET" // Should look like "5f36xxxx-x3x7-4x3x-xexe-e86724a9xxxx-4c4axxxx-3x3x-x5xe-x9x3-333d65xxxxxx"
#define LIGHT_ID "YOUR-DEVICE-ID" // Should look like "5dc1564130xxxxxxxxxxxxxx"
#define BAUD_RATE 115200 // Change baudrate to your need
// define array of supported color temperatures
int colorTemperatureArray[] = { 2200, 2700, 4000, 5500, 7000 };
int max_color_temperatures = sizeof(colorTemperatureArray) / sizeof(colorTemperatureArray[0]); // calculates how many elements are stored in colorTemperature array
// a map used to convert a given color temperature into color temperature index (used for colorTemperatureArray)
std::map<int, int> colorTemperatureIndex;
// initializes the map above with color temperatures and index values
// so that the map can be used to do a reverse search like
// int index = colorTemperateIndex[4000]; <- will result in index == 2
void setupColorTemperatureIndex()
{
Serial.println("Setup color temperature lookup table");
for (int i = 0; i < max_color_temperatures; i++)
{
colorTemperatureIndex[colorTemperatureArray[i]] = i;
Serial.println("colorTemperatureIndex[" + String(colorTemperatureArray[i]) + "] = " + String(colorTemperatureIndex[colorTemperatureArray[i]]));
}
}
// we use a struct to store all states and values for our light
struct
{
bool powerState = false;
int brightness = 0;
struct
{
byte r = 0;
byte g = 0;
byte b = 0;
} color;
int colorTemperature = colorTemperatureArray[0]; // set colorTemperature to first element in colorTemperatureArray array
} device_state;
bool onPowerState(const String &deviceId, bool &state)
{
Serial.println("Device " + deviceId + String(state ? " turned on" : " turn off") + " (via SinricPro)" );
device_state.powerState = state;
return true; // request handled properly
}
bool onBrightness(const String &deviceId, int &brightness)
{
device_state.brightness = brightness;
Serial.println("Device " + deviceId + " brightness level changed to " + String(brightness));
return true;
}
bool onAdjustBrightness(const String &deviceId, int brightnessDelta)
{
device_state.brightness += brightnessDelta;
Serial.println("Device " + deviceId + " brightness level changed about " + String(brightnessDelta) + " to " + String(device_state.brightness));
brightnessDelta = device_state.brightness;
return true;
}
bool onColor(const String &deviceId, byte &r, byte &g, byte &b)
{
device_state.color.r = r;
device_state.color.g = g;
device_state.color.b = b;
Serial.println("Device " + deviceId + " color changed to " + String(device_state.color.r) + ", "
+ String(device_state.color.g) + ", " + String(device_state.color.g) + "(RGB)");
return true;
}
bool onColorTemperature(const String &deviceId, int &colorTemperature)
{
device_state.colorTemperature = colorTemperature;
Serial.println("Device " + deviceId + " color temperature changed to " + String(device_state.colorTemperature));
return true;
}
bool onIncreaseColorTemperature(const String &deviceId, int &colorTemperature)
{
int index = colorTemperatureIndex[device_state.colorTemperature]; // get index of stored colorTemperature
index++; // do the increase
if (index < 0)
index = 0; // make sure that index stays within array boundaries
if (index > max_color_temperatures - 1)
index = max_color_temperatures - 1; // make sure that index stays within array boundaries
device_state.colorTemperature = colorTemperatureArray[index]; // get the color temperature value
Serial.println("Device " + deviceId + " increased color temperature to " + String(device_state.colorTemperature));
colorTemperature = device_state.colorTemperature; // return current color temperature value
return true;
}
bool onDecreaseColorTemperature(const String &deviceId, int &colorTemperature)
{
int index = colorTemperatureIndex[device_state.colorTemperature]; // get index of stored colorTemperature
index--; // do the decrease
if (index < 0)
index = 0; // make sure that index stays within array boundaries
if (index > max_color_temperatures - 1)
index = max_color_temperatures - 1; // make sure that index stays within array boundaries
device_state.colorTemperature = colorTemperatureArray[index]; // get the color temperature value
Serial.println("Device " + deviceId + " decreased color temperature to " + String(device_state.colorTemperature));
colorTemperature = device_state.colorTemperature; // return current color temperature value
return true;
}
// setup function for setupEthernet connection
void setupEthernet()
{
#if USE_ETHERNET
LOGWARN(F("=========== USE_ETHERNET ==========="));
#elif USE_ETHERNET2
LOGWARN(F("=========== USE_ETHERNET2 ==========="));
#elif USE_ETHERNET3
LOGWARN(F("=========== USE_ETHERNET3 ==========="));
#elif USE_ETHERNET_LARGE
LOGWARN(F("=========== USE_ETHERNET_LARGE ==========="));
#elif USE_ETHERNET_ESP8266
LOGWARN(F("=========== USE_ETHERNET_ESP8266 ==========="));
#else
LOGWARN(F("========================="));
#endif
LOGWARN(F("Default SPI pinout:"));
LOGWARN1(F("MOSI:"), MOSI);
LOGWARN1(F("MISO:"), MISO);
LOGWARN1(F("SCK:"), SCK);
LOGWARN1(F("SS:"), SS);
LOGWARN(F("========================="));
// unknown board, do nothing, use default SS = 10
#ifndef USE_THIS_SS_PIN
#define USE_THIS_SS_PIN 10 // For other boards
#endif
LOGWARN1(F("Use default CS/SS pin : "), USE_THIS_SS_PIN);
// For other boards, to change if necessary
#if ( USE_ETHERNET || USE_ETHERNET_LARGE || USE_ETHERNET2 )
// Must use library patch for Ethernet, Ethernet2, EthernetLarge libraries
Ethernet.init (USE_THIS_SS_PIN);
#elif USE_ETHERNET3
// Use MAX_SOCK_NUM = 4 for 4K, 2 for 8K, 1 for 16K RX/TX buffer
#ifndef ETHERNET3_MAX_SOCK_NUM
#define ETHERNET3_MAX_SOCK_NUM 4
#endif
Ethernet.setCsPin (USE_THIS_SS_PIN);
Ethernet.init (ETHERNET3_MAX_SOCK_NUM);
#endif //( USE_ETHERNET || USE_ETHERNET2 || USE_ETHERNET3 || USE_ETHERNET_LARGE )
// start the ethernet connection and the server:
// Use Static IP
//Ethernet.begin(mac, ip);
// Use DHCP dynamic IP and random mac
srand(millis());
uint16_t index = rand() % NUMBER_OF_MAC;
Serial.print("Index = ");
Serial.println(index);
Ethernet.begin(mac[index]);
Serial.print("Connected!\n[Ethernet]: IP-Address is ");
Serial.println(Ethernet.localIP());
}
void setupSinricPro()
{
// get a new Light device from SinricPro
SinricProLight &myLight = SinricPro[LIGHT_ID];
// set callback function to device
myLight.onPowerState(onPowerState);
myLight.onBrightness(onBrightness);
myLight.onAdjustBrightness(onAdjustBrightness);
myLight.onColor(onColor);
myLight.onColorTemperature(onColorTemperature);
myLight.onIncreaseColorTemperature(onIncreaseColorTemperature);
myLight.onDecreaseColorTemperature(onDecreaseColorTemperature);
// setup SinricPro
SinricPro.onConnected([]()
{
Serial.println("Connected to SinricPro");
});
SinricPro.onDisconnected([]()
{
Serial.println("Disconnected from SinricPro");
});
SinricPro.begin(APP_KEY, APP_SECRET);
}
// main setup function
void setup()
{
Serial.begin(BAUD_RATE);
while (!Serial);
Serial.println("\nStarting Generic_Ethernet_Light");
setupColorTemperatureIndex(); // setup our helper map
setupEthernet();
setupSinricPro();
}
void loop()
{
SinricPro.handle();
}
Terminal output of SAMD_Ethernet_TV example
Starting SAMD_Ethernet_TV on ADAFRUIT_ITSYBITSY_M4_EXPRESS
12 channels configured
Index = 7
_pinCS = 0
W5100 init, using SS_PIN_DEFAULT = 10, new ss_pin = 10, W5100Class::ss_pin = 10
W5100::init: W5500, SSIZE =4096
Connected!
[Ethernet]: IP-Address is 192.168.2.79
Connected to SinricPro
TV turned on
TV turned off
TV turned on
TV turned off
TV turned on
Volume set to: 65
TV volume is muted
TV volume is unmuted
TV turned off
TV turned on
TV turned off
TV turned on
TV turned off
TV turned on
TV volume is muted
Skip channel: 1 (number: 1 / name: "CTV"
TV volume is unmuted
TV volume is muted
Volume set to: 36
Skip channel: -1 (number: 0 / name: "A/V"
Volume set to: 59