RMakerSonoffDualR3.ino 6.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
//This example demonstrates the ESP RainMaker with a standard Switch device.
#include "RMaker.h"
#include "WiFi.h"
#include "WiFiProv.h"

#define DEFAULT_POWER_MODE false
const char *service_name = "PROV_SONOFF_DUALR3";
const char *pop = "123456";

// GPIO for push button
static uint8_t gpio_reset = 0;
// GPIO for switch
static uint8_t gpio_switch1 = 32;
static uint8_t gpio_switch2 = 33;
// GPIO for virtual device
static uint8_t gpio_relay1 = 27;
static uint8_t gpio_relay2 = 14;
/* Variable for reading pin status*/
bool switch_state_ch1 = true;
bool switch_state_ch2 = true;
// GPIO for link status LED
static uint8_t gpio_led = 13;

struct LightSwitch {
    const uint8_t pin;
    bool pressed;
};

// Define the light switches for channel 1 and 2
LightSwitch switch_ch1 = {gpio_switch1, false};
LightSwitch switch_ch2 = {gpio_switch2, false};

//The framework provides some standard device types like switch, lightbulb, fan, temperature sensor.
34 35
static Switch my_switch1;
static Switch my_switch2;
36 37 38

void sysProvEvent(arduino_event_t *sys_event)
{
39
    switch (sys_event->event_id) {
40 41 42 43 44 45 46
        case ARDUINO_EVENT_PROV_START:
#if CONFIG_IDF_TARGET_ESP32
        Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop);
        printQR(service_name, pop, "ble");
#else
        Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop);
        printQR(service_name, pop, "softap");
47
#endif
48 49 50 51 52
        break;
        case ARDUINO_EVENT_WIFI_STA_CONNECTED:
        Serial.printf("\nConnected to Wi-Fi!\n");
        digitalWrite(gpio_led, true);
        break;
53
        default:;
54 55 56 57 58 59 60 61 62
    }
}

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(device_name, "Switch_ch1") == 0) {
63

64
      Serial.printf("Lightbulb = %s\n", val.val.b? "true" : "false");
65

66 67 68 69 70 71
      if(strcmp(param_name, "Power") == 0) {
          Serial.printf("Received value = %s for %s - %s\n", val.val.b? "true" : "false", device_name, param_name);
        switch_state_ch1 = val.val.b;
        (switch_state_ch1 == false) ? digitalWrite(gpio_relay1, LOW) : digitalWrite(gpio_relay1, HIGH);
        param->updateAndReport(val);
      }
72

73
    } else if(strcmp(device_name, "Switch_ch2") == 0) {
74

75 76 77 78 79 80 81 82
      Serial.printf("Switch value = %s\n", val.val.b? "true" : "false");

      if(strcmp(param_name, "Power") == 0) {
        Serial.printf("Received value = %s for %s - %s\n", val.val.b? "true" : "false", device_name, param_name);
        switch_state_ch2 = val.val.b;
        (switch_state_ch2 == false) ? digitalWrite(gpio_relay2, LOW) : digitalWrite(gpio_relay2, HIGH);
        param->updateAndReport(val);
      }
83

84
    }
85

86 87 88 89 90 91 92 93 94
}

void ARDUINO_ISR_ATTR isr(void* arg) {
    LightSwitch* s = static_cast<LightSwitch*>(arg);
    s->pressed = true;
}

void setup()
{
95

96
    uint32_t chipId = 0;
97

98 99 100 101 102 103 104 105
    Serial.begin(115200);

    // Configure the input GPIOs
    pinMode(gpio_reset, INPUT);
    pinMode(switch_ch1.pin, INPUT_PULLUP);
    attachInterruptArg(switch_ch1.pin, isr, &switch_ch1, CHANGE);
    pinMode(switch_ch2.pin, INPUT_PULLUP);
    attachInterruptArg(switch_ch2.pin, isr, &switch_ch2, CHANGE);
106

107 108 109 110 111 112 113 114 115
    // Set the Relays GPIOs as output mode
    pinMode(gpio_relay1, OUTPUT);
    pinMode(gpio_relay2, OUTPUT);
    pinMode(gpio_led, OUTPUT);
    // Write to the GPIOs the default state on booting
    digitalWrite(gpio_relay1, DEFAULT_POWER_MODE);
    digitalWrite(gpio_relay2, DEFAULT_POWER_MODE);
    digitalWrite(gpio_led, false);

116
    Node my_node;
117 118
    my_node = RMaker.initNode("Sonoff Dual R3");

119 120 121 122
    //Initialize switch device
    my_switch1 = Switch("Switch_ch1", &gpio_relay1);
    my_switch2 = Switch("Switch_ch2", &gpio_relay2);

123 124 125 126
    //Standard switch device
    my_switch1.addCb(write_callback);
    my_switch2.addCb(write_callback);

127
    //Add switch device to the node
128 129 130
    my_node.addDevice(my_switch1);
    my_node.addDevice(my_switch2);

131
    //This is optional
132
    RMaker.enableOTA(OTA_USING_PARAMS);
133
    //If you want to enable scheduling, set time zone for your region using setTimeZone().
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
    //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();

    //Service Name
    for(int i=0; i<17; i=i+8) {
      chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
    }

    Serial.printf("\nChip ID:  %d Service Name: %s\n", chipId, service_name);

    Serial.printf("\nStarting ESP-RainMaker\n");
    RMaker.start();

    WiFi.onEvent(sysProvEvent);
#if CONFIG_IDF_TARGET_ESP32
    WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name);
#else
    WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name);
#endif
}

void loop()
{

    if (switch_ch1.pressed) {
        Serial.printf("Switch 1 has been changed\n");
        switch_ch1.pressed = false;
        // Toggle switch 1 device state
        switch_state_ch1 = !switch_state_ch1;
        Serial.printf("Toggle State to %s.\n", switch_state_ch1 ? "true" : "false");
        my_switch1.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, switch_state_ch1);
        (switch_state_ch1 == false) ? digitalWrite(gpio_relay1, LOW) : digitalWrite(gpio_relay1, HIGH);
    } else if (switch_ch2.pressed) {
        Serial.printf("Switch 2 has been changed\n");
        switch_ch2.pressed = false;
        // Toggle switch 2 device state
        switch_state_ch2 = !switch_state_ch2;
        Serial.printf("Toggle State to %s.\n", switch_state_ch2 ? "true" : "false");
        my_switch2.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, switch_state_ch2);
        (switch_state_ch2 == false) ? digitalWrite(gpio_relay2, LOW) : digitalWrite(gpio_relay2, HIGH);
    }

    // Read GPIO0 (external button to reset device
    if(digitalRead(gpio_reset) == LOW) { //Push button pressed
        Serial.printf("Reset Button Pressed!\n");
        // Key debounce handling
        delay(100);
        int startTime = millis();
        while(digitalRead(gpio_reset) == LOW) delay(50);
        int endTime = millis();

        if ((endTime - startTime) > 10000) {
          // If key pressed for more than 10secs, reset all
          Serial.printf("Reset to factory.\n");
          RMakerFactoryReset(2);
        } else if ((endTime - startTime) > 3000) {
          Serial.printf("Reset Wi-Fi.\n");
          // If key pressed for more than 3secs, but less than 10, reset Wi-Fi
          RMakerWiFiReset(2);
        }
    }
    delay(100);
}