Skip to content

[Feature] Added Sonoff DUALR3 support with RainMaker example #5980

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions boards.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10018,3 +10018,104 @@ franzininho_wifi_msc_esp32s2.menu.DebugLevel.verbose=Verbose
franzininho_wifi_msc_esp32s2.menu.DebugLevel.verbose.build.code_debug=5

##############################################################

sonoff_dualr3.name=Sonoff DUALR3

sonoff_dualr3.upload.tool=esptool_py
sonoff_dualr3.upload.maximum_size=1310720
sonoff_dualr3.upload.maximum_data_size=327680
sonoff_dualr3.upload.flags=
sonoff_dualr3.upload.extra_flags=

sonoff_dualr3.serial.disableDTR=true
sonoff_dualr3.serial.disableRTS=true

sonoff_dualr3.build.tarch=xtensa
sonoff_dualr3.build.bootloader_addr=0x1000
sonoff_dualr3.build.target=esp32
sonoff_dualr3.build.mcu=esp32
sonoff_dualr3.build.core=esp32
sonoff_dualr3.build.variant=esp32
sonoff_dualr3.build.board=SONOFF_DUALR3

sonoff_dualr3.build.f_cpu=240000000L
sonoff_dualr3.build.flash_size=4MB
sonoff_dualr3.build.flash_freq=40m
sonoff_dualr3.build.flash_mode=dio
sonoff_dualr3.build.boot=dio
sonoff_dualr3.build.partitions=rainmaker
sonoff_dualr3.build.defines=
sonoff_dualr3.build.loop_core=
sonoff_dualr3.build.event_core=

sonoff_dualr3.menu.PartitionScheme.rainmaker=RainMaker
sonoff_dualr3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker
sonoff_dualr3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728

sonoff_dualr3.menu.CPUFreq.240=240MHz (WiFi/BT)
sonoff_dualr3.menu.CPUFreq.240.build.f_cpu=240000000L
sonoff_dualr3.menu.CPUFreq.160=160MHz (WiFi/BT)
sonoff_dualr3.menu.CPUFreq.160.build.f_cpu=160000000L
sonoff_dualr3.menu.CPUFreq.80=80MHz (WiFi/BT)
sonoff_dualr3.menu.CPUFreq.80.build.f_cpu=80000000L
sonoff_dualr3.menu.CPUFreq.40=40MHz (40MHz XTAL)
sonoff_dualr3.menu.CPUFreq.40.build.f_cpu=40000000L
sonoff_dualr3.menu.CPUFreq.26=26MHz (26MHz XTAL)
sonoff_dualr3.menu.CPUFreq.26.build.f_cpu=26000000L
sonoff_dualr3.menu.CPUFreq.20=20MHz (40MHz XTAL)
sonoff_dualr3.menu.CPUFreq.20.build.f_cpu=20000000L
sonoff_dualr3.menu.CPUFreq.13=13MHz (26MHz XTAL)
sonoff_dualr3.menu.CPUFreq.13.build.f_cpu=13000000L
sonoff_dualr3.menu.CPUFreq.10=10MHz (40MHz XTAL)
sonoff_dualr3.menu.CPUFreq.10.build.f_cpu=10000000L

sonoff_dualr3.menu.FlashMode.qio=QIO
sonoff_dualr3.menu.FlashMode.qio.build.flash_mode=dio
sonoff_dualr3.menu.FlashMode.qio.build.boot=qio
sonoff_dualr3.menu.FlashMode.dio=DIO
sonoff_dualr3.menu.FlashMode.dio.build.flash_mode=dio
sonoff_dualr3.menu.FlashMode.dio.build.boot=dio
sonoff_dualr3.menu.FlashMode.qout=QOUT
sonoff_dualr3.menu.FlashMode.qout.build.flash_mode=dout
sonoff_dualr3.menu.FlashMode.qout.build.boot=qout
sonoff_dualr3.menu.FlashMode.dout=DOUT
sonoff_dualr3.menu.FlashMode.dout.build.flash_mode=dout
sonoff_dualr3.menu.FlashMode.dout.build.boot=dout

sonoff_dualr3.menu.FlashFreq.80=80MHz
sonoff_dualr3.menu.FlashFreq.80.build.flash_freq=80m
sonoff_dualr3.menu.FlashFreq.40=40MHz
sonoff_dualr3.menu.FlashFreq.40.build.flash_freq=40m

sonoff_dualr3.menu.FlashSize.4M=4MB (32Mb)
sonoff_dualr3.menu.FlashSize.4M.build.flash_size=4MB

sonoff_dualr3.menu.UploadSpeed.921600=921600
sonoff_dualr3.menu.UploadSpeed.921600.upload.speed=921600
sonoff_dualr3.menu.UploadSpeed.115200=115200
sonoff_dualr3.menu.UploadSpeed.115200.upload.speed=115200
sonoff_dualr3.menu.UploadSpeed.256000.windows=256000
sonoff_dualr3.menu.UploadSpeed.256000.upload.speed=256000
sonoff_dualr3.menu.UploadSpeed.230400.windows.upload.speed=256000
sonoff_dualr3.menu.UploadSpeed.230400=230400
sonoff_dualr3.menu.UploadSpeed.230400.upload.speed=230400
sonoff_dualr3.menu.UploadSpeed.460800.linux=460800
sonoff_dualr3.menu.UploadSpeed.460800.macosx=460800
sonoff_dualr3.menu.UploadSpeed.460800.upload.speed=460800
sonoff_dualr3.menu.UploadSpeed.512000.windows=512000
sonoff_dualr3.menu.UploadSpeed.512000.upload.speed=512000

sonoff_dualr3.menu.DebugLevel.none=None
sonoff_dualr3.menu.DebugLevel.none.build.code_debug=0
sonoff_dualr3.menu.DebugLevel.error=Error
sonoff_dualr3.menu.DebugLevel.error.build.code_debug=1
sonoff_dualr3.menu.DebugLevel.warn=Warn
sonoff_dualr3.menu.DebugLevel.warn.build.code_debug=2
sonoff_dualr3.menu.DebugLevel.info=Info
sonoff_dualr3.menu.DebugLevel.info.build.code_debug=3
sonoff_dualr3.menu.DebugLevel.debug=Debug
sonoff_dualr3.menu.DebugLevel.debug.build.code_debug=4
sonoff_dualr3.menu.DebugLevel.verbose=Verbose
sonoff_dualr3.menu.DebugLevel.verbose.build.code_debug=5

##############################################################
Empty file.
Empty file.
193 changes: 193 additions & 0 deletions libraries/RainMaker/examples/RMakerSonoffDualR3/RMakerSonoffDualR3.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
//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.
static Switch my_switch1("Switch_ch1", &gpio_relay1);
static Switch my_switch2("Switch_ch2", &gpio_relay2);

void sysProvEvent(arduino_event_t *sys_event)
{
switch (sys_event->event_id) {
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");
#endif
break;
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
Serial.printf("\nConnected to Wi-Fi!\n");
digitalWrite(gpio_led, true);
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(device_name, "Switch_ch1") == 0) {

Serial.printf("Lightbulb = %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_ch1 = val.val.b;
(switch_state_ch1 == false) ? digitalWrite(gpio_relay1, LOW) : digitalWrite(gpio_relay1, HIGH);
param->updateAndReport(val);
}

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

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);
}

}

}

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

void setup()
{
uint32_t chipId = 0;

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);

// 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);

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

//Standard switch device
my_switch1.addCb(write_callback);
my_switch2.addCb(write_callback);

//Add switch device to the node
my_node.addDevice(my_switch1);
my_node.addDevice(my_switch2);

//This is optional
RMaker.enableOTA(OTA_USING_PARAMS);
//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();

//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);
}
27 changes: 27 additions & 0 deletions variants/sonoff_dualr3/pins_arduino.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h

#include <stdint.h>

#define EXTERNAL_NUM_INTERRUPTS 16
#define NUM_DIGITAL_PINS 40
#define NUM_ANALOG_INPUTS 16

#define analogInputToDigitalPin(p) (((p)<20)?(esp32_adc2gpio[(p)]):-1)
#define digitalPinToInterrupt(p) (((p)<40)?(p):-1)
#define digitalPinHasPWM(p) (p < 34)

static const uint8_t TX = 1;
static const uint8_t RX = 3;

static const uint8_t BUTTON = 0;
static const uint8_t LED_LINK = 13;
static const uint8_t RELAY_2 = 14;
static const uint8_t RELAY_1 = 27;
static const uint8_t SWITCH_2 = 33;
static const uint8_t SWITCH_1 = 32;

static const uint8_t CSE7761_TX = 25;
static const uint8_t CSE7761_RX = 26;

#endif /* Pins_Arduino_h */