From 39078df17a067a2838e019f535f58c626f386852 Mon Sep 17 00:00:00 2001 From: manuel Date: Sun, 2 Jul 2017 21:15:10 +0200 Subject: oliver/dr_desk --- oliver/dr_desk/.gitignore | 4 + oliver/dr_desk/dr_desk.ino | 286 +++++++++++++++++++++++++++++++++++++++++ oliver/dr_desk/lib/readme.txt | 36 ++++++ oliver/dr_desk/platformio.ini | 21 +++ oliver/dr_desk/src/dr_desk.ino | 1 + 5 files changed, 348 insertions(+) create mode 100644 oliver/dr_desk/.gitignore create mode 100644 oliver/dr_desk/dr_desk.ino create mode 100644 oliver/dr_desk/lib/readme.txt create mode 100644 oliver/dr_desk/platformio.ini create mode 120000 oliver/dr_desk/src/dr_desk.ino diff --git a/oliver/dr_desk/.gitignore b/oliver/dr_desk/.gitignore new file mode 100644 index 0000000..5dac9f5 --- /dev/null +++ b/oliver/dr_desk/.gitignore @@ -0,0 +1,4 @@ +.pioenvs +.piolibdeps +.clang_complete +.gcc-flags.json diff --git a/oliver/dr_desk/dr_desk.ino b/oliver/dr_desk/dr_desk.ino new file mode 100644 index 0000000..0ff13e2 --- /dev/null +++ b/oliver/dr_desk/dr_desk.ino @@ -0,0 +1,286 @@ +#include +#include +#include +#include +#include +#include "secrets.h" + +const char* autoconf_ssid = AUTOCONF_SSID; //AP name for WiFi setup AP which your ESP will open when not able to connect to other WiFi +const char* autoconf_pwd = AUTOCONF_PASSWORD; // AP password so noone else can connect to the ESP in case your router fails +const char* mqtt_server = "192.168.1.2"; //MQTT Server IP, your home MQTT server eg Mosquitto on RPi, or some public MQTT +const int mqtt_port = 1883; //MQTT Server PORT, default is 1883 but can be anything. + +const char* mqtt_pingall_sub = "home/pingall"; +const char* mqtt_pingall_pub = "home/pingall/response"; + +#define MQTT_BASE "home/diningroom/desk" +const char* mqtt_device_boot = MQTT_BASE "/device"; + +const char* mqtt_mode_sub = MQTT_BASE; +const char* mqtt_mode_pub = MQTT_BASE "/status"; + +const char* mqtt_color_sub = MQTT_BASE "/color"; +const char* mqtt_color_pub = MQTT_BASE "/color/status"; + +const char* mqtt_brightness_sub = MQTT_BASE "/brightness"; +const char* mqtt_brightness_pub = MQTT_BASE "/brightness/status"; + +#define RGB_PIN 2 +#define RGB_NUM_LEDS 12 +#define RGB_CHIPSET WS2812B +#define RGB_COLOR_ORDER GRB +#define NUM(a) (sizeof(a) / sizeof(*a)) + +WiFiClient espClient; +PubSubClient client(espClient); +char convBuffer[10]; +CRGB leds[RGB_NUM_LEDS]; + +void switchMode(struct mode *mode); +void modeOff(); +void modeSolid(); +void modeRainbow(); +void modeRainbowFast(); +void modeStrobo(); + +struct mode { + const char *name; + void (*func)(); +}; + +struct mode modes[] = { + { "off", modeOff }, + { "solid", modeSolid }, + { "rainbow", modeRainbow }, + { "rainbowfast", modeRainbowFast }, + { "strobo", modeStrobo }, +}; + +struct +{ + struct mode *mode = &modes[0]; + uint32_t color = CRGB::Red; + uint8_t brightness = 204; // 80% +} set; + +struct +{ + uint8_t brightness; + bool idle = false; +} current; + +void setup() +{ + Serial.begin(115200); + pinMode(BUILTIN_LED, OUTPUT); + + FastLED.addLeds(leds, RGB_NUM_LEDS); + current.brightness = set.brightness; + // update leds + set.mode->func(); + FastLED.show(); + + WiFiManager wifiManager; + wifiManager.autoConnect(autoconf_ssid, autoconf_pwd); + + setup_ota(); + + client.setServer(mqtt_server, mqtt_port); + client.setCallback(callback); + + digitalWrite(BUILTIN_LED, HIGH); //Turn off led as default +} + +void setup_ota() +{ + // Set OTA Password, and change it in platformio.ini + ArduinoOTA.setPassword(OTA_PASSWORD); + ArduinoOTA.onStart([]() {}); + ArduinoOTA.onEnd([]() {}); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {}); + ArduinoOTA.onError([](ota_error_t error) + { + if (error == OTA_AUTH_ERROR); // Auth failed + else if (error == OTA_BEGIN_ERROR); // Begin failed + else if (error == OTA_CONNECT_ERROR); // Connect failed + else if (error == OTA_RECEIVE_ERROR); // Receive failed + else if (error == OTA_END_ERROR); // End failed + }); + ArduinoOTA.begin(); +} + +void reconnect() +{ + // Loop until we're reconnected + while (!client.connected()) + { + // Create a random client ID + String clientId = "ESP8266Client-"; + clientId += String(random(0xffff), HEX); + + // Attempt to connect + if (client.connect(clientId.c_str())) + { + // Once connected, publish an announcement... + client.publish(mqtt_device_boot, "connected"); + // ... and resubscribe + client.subscribe(mqtt_pingall_sub); + + // publish states + Serial.println(mqtt_mode_sub); + client.subscribe(mqtt_mode_sub); + client.publish(mqtt_mode_pub, set.mode->name, true); + + Serial.println(mqtt_color_sub); + client.subscribe(mqtt_color_sub); + itoa(set.color, convBuffer, 10); + client.publish(mqtt_color_pub, convBuffer, true); + + Serial.println(mqtt_brightness_sub); + client.subscribe(mqtt_brightness_sub); + itoa(map(set.brightness, 0, 255, 0, 100), convBuffer, 10); + client.publish(mqtt_brightness_pub, convBuffer, true); + } + else + { + // Wait 5 seconds before retrying + delay(5000); + } + } +} + +void callback(char *topic, uint8_t *payload, unsigned int length) +{ + uint8_t c_payload[length]; + memcpy(c_payload, payload, length); + c_payload[length] = '\0'; + + if (strcmp(topic, mqtt_pingall_sub) == 0) + { + blink(); + client.publish(mqtt_pingall_pub, + "{\"diningroom_desk\":\"connected\"}"); + } + else if (strcmp(topic, mqtt_mode_sub) == 0) + { + for (uint8_t i = 0; i < NUM(modes); ++i) + { + if (strcmp(modes[i].name, (char *)c_payload) != 0) + continue; + switchMode(&modes[i]); + break; + } + } + else if (strcmp(topic, mqtt_color_sub) == 0) + { + // switch from OFF to SOLID + if (set.mode == &modes[0]) + switchMode(&modes[1]); + + set.color = atoi((char *)c_payload); + current.idle = false; + itoa(set.color, convBuffer, 10); + client.publish(mqtt_color_pub, convBuffer, true); + } + else if (strcmp(topic, mqtt_brightness_sub) == 0) + { + set.brightness = map(atoi((char *)c_payload), 0, 100, 0, 255); + current.idle = false; + itoa(map(set.brightness, 0, 255, 0, 100), convBuffer, 10); + client.publish(mqtt_brightness_pub, convBuffer, true); + } +} + +void blink() +{ + //Blink on received MQTT message + digitalWrite(BUILTIN_LED, LOW); + delay(25); + digitalWrite(BUILTIN_LED, HIGH); +} + +void calcBrightness() +{ + #define FADE_STEP 10 + if (current.brightness == set.brightness) + return; + int fadeAmount = set.brightness - current.brightness; + if (abs(fadeAmount) > FADE_STEP) + fadeAmount = (fadeAmount > 0) ? FADE_STEP : -FADE_STEP; + current.brightness += fadeAmount; +} + +void switchMode(struct mode *mode) +{ + if (set.mode == mode) + return; + Serial.print("Switching mode to "); + Serial.println(mode->name); + set.mode = mode; + current.idle = false; + client.publish(mqtt_mode_pub, set.mode->name, true); +} + +void modeOff() +{ + fill_solid(leds, RGB_NUM_LEDS, CRGB::Black); + current.idle = true; +} + +void modeSolid() +{ + fill_solid(leds, RGB_NUM_LEDS, set.color); + calcBrightness(); + nscale8_video(leds, RGB_NUM_LEDS, current.brightness); + current.idle = (current.brightness == set.brightness); +} + +void modeRainbow() +{ + static CRGBPalette16 palette = RainbowColors_p; + static uint8_t hue = 0; + calcBrightness(); + for (int i = 0; i < RGB_NUM_LEDS; ++i) + leds[i] = ColorFromPalette(palette, hue, current.brightness); + hue++; +} + +void modeRainbowFast() +{ + static CRGBPalette16 palette = RainbowColors_p; + static uint8_t hue = 0; + calcBrightness(); + for (int i = 0; i < RGB_NUM_LEDS; ++i) + leds[i] = ColorFromPalette(palette, hue, current.brightness); + hue+=5; +} + +void modeStrobo() +{ + static bool state = 0; + if (set.color == CRGB::Black) + return; + fill_solid(leds, RGB_NUM_LEDS, (state) ? set.color : CRGB::Black); + calcBrightness(); + nscale8_video(leds, RGB_NUM_LEDS, current.brightness); + state = !state; +} + +void loop() +{ + if (!client.connected()) + reconnect(); + client.loop(); + ArduinoOTA.handle(); + + EVERY_N_MILLISECONDS(100) + { + if (!current.idle) + { + set.mode->func(); + FastLED.show(); + } + if (!current.idle && current.brightness == 0) + current.idle = true; + } +} diff --git a/oliver/dr_desk/lib/readme.txt b/oliver/dr_desk/lib/readme.txt new file mode 100644 index 0000000..dbadc3d --- /dev/null +++ b/oliver/dr_desk/lib/readme.txt @@ -0,0 +1,36 @@ + +This directory is intended for the project specific (private) libraries. +PlatformIO will compile them to static libraries and link to executable file. + +The source code of each library should be placed in separate directory, like +"lib/private_lib/[here are source files]". + +For example, see how can be organized `Foo` and `Bar` libraries: + +|--lib +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| |--Foo +| | |- Foo.c +| | |- Foo.h +| |- readme.txt --> THIS FILE +|- platformio.ini +|--src + |- main.c + +Then in `src/main.c` you should use: + +#include +#include + +// rest H/C/CPP code + +PlatformIO will find your libraries automatically, configure preprocessor's +include paths and build them. + +More information about PlatformIO Library Dependency Finder +- http://docs.platformio.org/page/librarymanager/ldf.html diff --git a/oliver/dr_desk/platformio.ini b/oliver/dr_desk/platformio.ini new file mode 100644 index 0000000..0f31fed --- /dev/null +++ b/oliver/dr_desk/platformio.ini @@ -0,0 +1,21 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter, extra scripting +; Upload options: custom port, speed and extra flags +; Library options: dependencies, extra library storages +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/en/stable/projectconf.html + +[platformio] +env_default = nodemcuv2 + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 +framework = arduino +;upload_flags = --port=8266 --auth=ESP8266_PASSWORD +;upload_port = IP (Set fixed IP in your router first!!!) + +[platformio] +lib_dir=/home/manuel/coding/Arduino/libraries diff --git a/oliver/dr_desk/src/dr_desk.ino b/oliver/dr_desk/src/dr_desk.ino new file mode 120000 index 0000000..0cdf13b --- /dev/null +++ b/oliver/dr_desk/src/dr_desk.ino @@ -0,0 +1 @@ +../dr_desk.ino \ No newline at end of file -- cgit v1.2.3