Using rainMaker with array #7890
FernandoGarcia
started this conversation in
General
Replies: 1 comment
-
The solution is: #include "RMaker.h"
#include "WiFi.h"
#include "WiFiProv.h"
#include <Preferences.h>
#include <AceButton.h>
#define NUM_RELAYS 8
#if CONFIG_IDF_TARGET_ESP32C3
const byte resetPin = 9;
#else
const byte resetPin = 0;
#endif
const char nodeName[] = "ESP32_Relay_16";
const char *service_name = "PROV_1234";
const char *pop = "abcd1234";
bool firstPress = true;
Preferences pref;
using namespace ace_button;
// Define the buttons in an array using the default constructor.
AceButton lightSwitch[NUM_RELAYS];
// The framework provides some standard device types like switch, lightbulb, fan, temperaturesensor.
static Switch myRelay[NUM_RELAYS];
struct INFOS
{
const char *deviceName;
uint8_t relayPin;
bool relayState;
uint8_t switchPin;
};
#define INITIAL_STATE LOW // Initial state = HIGH to active LOW relay model.
// Define the device name, relay pin, relay default status and switch pin to an array.
INFOS info[NUM_RELAYS] = {
{ "Relay1", 4, INITIAL_STATE, 26},
{ "Relay2", 5, INITIAL_STATE, 27},
{ "Relay3", 18, INITIAL_STATE, 32},
{ "Relay4", 19, INITIAL_STATE, 33},
{ "Relay5", 21, INITIAL_STATE, 13},
{ "Relay6", 22, INITIAL_STATE, 12},
{ "Relay7", 23, INITIAL_STATE, 14},
{ "Relay8", 25, INITIAL_STATE, 15}
};
void sysProvEvent(arduino_event_t *sys_event)
{
switch (sys_event->event_id)
{
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
{
Serial.print("\nConnected IP address : ");
Serial.println(IPAddress(sys_event->event_info.got_ip.ip_info.ip.addr));
break;
}
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
{
Serial.println("\nDisconnected. Connecting to the AP again... ");
break;
}
case ARDUINO_EVENT_PROV_START:
{
#if CONFIG_IDF_TARGET_ESP32S2
Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop);
printQR(service_name, pop, "softap");
#else
Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop);
printQR(service_name, pop, "ble");
#endif
break;
}
case ARDUINO_EVENT_PROV_INIT:
{
wifi_prov_mgr_disable_auto_stop(10000);
break;
}
case ARDUINO_EVENT_PROV_CRED_SUCCESS:
{
wifi_prov_mgr_stop_provisioning();
break;
}
case ARDUINO_EVENT_PROV_CRED_RECV:
{
Serial.println("\nReceived Wi-Fi credentials");
Serial.print("\tSSID : ");
Serial.println((const char *) sys_event->event_info.prov_cred_recv.ssid);
Serial.print("\tPassword : ");
Serial.println((char const *) sys_event->event_info.prov_cred_recv.password);
break;
}
case ARDUINO_EVENT_PROV_CRED_FAIL:
{
Serial.println("\nProvisioning failed!\nPlease reset to factory and retry provisioning\n");
if(sys_event->event_info.prov_fail_reason == WIFI_PROV_STA_AUTH_ERROR)
{
Serial.println("\nWi-Fi AP password incorrect");
}
else
{
Serial.println("\nWi-Fi AP not found....Add API \" nvs_flash_erase() \" before beginProvision()");
}
break;
}
case ARDUINO_EVENT_PROV_CRED_SUCCESS:
{
Serial.println("\nProvisioning Successful");
break;
}
case ARDUINO_EVENT_PROV_END:
{
Serial.println("\nProvisioning Ends");
break;
}
default:
{
break;
}
}
}
void write_callback(Device *device, Param *param, const param_val_t val, void *priv_data, write_ctx_t *ctx)
{
const char *device_name = device->getDeviceName();
const char *param_name = param->getParamName();
if (strcmp(param_name, ESP_RMAKER_DEF_POWER_NAME) == 0)
{
for (byte i = 0; i < NUM_RELAYS; i++)
{
if (strcmp(device_name, info[i].deviceName) == 0)
{
info[i].relayState = val.val.b;
digitalWrite(info[i].relayPin, info[i].relayState);
// Publish the new state to all listeners
myRelay[i].updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, info[i].relayState);
// Save the relay state.
pref.putBool(info[i].deviceName, info[i].relayState);
break;
}
}
}
}
void getLastState()
{
for (byte i = 0; i < NUM_RELAYS; i++)
{
info[i].relayState = pref.getBool(info[i].deviceName, info[i].relayState);
digitalWrite(info[i].relayPin, info[i].relayState);
myRelay[i].updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, info[i].relayState);
}
}
void handleEvent(AceButton* button, uint8_t eventType, uint8_t buttonState)
{
uint8_t numSwitch = button->getId();
switch (eventType)
{
case AceButton::kEventPressed:
{
info[numSwitch].relayState = !info[numSwitch].relayState;
Serial.print(F("Light switch "));
Serial.print(numSwitch + 1);
Serial.print(F(" pressed, relayState: "));
Serial.println(info[numSwitch].relayState);
digitalWrite(info[numSwitch].relayPin, info[numSwitch].relayState);
myRelay[numSwitch].updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, info[numSwitch].relayState);
pref.putBool(info[numSwitch].deviceName, info[numSwitch].relayState);
break;
}
case AceButton::kEventReleased:
{
info[numSwitch].relayState = !info[numSwitch].relayState;
Serial.print(F("Light switch "));
Serial.print(numSwitch + 1);
Serial.print(F(" released, relayState: "));
Serial.println(info[numSwitch].relayState);
digitalWrite(info[numSwitch].relayPin, info[numSwitch].relayState);
myRelay[numSwitch].updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, info[numSwitch].relayState);
pref.putBool(info[numSwitch].deviceName, info[numSwitch].relayState);
break;
}
}
}
void setup()
{
Serial.begin(115200);
pinMode(resetPin, INPUT);
// Starts the configuration file where the state will be saved.
pref.begin(nodeName, false);
// Configure the ButtonConfig with the event handler, enable click and long press events.
ButtonConfig* buttonConfig = ButtonConfig::getSystemButtonConfig();
buttonConfig->setEventHandler(handleEvent);
buttonConfig->setFeature(ButtonConfig::kFeatureClick);
buttonConfig->setFeature(ButtonConfig::kFeatureLongPress);
Node my_node;
my_node = RMaker.initNode(nodeName);
for (byte i = 0; i < NUM_RELAYS; i++)
{
pinMode(info[i].relayPin, OUTPUT);
// Turn off all relays.
digitalWrite(info[i].relayPin, info[i].relayState);
// Initialize switch device
myRelay[i] = Switch(info[i].deviceName);
// Specify the callback function to relays.
myRelay[i].addCb(write_callback);
// Add switch device to the node.
my_node.addDevice(myRelay[i]);
// Switch uses the built-in pull up resistor.
pinMode(info[i].switchPin, INPUT_PULLUP);
// initialize the corresponding AceButton.
lightSwitch[i].init(info[i].switchPin, HIGH, i);
}
// This is optional
RMaker.enableOTA(OTA_USING_TOPICS);
// If you want to enable scheduling, set time zone for your region using setTimeZone().
// The list of available values are provided here https://rainmaker.espressif.com/docs/time-service.html
// RMaker.setTimeZone("Asia/Shanghai");
// Alternatively, enable the Timezone service and let the phone apps set the appropriate timezone
RMaker.enableTZService();
RMaker.enableSchedule();
RMaker.enableScenes();
RMaker.start();
WiFi.onEvent(sysProvEvent);
#if CONFIG_IDF_TARGET_ESP32S2
WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name);
#else
WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name);
#endif
// Get the last state of Relays.
getLastState();
}
void loop()
{
for (int i = 0; i < NUM_RELAYS; i++)
{
lightSwitch[i].check();
}
// Push button pressed.
if(digitalRead(resetPin) == LOW)
{
// Key debounce handling.
delay(100);
int startTime = millis();
while(digitalRead(resetPin) == LOW)
{
delay(50);
}
int endTime = millis();
// If key pressed for more than 10secs, reset all.
if ((endTime - startTime) > 10000)
{
Serial.printf("Factory reset!");
RMakerFactoryReset(2);
}
}
} |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Hi!
What's the right way to use rainMaker with array?
I was doing in this way:
But I have this compiling errors:
Thanks in advance.
Best regards.
Beta Was this translation helpful? Give feedback.
All reactions