diff --git a/platformio.ini b/platformio.ini
index ce57477..bb8fa86 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -9,7 +9,7 @@
; http://docs.platformio.org/page/projectconf.html
[platformio]
-env_default = build
+env_default = illucat
[common]
framework = arduino
@@ -66,4 +66,14 @@ upload_speed = ${common.upload_speed}
monitor_baud = ${common.monitor_baud}
framework = ${common.framework}
lib_deps = ${common.lib_deps}
- PubSubClient
\ No newline at end of file
+ PubSubClient
+
+[env:illucat]
+src_filter = +<*> - - +
+platform = ${common.platform}
+board = ${common.board}
+upload_speed = ${common.upload_speed}
+monitor_baud = ${common.monitor_baud}
+framework = ${common.framework}
+lib_deps = ${common.lib_deps}
+ Adafruit NeoPixel
\ No newline at end of file
diff --git a/src/examples/button/Button.h b/src/examples/button/Button.h
new file mode 100644
index 0000000..a8fa611
--- /dev/null
+++ b/src/examples/button/Button.h
@@ -0,0 +1,45 @@
+ #ifndef __MESH_APP__
+#define __MESH_APP__
+
+#include
+#include
+#include
+
+using namespace std;
+using namespace std::placeholders;
+
+class Button : public Sprocket {
+ public:
+ Task btnTask;
+ MeshNet* net;
+ int pin;
+ MeshApp(SprocketConfig cfg) : Sprocket(cfg) {}
+ Sprocket* activate(Scheduler* scheduler, Network* network) {
+ pinMode(D2, INPUT_PULLUP);
+ net = static_cast(network);
+ net->mesh.onReceive(bind(&MeshApp::receivedCallback,this, _1, _2));
+ someTask.set(TASK_MILLISECOND * 50, TASK_FOREVER,
+ bind(&MeshApp::readPin, this, net));
+ scheduler->addTask(btnTask);
+ btnTask.enable();
+ } using Sprocket::activate;
+
+ void readPin(MeshNet* network){
+ if(digitalRead(pin)){
+ network->broadcast("{ \"pressed \": 1 }");
+ }
+ }
+
+ void receivedCallback( uint32_t from, String &msg ) {
+ Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());
+ // respond in receive callback can cause an endless loop when all nodes run the same firmware
+ //String foo = String("cheerz back to ") + String(from);
+ //net->broadcast(foo);
+ }
+ void loop() {
+ net->update();
+ scheduler.execute();
+ }
+};
+
+#endif
\ No newline at end of file
diff --git a/src/examples/button/config.h b/src/examples/button/config.h
new file mode 100644
index 0000000..c27cb09
--- /dev/null
+++ b/src/examples/button/config.h
@@ -0,0 +1,25 @@
+#ifndef __MESH_CONFIG__
+#define __MESH_CONFIG__
+
+// Scheduler config
+#define _TASK_SLEEP_ON_IDLE_RUN
+#define _TASK_STD_FUNCTION
+
+// Chip config
+#define SERIAL_BAUD_RATE 115200
+#define STARTUP_DELAY 3000
+
+// Mesh config
+#define STATION_MODE 0
+#define WIFI_CHANNEL 11
+#define MESH_PORT 5555
+#define MESH_PREFIX "whateverYouLike"
+#define MESH_PASSWORD "somethingSneaky"
+#define STATION_SSID "Th1ngs4P"
+#define STATION_PASSWORD "th3r31sn0sp00n"
+#define HOSTNAME "mesh-node"
+#define MESH_DEBUG_TYPES ERROR | STARTUP | CONNECTION
+
+#define BUTTON_PIN D2
+
+#endif
\ No newline at end of file
diff --git a/src/examples/button/main.cpp b/src/examples/button/main.cpp
new file mode 100644
index 0000000..655fbbd
--- /dev/null
+++ b/src/examples/button/main.cpp
@@ -0,0 +1,20 @@
+#include "config.h"
+#include "MeshNet.h"
+#include "MeshApp.h"
+
+MeshNet net({
+ STATION_MODE, WIFI_CHANNEL,
+ MESH_PORT, MESH_PREFIX, MESH_PASSWORD,
+ STATION_SSID, STATION_PASSWORD, HOSTNAME,
+ MESH_DEBUG_TYPES
+});
+MeshApp sprocket({ STARTUP_DELAY, SERIAL_BAUD_RATE });
+
+void setup() {
+ sprocket.join(net);
+}
+
+void loop() {
+ sprocket.loop();
+ yield();
+}
\ No newline at end of file
diff --git a/src/examples/illucat/Illucat.h b/src/examples/illucat/Illucat.h
new file mode 100644
index 0000000..0991f6c
--- /dev/null
+++ b/src/examples/illucat/Illucat.h
@@ -0,0 +1,45 @@
+#ifndef __MESH_APP__
+#define __MESH_APP__
+
+#include
+#include
+#include
+#include "NeoPattern.h"
+
+using namespace std;
+using namespace std::placeholders;
+
+struct NeoPixelConfig {
+ int pin;
+ int length;
+};
+
+class Illucat : public Sprocket {
+ public:
+ MeshNet* net;
+ NeoPattern* pixels;
+ Illucat(SprocketConfig cfg, NeoPixelConfig pixelCfg) : Sprocket(cfg) {
+ pixels = new NeoPattern(pixelCfg.length, pixelCfg.pin, NEO_GRB + NEO_KHZ800, [](int pixels){});
+ }
+ Sprocket* activate(Scheduler* scheduler, Network* network) {
+ net = static_cast(network);
+ net->mesh.onReceive(bind(&Illucat::messageReceived,this, _1, _2));
+ // TODO default rainbow task
+ } using Sprocket::activate;
+
+ void messageReceived( uint32_t from, String &msg ) {
+ Serial.printf("illucat: received from %u msg=%s\n", from, msg.c_str());
+ setHexColor(msg.c_str());
+ }
+ void setHexColor(const char *hex){
+ int r, g, b;
+ sscanf(hex, "%02x%02x%02x", &r, &g, &b);
+ pixels->ColorSet(pixels->Color(r,g,b));
+ }
+ void loop() {
+ net->update();
+ scheduler.execute();
+ }
+};
+
+#endif
\ No newline at end of file
diff --git a/src/examples/illucat/NeoPattern.h b/src/examples/illucat/NeoPattern.h
new file mode 100644
index 0000000..f2b1a58
--- /dev/null
+++ b/src/examples/illucat/NeoPattern.h
@@ -0,0 +1,304 @@
+#ifndef __NeoPattern_H_INCLUDED__
+#define __NeoPattern_H_INCLUDED__
+
+#include
+
+/**
+ * NeoPattern by Bill Earl
+ * https://learn.adafruit.com/multi-tasking-the-arduino-part-3/overview
+ */
+
+// Pattern types supported:
+enum pattern { NONE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE };
+// Patern directions supported:
+enum direction { FORWARD, REVERSE };
+
+// NeoPattern Class - derived from the Adafruit_NeoPixel class
+class NeoPattern : public Adafruit_NeoPixel
+{
+ public:
+
+ // Member Variables:
+ pattern ActivePattern; // which pattern is running
+ direction Direction; // direction to run the pattern
+
+ unsigned long Interval; // milliseconds between updates
+ unsigned long lastUpdate; // last update of position
+
+ uint32_t Color1, Color2; // What colors are in use
+ uint16_t TotalSteps; // total number of steps in the pattern
+ uint16_t Index; // current step within the pattern
+ uint16_t completed = 0;
+
+ void (*OnComplete)(int); // Callback on completion of pattern
+
+ // Constructor - calls base-class constructor to initialize strip
+ NeoPattern(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)(int))
+ :Adafruit_NeoPixel(pixels, pin, type)
+ {
+ OnComplete = callback;
+ }
+
+ // Update the pattern
+ void Update()
+ {
+ if((millis() - lastUpdate) > Interval) // time to update
+ {
+ lastUpdate = millis();
+ switch(ActivePattern)
+ {
+ case RAINBOW_CYCLE:
+ RainbowCycleUpdate();
+ break;
+ case THEATER_CHASE:
+ TheaterChaseUpdate();
+ break;
+ case COLOR_WIPE:
+ ColorWipeUpdate();
+ break;
+ case SCANNER:
+ ScannerUpdate();
+ break;
+ case FADE:
+ FadeUpdate();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ // Increment the Index and reset at the end
+ void Increment()
+ {
+ completed = 0;
+ if (Direction == FORWARD)
+ {
+ Index++;
+ if (Index >= TotalSteps)
+ {
+ Index = 0;
+ if (OnComplete != NULL)
+ {
+ completed = 1;
+ OnComplete(numPixels()); // call the comlpetion callback
+ }
+ }
+ }
+ else // Direction == REVERSE
+ {
+ --Index;
+ if (Index <= 0)
+ {
+ Index = TotalSteps-1;
+ if (OnComplete != NULL)
+ {
+ completed = 1;
+ OnComplete(numPixels()); // call the comlpetion callback
+ }
+ }
+ }
+ }
+
+ // Reverse pattern direction
+ void Reverse()
+ {
+ if (Direction == FORWARD)
+ {
+ Direction = REVERSE;
+ Index = TotalSteps-1;
+ }
+ else
+ {
+ Direction = FORWARD;
+ Index = 0;
+ }
+ }
+
+ // Initialize for a RainbowCycle
+ void RainbowCycle(uint8_t interval, direction dir = FORWARD)
+ {
+ ActivePattern = RAINBOW_CYCLE;
+ Interval = interval;
+ TotalSteps = 255;
+ Index = 0;
+ Direction = dir;
+ }
+
+ // Update the Rainbow Cycle Pattern
+ void RainbowCycleUpdate()
+ {
+ for(int i=0; i< numPixels(); i++)
+ {
+ setPixelColor(i, Wheel(((i * 256 / numPixels()) + Index) & 255));
+ }
+ show();
+ Increment();
+ }
+
+ // Initialize for a Theater Chase
+ void TheaterChase(uint32_t color1, uint32_t color2, uint16_t interval, direction dir = FORWARD)
+ {
+ ActivePattern = THEATER_CHASE;
+ Interval = interval;
+ TotalSteps = numPixels();
+ Color1 = color1;
+ Color2 = color2;
+ Index = 0;
+ Direction = dir;
+ }
+
+ // Update the Theater Chase Pattern
+ void TheaterChaseUpdate()
+ {
+ for(int i=0; i< numPixels(); i++)
+ {
+ if ((i + Index) % 3 == 0)
+ {
+ setPixelColor(i, Color1);
+ }
+ else
+ {
+ setPixelColor(i, Color2);
+ }
+ }
+ show();
+ Increment();
+ }
+
+ // Initialize for a ColorWipe
+ void ColorWipe(uint32_t color, uint8_t interval, direction dir = FORWARD)
+ {
+ ActivePattern = COLOR_WIPE;
+ Interval = interval;
+ TotalSteps = numPixels();
+ Color1 = color;
+ Index = 0;
+ Direction = dir;
+ }
+
+ // Update the Color Wipe Pattern
+ void ColorWipeUpdate()
+ {
+ setPixelColor(Index, Color1);
+ show();
+ Increment();
+ }
+
+ // Initialize for a SCANNNER
+ void Scanner(uint32_t color1, uint8_t interval)
+ {
+ ActivePattern = SCANNER;
+ Interval = interval;
+ TotalSteps = (numPixels() - 1) * 2;
+ Color1 = color1;
+ Index = 0;
+ }
+
+ // Update the Scanner Pattern
+ void ScannerUpdate()
+ {
+ for (int i = 0; i < numPixels(); i++)
+ {
+ if (i == Index) // Scan Pixel to the right
+ {
+ setPixelColor(i, Color1);
+ }
+ else if (i == TotalSteps - Index) // Scan Pixel to the left
+ {
+ setPixelColor(i, Color1);
+ }
+ else // Fading tail
+ {
+ setPixelColor(i, DimColor(getPixelColor(i)));
+ }
+ }
+ show();
+ Increment();
+ }
+
+ // Initialize for a Fade
+ void Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD)
+ {
+ ActivePattern = FADE;
+ Interval = interval;
+ TotalSteps = steps;
+ Color1 = color1;
+ Color2 = color2;
+ Index = 0;
+ Direction = dir;
+ }
+
+ // Update the Fade Pattern
+ void FadeUpdate()
+ {
+ // Calculate linear interpolation between Color1 and Color2
+ // Optimise order of operations to minimize truncation error
+ uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps;
+ uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps;
+ uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps;
+
+ ColorSet(Color(red, green, blue));
+ show();
+ Increment();
+ }
+
+ // Calculate 50% dimmed version of a color (used by ScannerUpdate)
+ uint32_t DimColor(uint32_t color)
+ {
+ // Shift R, G and B components one bit to the right
+ uint32_t dimColor = Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1);
+ return dimColor;
+ }
+
+ // Set all pixels to a color (synchronously)
+ void ColorSet(uint32_t color)
+ {
+ for (int i = 0; i < numPixels(); i++)
+ {
+ setPixelColor(i, color);
+ }
+ show();
+ }
+
+ // Returns the Red component of a 32-bit color
+ uint8_t Red(uint32_t color)
+ {
+ return (color >> 16) & 0xFF;
+ }
+
+ // Returns the Green component of a 32-bit color
+ uint8_t Green(uint32_t color)
+ {
+ return (color >> 8) & 0xFF;
+ }
+
+ // Returns the Blue component of a 32-bit color
+ uint8_t Blue(uint32_t color)
+ {
+ return color & 0xFF;
+ }
+
+ // Input a value 0 to 255 to get a color value.
+ // The colours are a transition r - g - b - back to r.
+ uint32_t Wheel(byte WheelPos)
+ {
+ WheelPos = 255 - WheelPos;
+ if(WheelPos < 85)
+ {
+ return Color(255 - WheelPos * 3, 0, WheelPos * 3);
+ }
+ else if(WheelPos < 170)
+ {
+ WheelPos -= 85;
+ return Color(0, WheelPos * 3, 255 - WheelPos * 3);
+ }
+ else
+ {
+ WheelPos -= 170;
+ return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
+ }
+ }
+};
+
+#endif
\ No newline at end of file
diff --git a/src/examples/illucat/config.h b/src/examples/illucat/config.h
new file mode 100644
index 0000000..f099c01
--- /dev/null
+++ b/src/examples/illucat/config.h
@@ -0,0 +1,29 @@
+#ifndef __MESH_CONFIG__
+#define __MESH_CONFIG__
+
+// Scheduler config
+#define _TASK_SLEEP_ON_IDLE_RUN
+#define _TASK_STD_FUNCTION
+
+// Chip config
+#define SERIAL_BAUD_RATE 115200
+#define STARTUP_DELAY 3000
+
+// Mesh config
+#define STATION_MODE 0
+#define WIFI_CHANNEL 11
+#define MESH_PORT 5555
+#define MESH_PREFIX "whateverYouLike"
+#define MESH_PASSWORD "somethingSneaky"
+#define STATION_SSID "Th1ngs4P"
+#define STATION_PASSWORD "th3r31sn0sp00n"
+#define HOSTNAME "mesh-node"
+#define MESH_DEBUG_TYPES ERROR | STARTUP | CONNECTION
+
+// illucat
+#define LED_STRIP_PIN D2
+#define LED_STRIP_LENGTH 8
+#define LED_STRIP_BRIGHTNESS 32
+
+
+#endif
\ No newline at end of file
diff --git a/src/examples/illucat/main.cpp b/src/examples/illucat/main.cpp
new file mode 100644
index 0000000..9c12dbf
--- /dev/null
+++ b/src/examples/illucat/main.cpp
@@ -0,0 +1,21 @@
+#include "config.h"
+#include "MeshNet.h"
+#include "Illucat.h"
+
+MeshNet net({
+ STATION_MODE, WIFI_CHANNEL,
+ MESH_PORT, MESH_PREFIX, MESH_PASSWORD,
+ STATION_SSID, STATION_PASSWORD, HOSTNAME,
+ MESH_DEBUG_TYPES
+});
+Illucat sprocket({ STARTUP_DELAY, SERIAL_BAUD_RATE },
+ { LED_STRIP_PIN, LED_STRIP_LENGTH });
+
+void setup() {
+ sprocket.join(net);
+}
+
+void loop() {
+ sprocket.loop();
+ yield();
+}
\ No newline at end of file