|
| 1 | +//This example demonstrates the ESP RainMaker with a custom Air Cooler device |
| 2 | +#include "RMaker.h" |
| 3 | +#include "WiFi.h" |
| 4 | +#include "WiFiProv.h" |
| 5 | +#include "led_strip.h" |
| 6 | + |
| 7 | +#define DEFAULT_POWER_MODE true |
| 8 | +#define DEFAULT_SWING false |
| 9 | +#define DEFAULT_SPEED 0 |
| 10 | +#define DEFAULT_MODE "Auto" |
| 11 | + |
| 12 | +const char *service_name = "PROV_1234"; |
| 13 | +const char *pop = "abcd1234"; |
| 14 | + |
| 15 | +#if CONFIG_IDF_TARGET_ESP32C3 |
| 16 | +//GPIO for push button |
| 17 | +static int gpio_reset = 9; |
| 18 | +//GPIO for virtual device |
| 19 | +static int gpio_power = 7; |
| 20 | +static int gpio_swing = 3; |
| 21 | +static int gpio_mode_auto = 4; |
| 22 | +static int gpio_mode_cool = 5; |
| 23 | +static int gpio_mode_heat = 6; |
| 24 | +static int gpio_speed = 10; |
| 25 | + |
| 26 | +#else |
| 27 | +//GPIO for push button |
| 28 | +static int gpio_reset = 0; |
| 29 | +//GPIO for virtual device |
| 30 | +static int gpio_power = 16; |
| 31 | +static int gpio_swing = 17; |
| 32 | +static int gpio_mode_auto = 18; |
| 33 | +static int gpio_mode_cool = 19; |
| 34 | +static int gpio_mode_heat = 21; |
| 35 | +static int gpio_speed = 22; |
| 36 | +#endif |
| 37 | + |
| 38 | +bool power_state = true; |
| 39 | + |
| 40 | +// The framework provides some standard device types like switch, lightbulb, fan, temperature sensor. |
| 41 | +// But, you can also define custom devices using the 'Device' base class object, as shown here |
| 42 | +static Device my_device("Air Cooler", "my.device.air-cooler", NULL); |
| 43 | + |
| 44 | +void sysProvEvent(arduino_event_t *sys_event) |
| 45 | +{ |
| 46 | + switch (sys_event->event_id) { |
| 47 | + case ARDUINO_EVENT_PROV_START: |
| 48 | +#if CONFIG_IDF_TARGET_ESP32S2 |
| 49 | + Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop); |
| 50 | + printQR(service_name, pop, "softap"); |
| 51 | +#else |
| 52 | + Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop); |
| 53 | + printQR(service_name, pop, "ble"); |
| 54 | +#endif |
| 55 | + break; |
| 56 | + default:; |
| 57 | + } |
| 58 | +} |
| 59 | + |
| 60 | +void write_callback(Device *device, Param *param, const param_val_t val, void *priv_data, write_ctx_t *ctx) |
| 61 | +{ |
| 62 | + const char *device_name = device->getDeviceName(); |
| 63 | + const char *param_name = param->getParamName(); |
| 64 | + |
| 65 | + if(strcmp(param_name, "Power") == 0) { |
| 66 | + Serial.printf("Received value = %s for %s - %s\n", val.val.b? "true" : "false", device_name, param_name); |
| 67 | + power_state = val.val.b; |
| 68 | + (power_state == false) ? digitalWrite(gpio_power, LOW) : digitalWrite(gpio_power, HIGH); |
| 69 | + param->updateAndReport(val); |
| 70 | + } else if (strcmp(param_name, "Swing") == 0) { |
| 71 | + Serial.printf("\nReceived value = %s for %s - %s\n", val.val.b? "true" : "false", device_name, param_name); |
| 72 | + bool swing = val.val.b; |
| 73 | + (swing == false) ? digitalWrite(gpio_swing, LOW) : digitalWrite(gpio_swing, HIGH); |
| 74 | + param->updateAndReport(val); |
| 75 | + } else if (strcmp(param_name, "Speed") == 0) { |
| 76 | + Serial.printf("\nReceived value = %d for %s - %s\n", val.val.i, device_name, param_name); |
| 77 | + int speed = val.val.i; |
| 78 | + analogWrite(gpio_speed, speed); |
| 79 | + param->updateAndReport(val); |
| 80 | + } else if (strcmp(param_name, "Mode") == 0) { |
| 81 | + const char* mode = val.val.s; |
| 82 | + if (strcmp(mode, "Auto") == 0) { |
| 83 | + digitalWrite(gpio_mode_auto, HIGH); |
| 84 | + digitalWrite(gpio_mode_heat, LOW); |
| 85 | + digitalWrite(gpio_mode_cool, LOW); |
| 86 | + } else if (strcmp(mode, "Heat") == 0) { |
| 87 | + digitalWrite(gpio_mode_auto, LOW); |
| 88 | + digitalWrite(gpio_mode_heat, HIGH); |
| 89 | + digitalWrite(gpio_mode_cool, LOW); |
| 90 | + } else if (strcmp(mode, "Cool") == 0) { |
| 91 | + digitalWrite(gpio_mode_auto, LOW); |
| 92 | + digitalWrite(gpio_mode_heat, LOW); |
| 93 | + digitalWrite(gpio_mode_cool, HIGH); |
| 94 | + } |
| 95 | + Serial.printf("\nReceived value = %s for %s - %s\n", val.val.s, device_name, param_name); |
| 96 | + param->updateAndReport(val); |
| 97 | + } |
| 98 | +} |
| 99 | + |
| 100 | +void setup() |
| 101 | +{ |
| 102 | + Serial.begin(115200); |
| 103 | + pinMode(gpio_reset, INPUT_PULLUP); |
| 104 | + pinMode(gpio_power, OUTPUT); |
| 105 | + digitalWrite(gpio_power, DEFAULT_POWER_MODE); |
| 106 | + pinMode(gpio_swing, OUTPUT); |
| 107 | + digitalWrite(gpio_swing, DEFAULT_SWING); |
| 108 | + pinMode(gpio_mode_auto, OUTPUT); |
| 109 | + if (strcmp(DEFAULT_MODE, "Auto") == 0) digitalWrite(gpio_mode_auto, HIGH); |
| 110 | + pinMode(gpio_mode_cool, OUTPUT); |
| 111 | + if (strcmp(DEFAULT_MODE, "Cool") == 0) digitalWrite(gpio_mode_auto, HIGH); |
| 112 | + pinMode(gpio_mode_heat, OUTPUT); |
| 113 | + if (strcmp(DEFAULT_MODE, "Heat") == 0) digitalWrite(gpio_mode_auto, HIGH); |
| 114 | + pinMode(gpio_speed, OUTPUT); |
| 115 | + analogWrite(gpio_speed, DEFAULT_SPEED); |
| 116 | + |
| 117 | + Node my_node; |
| 118 | + my_node = RMaker.initNode("ESP RainMaker Node"); |
| 119 | + |
| 120 | + //Create custom air cooler device |
| 121 | + my_device.addNameParam(); |
| 122 | + my_device.addPowerParam(DEFAULT_POWER_MODE); |
| 123 | + my_device.assignPrimaryParam(my_device.getParamByName(ESP_RMAKER_DEF_POWER_NAME)); |
| 124 | + |
| 125 | + Param swing("Swing", ESP_RMAKER_PARAM_TOGGLE, value(DEFAULT_SWING), PROP_FLAG_READ | PROP_FLAG_WRITE); |
| 126 | + swing.addUIType(ESP_RMAKER_UI_TOGGLE); |
| 127 | + my_device.addParam(swing); |
| 128 | + |
| 129 | + Param speed("Speed", ESP_RMAKER_PARAM_RANGE, value(DEFAULT_SPEED), PROP_FLAG_READ | PROP_FLAG_WRITE); |
| 130 | + speed.addUIType(ESP_RMAKER_UI_SLIDER); |
| 131 | + speed.addBounds(value(0), value(255), value(1)); |
| 132 | + my_device.addParam(speed); |
| 133 | + |
| 134 | + static const char* modes[] = { "Auto", "Cool", "Heat" }; |
| 135 | + Param mode_param("Mode", ESP_RMAKER_PARAM_MODE, value("Auto"), PROP_FLAG_READ | PROP_FLAG_WRITE); |
| 136 | + mode_param.addValidStrList(modes, 3); |
| 137 | + mode_param.addUIType(ESP_RMAKER_UI_DROPDOWN); |
| 138 | + my_device.addParam(mode_param); |
| 139 | + |
| 140 | + my_device.addCb(write_callback); |
| 141 | + |
| 142 | + //Add custom Air Cooler device to the node |
| 143 | + my_node.addDevice(my_device); |
| 144 | + |
| 145 | + //This is optional |
| 146 | + // RMaker.enableOTA(OTA_USING_PARAMS); |
| 147 | + //If you want to enable scheduling, set time zone for your region using setTimeZone(). |
| 148 | + //The list of available values are provided here https://rainmaker.espressif.com/docs/time-service.html |
| 149 | + // RMaker.setTimeZone("Asia/Shanghai"); |
| 150 | + //Alternatively, enable the Timezone service and let the phone apps set the appropriate timezone |
| 151 | + // RMaker.enableTZService(); |
| 152 | + |
| 153 | + RMaker.enableSchedule(); |
| 154 | + |
| 155 | + RMaker.start(); |
| 156 | + |
| 157 | + WiFi.onEvent(sysProvEvent); |
| 158 | +#if CONFIG_IDF_TARGET_ESP32S2 |
| 159 | + WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name); |
| 160 | +#else |
| 161 | + WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name); |
| 162 | +#endif |
| 163 | +} |
| 164 | + |
| 165 | +void loop() |
| 166 | +{ |
| 167 | + if(digitalRead(gpio_reset) == LOW) { //Push button pressed |
| 168 | + |
| 169 | + // Key debounce handling |
| 170 | + delay(100); |
| 171 | + int startTime = millis(); |
| 172 | + while(digitalRead(gpio_reset) == LOW) delay(50); |
| 173 | + int press_duration = millis() - startTime; |
| 174 | + |
| 175 | + if (press_duration > 10000) { |
| 176 | + // If key pressed for more than 10secs, reset all |
| 177 | + Serial.printf("Reset to factory.\n"); |
| 178 | + RMakerFactoryReset(2); |
| 179 | + } else if (press_duration > 3000) { |
| 180 | + Serial.printf("Reset Wi-Fi.\n"); |
| 181 | + // If key pressed for more than 3secs, but less than 10, reset Wi-Fi |
| 182 | + RMakerWiFiReset(2); |
| 183 | + } else { |
| 184 | + // Toggle device state |
| 185 | + power_state = !power_state; |
| 186 | + Serial.printf("Toggle power state to %s.\n", power_state ? "true" : "false"); |
| 187 | + my_device.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, power_state); |
| 188 | + (power_state == false) ? digitalWrite(gpio_power, LOW) : digitalWrite(gpio_power, HIGH); |
| 189 | + } |
| 190 | + } |
| 191 | + delay(100); |
| 192 | +} |
0 commit comments