// MultiDevice: two lamps on one board, two Alexa endpoints, one handler (Alexa.PowerController). // // Every device has its own endpoint id and name. Both get the same handler; the directive says which device it // is for. #include #include #include // Wi-Fi and the credentials of your Alex2MQTT account const char *WIFI_SSID = ""; const char *WIFI_PASSWORD = ""; const char *ALEXA_USERNAME = ""; const char *ALEXA_PASSWORD = ""; const char *ALEXA_ROOT_TOPIC = ""; const int LAMP_COUNT = 2; const uint8_t LAMP_PINS[LAMP_COUNT] = {5, 4}; // D1 and D2 on a Wemos D1 mini, high = lit const char *const LAMP_NAMES[LAMP_COUNT] = {"Left Lamp", "Right Lamp"}; const char *const LAMP_IDS[LAMP_COUNT] = {"esp-multi-left", "esp-multi-right"}; Alex2ESP alexa; AlexaDevice *lamps[LAMP_COUNT]; bool lampOn[LAMP_COUNT] = {false, false}; // Joins the Wi-Fi network and returns after 30 s at the latest. Without a connection the sketch carries on: the // ESP8266 keeps trying, and alexa.loop() opens the MQTT session once Wi-Fi is up. void connectWiFi() { WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); Serial.printf("\n[WIFI] Connecting to \"%s\"\n", WIFI_SSID); unsigned long started = millis(); while (WiFi.status() != WL_CONNECTED && millis() - started < 30000) { delay(100); } if (WiFi.status() == WL_CONNECTED) { Serial.printf("[WIFI] Connected, IP address %s\n", WiFi.localIP().toString().c_str()); } else { Serial.printf("[WIFI] No connection after 30 s (status %d): check WIFI_SSID and WIFI_PASSWORD. Still trying.\n", WiFi.status()); } } // The state of one lamp: what the answer to a directive and the answer to ReportState carry void sendState(AlexaStatusMessage message, int lamp) { message.addHealthProp(EndpointHealth::OK) .addPowerControllerProp(lampOn[lamp] ? PowerController::ON : PowerController::OFF) .send(); } void onDirective(AlexaDirective &directive) { int lamp = directive.device == lamps[1] ? 1 : 0; if (directive.isReportState()) { sendState(directive.stateReport(), lamp); return; } if (directive.type == AlexaInterfaceType::POWER_CONTROLLER && (directive.is("TurnOn") || directive.is("TurnOff"))) { lampOn[lamp] = directive.is("TurnOn"); digitalWrite(LAMP_PINS[lamp], lampOn[lamp] ? HIGH : LOW); sendState(directive.response(), lamp); return; } directive.error(AlexaErrorType::INVALID_DIRECTIVE, "This lamp switches on and off").send(); } void setup() { Serial.begin(74880); connectWiFi(); // MQTT user name, MQTT password, root topic alexa.begin(ALEXA_USERNAME, ALEXA_PASSWORD, ALEXA_ROOT_TOPIC); for (int i = 0; i < LAMP_COUNT; i++) { pinMode(LAMP_PINS[i], OUTPUT); digitalWrite(LAMP_PINS[i], LOW); // The name Alexa shows, and the id of the endpoint: every device of an account has its own lamps[i] = alexa.getDevice(LAMP_NAMES[i], LAMP_IDS[i]); lamps[i]->setDisplayCategory(DisplayCategory::LIGHT); lamps[i]->addCapability(AlexaInterfaces::PowerController); lamps[i]->addCapability(AlexaInterfaces::EndpointHealth); lamps[i]->onDirective(onDirective); } } void loop() { alexa.loop(); }