Merge branch 'develop' into 'master'

merge develop into master

See merge request wirelos/sprocket-core!2
This commit is contained in:
2018-07-02 07:23:13 +00:00
27 changed files with 776 additions and 139 deletions

View File

@@ -3,18 +3,13 @@ stages:
cache:
paths:
- firmware
- .piolibdeps
before_script:
- "pip install -U platformio"
firmware-build:
build-examples:
stage: build
image: python:2.7-stretch
image: registry.gitlab.com/wirelos/contraption-pipeline/platformio:v1
script:
- platformio lib --global install painlessMesh ArduinoJson TaskScheduler PubSubClient ESPAsyncTCP AsyncTCP "ESP Async WebServer"
- platformio ci --lib="." --board=esp12e src/examples/basic/
- platformio ci --lib="." --board=esp12e src/examples/mesh/
artifacts:
paths:
- .pioenvs/esp12e/firmware.bin
- .pioenvs/esp12e/spiffs.bin
- platformio ci --lib="." --board=esp12e src/examples/mqttBridge/

View File

@@ -1,6 +1,6 @@
{
"terminal.integrated.env.linux": {
"PATH": "/home/master/.platformio/penv/bin:/home/master/.platformio/penv:/home/master/bin:/home/master/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin",
"PATH": "/home/master/.platformio/penv/bin:/home/master/.platformio/penv:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl",
"PLATFORMIO_CALLER": "vscode"
},
"files.associations": {

8
README.md Normal file
View File

@@ -0,0 +1,8 @@
# InterCat
Our entry for the make-zürich 2018 teacher's calling challenge.
Unfortunately we couldn't get as far as we wanted, so there is no documentation or anything usefull for the uninitiated.
If you want more information, please contact me directly.
Maybe we will follow up on the project and add more information, in case someone is interested.
Anyway: all source code is available in the git repository.
The different mesh node types can be checked out from the branches.

View File

@@ -1,7 +1,7 @@
{
"name": "sprocket-core",
"keywords": "esp8266, sprocket, stack",
"description": "Core stack for sprockets",
"description": "Core stack for Sprockets",
"authors":
{
"name": "Patrick Balsiger",
@@ -14,5 +14,12 @@
"url": "https://gitlab.com/wirelos/sprocket-core/"
},
"frameworks": "arduino",
"platforms": "espressif8266"
"platforms": "espressif8266",
"examples": "examples/*",
"export": {
"exclude":
[
"firmware/"
]
}
}

View File

@@ -9,7 +9,7 @@
; http://docs.platformio.org/page/projectconf.html
[platformio]
env_default = meshMqttBridge
env_default = button
[common]
framework = arduino
@@ -22,6 +22,7 @@ lib_deps =
ESP Async WebServer
ESPAsyncTCP
TaskScheduler
painlessMesh
[env:build]
src_filter = +<*> -<examples/>
@@ -34,12 +35,13 @@ upload_speed = ${common.upload_speed}
monitor_baud = ${common.monitor_baud}
framework = ${common.framework}
lib_deps = ${common.lib_deps}
#build_flags = -DLED_PIN=2 -g
;upload_port = /dev/ttyUSB0
;upload_port = 192.168.1.168
[env:basic]
src_filter = +<*> +<examples/basic/> -<examples/mesh/> -<examples/mqttBridge/>
src_filter = +<*> -<examples/> -<firmware/> +<examples/basic/>
platform = ${common.platform}
board = ${common.board}
upload_speed = ${common.upload_speed}
@@ -48,22 +50,39 @@ framework = ${common.framework}
lib_deps = ${common.lib_deps}
[env:mesh]
src_filter = +<*> +<examples/mesh/> -<examples/basic/> -<examples/mqttBridge/>
src_filter = +<*> -<examples/> -<firmware/> +<examples/mesh/>
platform = ${common.platform}
board = ${common.board}
upload_speed = ${common.upload_speed}
monitor_baud = ${common.monitor_baud}
framework = ${common.framework}
lib_deps = ${common.lib_deps}
painlessMesh
[env:meshMqttBridge]
src_filter = +<*> +<examples/mesh/> -<examples/basic/> -<examples/mesh/>
src_filter = +<*> -<examples/> -<firmware/> +<examples/mqttBridge/>
platform = espressif8266
board = esp12e
upload_speed = ${common.upload_speed}
monitor_baud = ${common.monitor_baud}
framework = ${common.framework}
lib_deps = ${common.lib_deps}
painlessMesh
PubSubClient
PubSubClient
[env:illucat]
src_filter = +<*> -<examples/> -<firmware/> +<examples/illucat/>
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
[env:button]
src_filter = +<*> -<examples/> -<firmware/> +<examples/button/>
platform = ${common.platform}
board = ${common.board}
upload_speed = ${common.upload_speed}
monitor_baud = ${common.monitor_baud}
framework = ${common.framework}
lib_deps = ${common.lib_deps}

53
src/MeshNet.cpp Normal file
View File

@@ -0,0 +1,53 @@
#include "MeshNet.h"
MeshNet::MeshNet(MeshConfig cfg) : Network() {
config = cfg;
}
Network* MeshNet::init(){
Serial.println("init mesh");
//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
mesh.setDebugMsgTypes( config.debugTypes );
mesh.init( config.meshSSID, config.meshPassword, scheduler, config.meshPort, WIFI_AP_STA, config.channel );
//mesh.onReceive(bind(&MeshNet::receivedCallback,this, _1, _2));
mesh.onNewConnection(bind(&MeshNet::newConnectionCallback, this, _1));
mesh.onChangedConnections(bind(&MeshNet::changedConnectionCallback, this));
mesh.onNodeTimeAdjusted(bind(&MeshNet::nodeTimeAdjustedCallback, this, _1));
if(config.stationMode){
Serial.println("connect station");
mesh.stationManual(config.stationSSID, config.stationPassword);
mesh.setHostname(config.hostname);
}
return this;
}
void MeshNet::sendTo(uint32_t target, String msg){
mesh.sendSingle(target, msg);
}
void MeshNet::broadcast(String msg){
mesh.sendBroadcast(msg);
}
void MeshNet::update(){
// only needed when no scheduler was passed to mesh.init
mesh.update();
}
void MeshNet::receivedCallback( uint32_t from, String &msg ) {
Serial.printf("--> Received from %u msg=%s\n", from, msg.c_str());
}
void MeshNet::newConnectionCallback(uint32_t nodeId) {
Serial.printf("--> New Connection, nodeId = %u\n", nodeId);
}
void MeshNet::changedConnectionCallback() {
Serial.printf("--> Changed connections %s\n",mesh.subConnectionJson().c_str());
}
void MeshNet::nodeTimeAdjustedCallback(int32_t offset) {
Serial.printf("--> Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

View File

@@ -4,6 +4,7 @@
#include <painlessMesh.h>
#include <WiFiClient.h>
#include "Network.h"
using namespace std;
using namespace std::placeholders;
@@ -22,59 +23,18 @@ struct MeshConfig {
class MeshNet : public Network {
public:
painlessMesh mesh;
MeshConfig config;
MeshNet(MeshConfig cfg) : Network() {
config = cfg;
}
Network* init(){
Serial.println("init mesh");
//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
mesh.setDebugMsgTypes( config.debugTypes );
mesh.init( config.meshSSID, config.meshPassword, scheduler, config.meshPort, WIFI_AP_STA, config.channel );
//mesh.onReceive(bind(&MeshNet::receivedCallback,this, _1, _2));
mesh.onNewConnection(bind(&MeshNet::newConnectionCallback, this, _1));
mesh.onChangedConnections(bind(&MeshNet::changedConnectionCallback, this));
mesh.onNodeTimeAdjusted(bind(&MeshNet::nodeTimeAdjustedCallback, this, _1));
if(config.stationMode){
Serial.println("connect station");
mesh.stationManual(config.stationSSID, config.stationPassword);
mesh.setHostname(config.hostname);
}
return this;
}
Network* connect(){
return this;
}
void broadcast(String msg){
mesh.sendBroadcast(msg);
}
void update(){
// only needed when no scheduler was passed to mesh.init
mesh.update();
}
void receivedCallback( uint32_t from, String &msg ) {
Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());
}
void newConnectionCallback(uint32_t nodeId) {
id = nodeId;
Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
}
void changedConnectionCallback() {
Serial.printf("Changed connections %s\n",mesh.subConnectionJson().c_str());
}
void nodeTimeAdjustedCallback(int32_t offset) {
Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}
MeshNet(MeshConfig cfg);
Network* init();
void broadcast(String msg);
void sendTo(uint32_t target, String msg);
void update(); // only needed when no scheduler was passed to mesh.init
void receivedCallback( uint32_t from, String &msg );
void newConnectionCallback(uint32_t nodeId);
void changedConnectionCallback();
void nodeTimeAdjustedCallback(int32_t offset);
};
#endif

View File

@@ -23,8 +23,7 @@ Sprocket* Sprocket::join(Network& net){
Serial.println("join network");
net.init(&scheduler);
net.connect();
activate(&scheduler, &net);
return this;
return activate(&scheduler, &net);
}
Sprocket* Sprocket::addTask(Task& tsk){

View File

@@ -20,11 +20,11 @@ class Sprocket {
Sprocket(SprocketConfig);
Sprocket* init(SprocketConfig);
Sprocket* join(Network&);
Sprocket* addTask(Task&); // REMOVE ??
Sprocket* addTask(Task&);
virtual void loop();
virtual Sprocket* activate();
virtual Sprocket* activate(Scheduler*) {}
virtual Sprocket* activate(Scheduler*, Network*) {}
virtual Sprocket* activate(Scheduler*) { return this; }
virtual Sprocket* activate(Scheduler*, Network*) { return this; }
};
#endif

View File

@@ -3,7 +3,6 @@
//#include "Sprocket.h"
#include <ESPAsyncWebServer.h>
#include <TaskSchedulerDeclarations.h>
#include <Sprocket.h>
using namespace std;
@@ -12,7 +11,7 @@ using namespace std::placeholders;
class ExampleApp : public Sprocket {
public:
Task someTask;
ExampleApp() {
ExampleApp(SprocketConfig cfg) : Sprocket(cfg) {
Serial.println("joo");
}
Sprocket* activate(Scheduler* scheduler) {

View File

@@ -1,21 +1,13 @@
#define _TASK_SLEEP_ON_IDLE_RUN
#define _TASK_STD_FUNCTION
#include <TaskScheduler.h>
#include "ExampleApp.h"
#define SERIAL_BAUD_RATE 115200
#define STARTUP_DELAY 3000
SprocketConfig config = { STARTUP_DELAY, SERIAL_BAUD_RATE };
#include "ExampleApp.h"
ExampleApp sprocket;
ExampleApp sprocket({ STARTUP_DELAY, SERIAL_BAUD_RATE });
void setup() {
delay(STARTUP_DELAY);
sprocket.init(config);
sprocket.activate();
}

View File

@@ -0,0 +1,47 @@
#ifndef __MESH_APP__
#define __MESH_APP__
#include <painlessMesh.h>
#include <Sprocket.h>
#include <MeshNet.h>
using namespace std;
using namespace std::placeholders;
class Button : public Sprocket {
public:
Task btnTask;
MeshNet* net;
int pin;
Button(SprocketConfig cfg) : Sprocket(cfg) {}
Sprocket* activate(Scheduler* scheduler, Network* network) {
pin = D2;
pinMode(pin, INPUT_PULLUP);
net = static_cast<MeshNet*>(network);
net->mesh.onReceive(bind(&Button::receivedCallback,this, _1, _2));
btnTask.set(TASK_MILLISECOND * 500, TASK_FOREVER,
bind(&Button::readPin, this, net));
scheduler->addTask(btnTask);
btnTask.enable();
} using Sprocket::activate;
void readPin(MeshNet* network){
if(digitalRead(pin)){
Serial.println("btn pressed");
network->broadcast("EE1B2E");
}
}
void receivedCallback( uint32_t from, String &msg ) {
Serial.printf("button: 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

View File

@@ -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

View File

@@ -0,0 +1,20 @@
#include "config.h"
#include "MeshNet.h"
#include "Button.h"
MeshNet net({
STATION_MODE, WIFI_CHANNEL,
MESH_PORT, MESH_PREFIX, MESH_PASSWORD,
STATION_SSID, STATION_PASSWORD, HOSTNAME,
MESH_DEBUG_TYPES
});
Button sprocket({ STARTUP_DELAY, SERIAL_BAUD_RATE });
void setup() {
sprocket.join(net);
}
void loop() {
sprocket.loop();
yield();
}

View File

@@ -0,0 +1,45 @@
#ifndef __MESH_APP__
#define __MESH_APP__
#include <painlessMesh.h>
#include <Sprocket.h>
#include <MeshNet.h>
#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<MeshNet*>(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

View File

@@ -0,0 +1,304 @@
#ifndef __NeoPattern_H_INCLUDED__
#define __NeoPattern_H_INCLUDED__
#include <Adafruit_NeoPixel.h>
/**
* 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

View File

@@ -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

View File

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

View File

@@ -12,19 +12,19 @@ class MeshApp : public Sprocket {
public:
Task someTask;
MeshNet* net;
MeshApp(SprocketConfig cfg) : Sprocket(cfg) {}
Sprocket* activate(Scheduler* scheduler, Network* network) {
net = static_cast<MeshNet*>(network);
net->mesh.onReceive(bind(&MeshApp::receivedCallback,this, _1, _2));
// add a task that sends stuff to the mesh
someTask.set(TASK_SECOND * 5, TASK_FOREVER,
bind(&MeshApp::advertise, this, net));
bind(&MeshApp::heartbeat, this, net));
scheduler->addTask(someTask);
someTask.enable();
} using Sprocket::activate;
void advertise(MeshNet* network){
String msg = "Hi, my name is " + String(network->id);
void heartbeat(MeshNet* network){
String msg = "{ \"payload \": 1 }";
network->broadcast(msg);
}

View File

@@ -0,0 +1,23 @@
#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
#endif

View File

@@ -1,26 +1,17 @@
#define _TASK_SLEEP_ON_IDLE_RUN
#define _TASK_STD_FUNCTION
#include "Network.h"
#include "config.h"
#include "MeshNet.h"
#include "Sprocket.h"
#include "MeshApp.h"
#define SERIAL_BAUD_RATE 115200
#define STARTUP_DELAY 3000
SprocketConfig config = { STARTUP_DELAY, SERIAL_BAUD_RATE };
MeshNet net;
MeshApp sprocket;
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() {
delay(STARTUP_DELAY);
sprocket.init(config);
sprocket.join(net);
}
void loop() {

View File

@@ -34,16 +34,21 @@ class MqttMeshBridge : public Sprocket {
mqttConfig = cfg;
}
Sprocket* activate(Scheduler* scheduler, Network* network) {
Serial.println("activate MQTT bridge");
net = static_cast<MeshNet*>(network);
net->mesh.onReceive(bind(&MqttMeshBridge::receivedCallback,this, _1, _2));
client = new PubSubClient(mqttConfig.brokerHost, mqttConfig.brokerPort, bind(&MqttMeshBridge::mqttCallback, this, _1, _2, _3), wifiClient);
Sprocket* activate(Scheduler* scheduler){
enableConnectTask(scheduler);
enableProcessTask(scheduler);
return this;
}
Sprocket* activate(Scheduler* scheduler, Network* network) {
Serial.println("activate MQTT bridge");
net = static_cast<MeshNet*>(network);
net->mesh.onReceive(bind(&MqttMeshBridge::receivedCallback,this, _1, _2));
client = new PubSubClient(mqttConfig.brokerHost, mqttConfig.brokerPort, bind(&MqttMeshBridge::mqttCallback, this, _1, _2, _3), wifiClient);
return activate(scheduler);
}
private:
void enableConnectTask(Scheduler* scheduler) {
connectTask.set(TASK_SECOND * 5, TASK_FOREVER, bind(&MqttMeshBridge::connect, this));
scheduler->addTask(connectTask);

View File

@@ -1,30 +1,7 @@
#define _TASK_SLEEP_ON_IDLE_RUN
#define _TASK_STD_FUNCTION
#include <MeshNet.h>
#include "config.h"
#include "MeshNet.h"
#include "MqttMeshBridge.h"
// Chip config
#define SERIAL_BAUD_RATE 115200
#define STARTUP_DELAY 3000
// Mesh config
#define STATION_MODE 1
#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 "mqtt-mesh-bridge"
#define MESH_DEBUG_TYPES ERROR | STARTUP | CONNECTION
// Bridge config
#define MQTT_CLIENT_NAME HOSTNAME
#define MQTT_BROKER "iot.eclipse.org"
#define MQTT_PORT 1883
#define MQTT_TOPIC_ROOT "mesh/"
MeshNet net({
STATION_MODE, WIFI_CHANNEL,
MESH_PORT, MESH_PREFIX, MESH_PASSWORD,

View File

@@ -0,0 +1,29 @@
#ifndef __BRIDGE_CONFIG__
#define __BRIDGE_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 1
#define WIFI_CHANNEL 11
#define MESH_PORT 5555
#define MESH_PREFIX "wirelos_contraption"
#define MESH_PASSWORD "th3r31sn0sp00n"
#define STATION_SSID "Th1ngs4P"
#define STATION_PASSWORD "th3r31sn0sp00n"
#define HOSTNAME "sprocket"
#define MESH_DEBUG_TYPES ERROR | STARTUP | CONNECTION
// Bridge config
#define MQTT_CLIENT_NAME HOSTNAME
#define MQTT_BROKER "citadel.lan"
#define MQTT_PORT 1883
#define MQTT_TOPIC_ROOT "mesh"
#endif

View File

@@ -0,0 +1,38 @@
#ifndef __BASE_SPROCKET__
#define __BASE_SPROCKET__
#include <ESPAsyncWebServer.h>
#include <Sprocket.h>
using namespace std;
using namespace std::placeholders;
// TODO remove someTask and replace with OTA stuff
class BaseSprocket : public Sprocket {
public:
Task someTask;
MeshNet* net;
BaseSprocket(SprocketConfig cfg) : Sprocket(cfg) {
}
Sprocket* activate(Scheduler* scheduler, Network* network) {
net = static_cast<MeshNet*>(network);
net->mesh.onReceive(bind(&BaseSprocket::receivedCallback,this, _1, _2));
// add a task that sends stuff to the mesh
someTask.set(TASK_SECOND * 5, TASK_FOREVER,
bind(&BaseSprocket::heartbeat, this, net));
scheduler->addTask(someTask);
someTask.enable();
} using Sprocket::activate;
void heartbeat(MeshNet* network){
String msg = "{ \"alive \": 1 }";
network->broadcast(msg);
}
virtual void receivedCallback( uint32_t from, String &msg ) {
Serial.printf("RECV %u = %s\n", from, msg.c_str());
}
};
#endif

28
src/firmware/config.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef __BRIDGE_CONFIG__
#define __BRIDGE_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 // 1 = connect to AP using STATION params
#define WIFI_CHANNEL 11
#define MESH_PORT 5555
#define MESH_PREFIX "wirelos_contraption"
#define MESH_PASSWORD "th3r31sn0sp00n"
#define STATION_SSID "Th1ngs4P"
#define STATION_PASSWORD "th3r31sn0sp00n"
#define HOSTNAME "sprocket"
#define MESH_DEBUG_TYPES ERROR | STARTUP | CONNECTION
#define MQTT_CLIENT_NAME HOSTNAME
#define MQTT_BROKER "citadel.lan"
#define MQTT_PORT 1883
#define MQTT_TOPIC_ROOT "mesh"
#endif

23
src/firmware/main.cpp Normal file
View File

@@ -0,0 +1,23 @@
#include "config.h"
#include "MeshNet.h"
#include "BaseSprocket.h"
MeshNet net({
STATION_MODE, WIFI_CHANNEL,
MESH_PORT, MESH_PREFIX, MESH_PASSWORD,
STATION_SSID, STATION_PASSWORD, HOSTNAME,
MESH_DEBUG_TYPES
});
BaseSprocket sprocket(
{ STARTUP_DELAY, SERIAL_BAUD_RATE }
);
void setup() {
sprocket.join(net);
}
void loop() {
sprocket.loop();
yield();
}