19 Commits

Author SHA1 Message Date
499f8447ba foo 2018-12-01 15:49:07 +01:00
7cc4451c1c some nice intro text 2018-11-29 19:17:26 +01:00
Patrick Balsiger
f558a09974 remove redundant section 2018-10-20 16:04:41 +00:00
Patrick Balsiger
fd205348f8 add default password to guide 2018-10-20 16:04:12 +00:00
Patrick Balsiger
9f417340c5 fix typos 2018-10-20 15:59:57 +00:00
Patrick Balsiger
acae6c1b09 simplify enduser setup 2018-10-20 15:54:10 +00:00
a916e542fb change default animation to rainbow 2018-10-09 11:00:41 +02:00
6fc5908761 use release env in ci build 2018-10-07 13:20:24 +02:00
Patrick Balsiger
afd13ca661 Merge branch 'separation' into 'master'
Separation

See merge request 0x1d/illucat!3
2018-10-07 11:14:03 +00:00
Patrick Balsiger
09915ca94b Merge branch 'master' into 'separation'
# Conflicts:
#   data/pixelConfig.json
2018-10-07 11:13:44 +00:00
2a21775524 use illu base, reduce pixel num 2018-10-07 12:58:08 +02:00
0e13508158 set build to default env 2018-10-07 12:44:12 +02:00
75a4e3e94c minimize startup time 2018-10-07 11:47:57 +02:00
b91255fe85 run default animation earlier 2018-10-06 15:48:48 +02:00
207f90d60a separate concerns 2018-10-04 02:34:37 +02:00
0686895f33 add conn timeout to example conf 2018-10-03 22:07:20 +02:00
ffd76acb69 Merge branch 'standalone' into release/1.0.0 2018-10-03 21:59:54 +02:00
77d92155df add ap infos to example conf 2018-10-03 21:24:47 +02:00
2ba0684982 comment out all mesh stuff 2018-09-28 11:09:39 +02:00
13 changed files with 278 additions and 63 deletions

View File

@@ -22,8 +22,8 @@ firmware:
script:
- mv data/example.config.json data/config.json
- pio run -t clean
- pio run
- pio run -t buildfs
- pio run -e release
- pio run -e release -t buildfs
release:
stage: release
@@ -33,8 +33,8 @@ release:
script:
- pip install awscli
- mkdir -p ${PROJECT_NAME}/${CI_COMMIT_TAG}
- mv .pioenvs/build/firmware.bin ${PROJECT_NAME}/${CI_COMMIT_TAG}
- mv .pioenvs/build/spiffs.bin ${PROJECT_NAME}/${CI_COMMIT_TAG}
- mv .pioenvs/release/firmware.bin ${PROJECT_NAME}/${CI_COMMIT_TAG}
- mv .pioenvs/release/spiffs.bin ${PROJECT_NAME}/${CI_COMMIT_TAG}
- aws s3 --endpoint-url=https://$DO_SPACE_ENDPOINT cp ./ s3://$S3_BUCKET_NAME/ --recursive --exclude "*" --include "*.bin"
artifacts:
paths:

23
.vscode/settings.json vendored
View File

@@ -15,6 +15,27 @@
"unordered_map": "cpp",
"vector": "cpp",
"tuple": "cpp",
"utility": "cpp"
"utility": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"exception": "cpp",
"fstream": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"ostream": "cpp",
"numeric": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp"
}
}

View File

@@ -1,9 +1,16 @@
# Illumination-Cat
This is the brain of the the almighty Illumination-Cat.
The Illumination-Cat (short IlluCat) is the collaborative work of several streams, ranging from 3D modeling, electronics and programming.
Originating from the Chaos-Drucker Club with the idea of having
a cool status indicator for 3D printers, the project grew beyond the original idea.
From the software point of view, the IlluCat is the exemplary model of the [Sprocket framework](https://gitlab.com/wirelos/sprocket-lib), implementing the various aspects and possibilities of the framework.
IlluCat can embed several plugins, like web interface, MQTT, IRC or even mesh networking.
As the framework supports easy integration of many available Arduino libraries, IlluCat can be easily customized to your needs. This repository contains some example implementations that you can use to build your own custom cat.
## Resources & Documentation
[3D Model](https://www.thingiverse.com/thing:2974862)
[Installation](https://gitlab.com/0x1d/illucat/blob/master/installation.md)
[API](https://gitlab.com/0x1d/illucat/blob/master/api.md)
[OctoPrint Stuff](https://github.com/FrYakaTKoP/simple-octo-ws2812)
[Sprocket framework](https://gitlab.com/wirelos/sprocket-lib)
[Sprocket plugins](https://gitlab.com/wirelos)

View File

@@ -1,6 +1,9 @@
{
"stationMode": 0,
"hostname": "illucat",
"apSSID": "illucat",
"apPassword": "illumination",
"connectTimeout": 20000,
"stationSSID": "MyWifi",
"stationPassword": "myWifiPassword",
"meshSSID": "illucat",

View File

@@ -1,7 +1,7 @@
{
"pin": 4,
"length": 32,
"length": 8,
"brightness": 64,
"updateInterval": 50,
"updateInterval": 100,
"defaultColor": 100
}

View File

@@ -4,16 +4,14 @@
- download and flash firmware and filesystem
- or: rename example.config.json to config.json, build and upload it yourself
## Enduser Setup
## Enduser Setup (Standalone)
1. Scan for access points
1. connect to illucat access point
1. open web browser and navigate to the gateway IP
1. change stationMode to 1 in the Settings section for connecting the cat to your own AP. leave it 0 to build a mesh.
1. change stationSSID and stationPassword to match your AP settings
1. change the NeoPixel settings according to your hardware. The pin needs to be specified as the pin id of your board, e.g. 4 = D2 on a Wemos D1 Mini.
1. connect to the access point "illucat" with password "illumination"
1. open a web browser and navigate to http://192.168.4.1
1. To connect the cat to your own WiFi, open the "Settings" section and change "stationMode" to 1 and set "stationSSID" and "stationPassword" according to your own access point's credentials
1. submit all changes
1. hit restart under the System section
1. illucat connects to your network and can be reached with http://illucat (or any other configured hostname)
1. open the "System" section and hit "Restart"
1. illucat connects to your network and can be reached through http://illucat (might take some time, depending on your DNS server)
## Install and setup Python
@@ -64,21 +62,6 @@ hint: you can crank the baudrate up to 921600 bps ;)
python -m esptool --port COM11 --baud 115200 write_flash 0x00000 firmware.bin 0x00300000 spiffs.bin
# Configuration after first boot
the esp will build a AP with ssid name **illu** and password **illumination**
when connected browse to **http://illucat**
now you can enter the SSID and Password of your WLAN and set StationMode to 1
then press save and reset the esp)
the Cat should now joined your network
find the ip of your cat in your DHCP table
have fun

View File

@@ -31,6 +31,20 @@ lib_deps =
Adafruit NeoPixel
[env:build]
src_filter = +<*> -<wifiMesh/> +<wifi/>
platform = ${common.platform}
board = ${common.board}
upload_speed = ${common.upload_speed}
monitor_baud = ${common.monitor_baud}
framework = ${common.framework}
build_flags = -Wl,-Teagle.flash.4m1m.ld
-DSPROCKET_PRINT=1
lib_deps = ${common.lib_deps}
https://gitlab.com/wirelos/sprocket-core.git#develop
[env:build-mesh]
src_filter = +<*> +<wifiMesh/> -<wifi/>
platform = ${common.platform}
board = ${common.board}
upload_speed = ${common.upload_speed}
@@ -42,6 +56,7 @@ lib_deps = ${common.lib_deps}
https://gitlab.com/wirelos/sprocket-core.git#develop
[env:release]
src_filter = +<*> -<wifiMesh/> +<wifi/>
platform = ${common.platform}
board = ${common.board}
upload_speed = ${common.upload_speed}
@@ -50,10 +65,11 @@ framework = ${common.framework}
build_flags = -Wl,-Teagle.flash.4m1m.ld
-DSPROCKET_PRINT=0
lib_deps = ${common.lib_deps}
https://gitlab.com/wirelos/sprocket-core.git#master
https://gitlab.com/wirelos/sprocket-core.git#develop
[env:nodemcu]
src_filter = +<*> -<wifiMesh/> +<wifi/>
platform = ${common.platform}
board = nodemcu
upload_speed = ${common.upload_speed}

View File

@@ -1,9 +1,9 @@
#ifndef __MESH_APP__
#define __MESH_APP__
#include <painlessMesh.h>
#include <base/MeshSprocket.h>
#include <TaskScheduler.h>
#include <MeshNet.h>
#include <Sprocket.h>
#include "config.h"
#include "NeoPattern.cpp"
@@ -21,14 +21,15 @@
using namespace std;
using namespace std::placeholders;
class IlluCat : public MeshSprocket {
class IlluCat : public Sprocket {
public:
NeoPattern* pixels;
NeoPatternDto defaultState;
NeoPatternDto state;
AsyncWebServer* server;
AsyncWebSocket* ws;
AsyncWebSocket* wsStream;
//AsyncWebSocket* wsStream;
NeoPixelConfig pixelConfig;
SprocketConfig sprocketConfig;
@@ -37,31 +38,25 @@ class IlluCat : public MeshSprocket {
SprocketMessage currentMessage;
IlluCat(SprocketConfig cfg, OtaConfig otaCfg, WebServerConfig webCfg/* , NeoPixelConfig pixelCfg */) : MeshSprocket(cfg) {
//pixelConfig = pixelCfg;
IlluCat(SprocketConfig cfg, OtaConfig otaCfg, WebServerConfig webCfg) : Sprocket(cfg) {
sprocketConfig = cfg;
otaConfig = otaCfg;
webConfig = webCfg;
pixelConfig.pin = 4;
pixelConfig.length = 8;
pixelConfig.brightness = 32;
pixelConfig.updateInterval = 100;
pixelConfig.defaultColor = 100;
}
virtual void scanningAnimation() {
pixels->Scanner(pixels->Wheel(COLOR_NOT_CONNECTED), pixelConfig.updateInterval);
}
virtual void defaultAnimation() {
String defaultStr = String(defaultState.value);
PIXEL_FNCS[defaultState.mode](pixels, defaultStr.c_str());
pixels->RainbowCycle(pixelConfig.updateInterval);
}
Sprocket* activate(Scheduler* scheduler, Network* network) {
net = static_cast<MeshNet*>(network);
// load config files from SPIFFS
if(SPIFFS.begin()){
pixelConfig.fromFile("/pixelConfig.json");
@@ -73,17 +68,20 @@ class IlluCat : public MeshSprocket {
pixels = new NeoPattern(pixelConfig.length, pixelConfig.pin, NEO_GRB + NEO_KHZ800);
server = new AsyncWebServer(80);
ws = new AsyncWebSocket("/pixel");
wsStream = new AsyncWebSocket("/stream");
//wsStream = new AsyncWebSocket("/stream");
defaultAnimation();
// add plugins
addPlugin(new OtaTcpPlugin(otaConfig));
// TODO add HTTP OTA instead of TCP
//addPlugin(new OtaTcpPlugin(otaConfig));
addPlugin(new WebServerPlugin(webConfig, server));
addPlugin(new WebConfigPlugin(server));
addPlugin(new PixelPlugin(pixelConfig, pixels));
defaultAnimation();
String softApPrt = "SoftAP IP: " + WiFi.softAPIP().toString();
PRINT_MSG(Serial, SPROCKET_TYPE, softApPrt.c_str());
// FIXME move to networking
//String softApPrt = "SoftAP IP: " + WiFi.softAPIP().toString();
//PRINT_MSG(Serial, SPROCKET_TYPE, softApPrt.c_str());
// TODO move to plugin
// setup web stuff
@@ -91,11 +89,11 @@ class IlluCat : public MeshSprocket {
server->on("/pixel/api", HTTP_POST, bind(&IlluCat::patternWebRequestHandler, this, _1));
ws->onEvent(bind(&IlluCat::onWsEvent, this, _1, _2, _3, _4, _5, _6));
server->addHandler(ws);
wsStream->onEvent(bind(&IlluCat::onStream, this, _1, _2, _3, _4, _5, _6));
server->addHandler(wsStream);
//wsStream->onEvent(bind(&IlluCat::onStream, this, _1, _2, _3, _4, _5, _6));
//server->addHandler(wsStream);
return MeshSprocket::activate(scheduler, network);
} using MeshSprocket::activate;
return Sprocket::activate(scheduler, network);
} using Sprocket::activate;
// TODO move to utils
String getRequestParameterOrDefault(AsyncWebServerRequest *request, String param, String defaultValue, bool isPost = true){
@@ -122,7 +120,7 @@ class IlluCat : public MeshSprocket {
String msg = currentMessage.toJsonString();
publish(currentMessage.topic, currentMessage.payload);
if(currentMessage.broadcast){
net->mesh.sendBroadcast(msg);
network.broadcast(msg);
}
request->send(200, "text/plain", msg);
}
@@ -131,7 +129,7 @@ class IlluCat : public MeshSprocket {
if(type == WS_EVT_DATA){
String frame = WsUtils::parseFrameAsString(type, arg, data, len, 0);
dispatch(0, frame);
net->mesh.sendBroadcast(frame);
network.broadcast(frame);
}
}
@@ -144,7 +142,8 @@ class IlluCat : public MeshSprocket {
}
void loop(){
MeshSprocket::loop();
Sprocket::loop();
yield();
}
};

View File

@@ -8,17 +8,20 @@
// Chip config
#define SPROCKET_TYPE "ILLUCAT"
#define SERIAL_BAUD_RATE 115200
#define STARTUP_DELAY 3000
#define STARTUP_DELAY 1000
// Mesh config
#define SPROCKET_MODE 0
#define WIFI_CHANNEL 11
#define MESH_PORT 5555
#define AP_SSID "illucat"
#define AP_PASSWORD "illumination"
#define MESH_PREFIX "illucat-mesh"
#define MESH_PASSWORD "th3r31sn0sp00n"
#define STATION_SSID "MyAP"
#define STATION_PASSWORD "th3r31sn0sp00n"
#define HOSTNAME "illucat"
#define CONNECT_TIMEOUT 10000
#define MESH_DEBUG_TYPES ERROR | STARTUP | CONNECTION
//ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE

118
src/wifi/WebCat.h Normal file
View File

@@ -0,0 +1,118 @@
#ifndef __WEB_CAT__
#define __WEB_CAT__
#include <TaskScheduler.h>
#include <MeshNet.h>
#include <Sprocket.h>
#include "config.h"
#include "NeoPattern.cpp"
#include "NeoPatternDto.h"
#include "NeoPattern_api_json.h"
#include "NeoPattern_api_modes.cpp"
#include "utils_print.h"
#include "utils_ws.h"
#include <plugins/WebSO.h>
#include <plugins/OtaTcpPlugin.cpp>
#include <plugins/WebServerPlugin.cpp>
#include <plugins/WebConfigPlugin.cpp>
#include "PixelPlugin.h"
#include "IlluCat.h"
using namespace std;
using namespace std::placeholders;
class WebCat : public IlluCat {
public:
AsyncWebServer* server;
AsyncWebSocket* ws;
//AsyncWebSocket* wsStream;
WebServerConfig webConfig;
SprocketMessage currentMessage;
WebCat(SprocketConfig cfg, OtaConfig otaCfg, WebServerConfig webCfg) : IlluCat(cfg, otaCfg, webCfg) {
webConfig = webCfg;
}
Sprocket* activate(Scheduler* scheduler, Network* network) {
Serial.println("SETUP SERVER");
// initialize services
server = new AsyncWebServer(80);
ws = new AsyncWebSocket("/pixel");
//wsStream = new AsyncWebSocket("/stream");
Serial.println("init handlers");
// TODO move to plugin
// setup web stuff
server->serveStatic("/pixelConfig.json", SPIFFS, "pixelConfig.json");
server->on("/pixel/api", HTTP_POST, bind(&WebCat::patternWebRequestHandler, this, _1));
ws->onEvent(bind(&WebCat::onWsEvent, this, _1, _2, _3, _4, _5, _6));
server->addHandler(ws);
//wsStream->onEvent(bind(&WebCat::onStream, this, _1, _2, _3, _4, _5, _6));
//server->addHandler(wsStream);
Serial.println("add plugins");
// add plugins
// TODO add HTTP OTA instead of TCP
//addPlugin(new OtaTcpPlugin(otaConfig));
addPlugin(new WebServerPlugin(webConfig, server));
addPlugin(new WebConfigPlugin(server));
return IlluCat::activate(scheduler, network);;
};
// TODO move to utils
String getRequestParameterOrDefault(AsyncWebServerRequest *request, String param, String defaultValue, bool isPost = true){
if(request->hasParam(param, isPost)) {
return request->getParam(param, isPost)->value();
}
return defaultValue;
}
void onStream(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) {
if(type == WS_EVT_DATA){
PRINT_MSG(Serial, SPROCKET_TYPE, WsUtils::parseFrameAsString(type, arg, data, len, 0).c_str());
pixels->ActivePattern = NONE;
pixels->handleStream(data, len);
}
}
void patternWebRequestHandler(AsyncWebServerRequest *request) {
PRINT_MSG(Serial, SPROCKET_TYPE, "POST /pixel/api");
currentMessage.topic = getRequestParameterOrDefault(request, "topic", "");
currentMessage.payload = getRequestParameterOrDefault(request, "payload", "");
currentMessage.broadcast = atoi(getRequestParameterOrDefault(request, "broadcast", "0").c_str());
String msg = currentMessage.toJsonString();
publish(currentMessage.topic, currentMessage.payload);
if(currentMessage.broadcast){
network.broadcast(msg);
}
request->send(200, "text/plain", msg);
}
virtual void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) {
if(type == WS_EVT_DATA){
String frame = WsUtils::parseFrameAsString(type, arg, data, len, 0);
dispatch(0, frame);
network.broadcast(frame);
}
}
virtual void dispatch( uint32_t from, String &msg ) {
currentMessage.fromJsonString(msg);
if(currentMessage.valid){
currentMessage.from = from;
publish(currentMessage.topic, currentMessage.payload);
}
}
void loop(){
Sprocket::loop();
yield();
}
};
#endif

27
src/wifi/main.cpp Normal file
View File

@@ -0,0 +1,27 @@
#include "config.h"
#include "WiFiNet.h"
#include "IlluCat.h"
WiFiNet net(
SPROCKET_MODE,
STATION_SSID,
STATION_PASSWORD,
AP_SSID,
AP_PASSWORD,
HOSTNAME,
CONNECT_TIMEOUT
);
IlluCat sprocket(
{ STARTUP_DELAY, SERIAL_BAUD_RATE },
{ OTA_PORT, OTA_PASSWORD },
{ WEB_CONTEXT_PATH, WEB_DOC_ROOT, WEB_DEFAULT_FILE }
);
void setup() {
sprocket.join(net);
}
void loop() {
sprocket.loop();
yield();
}

39
src/wifiMesh/MeshCat.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef __MESHCAT__
#define __MESHCAT__
#include <TaskSchedulerDeclarations.h>
#include <MeshNet.h>
#include <SprocketConfig.h>
#include "utils_print.h"
#include "IlluCat.h"
#include "config.h"
using namespace std;
using namespace std::placeholders;
class MeshCat : public IlluCat {
public:
Scheduler* meshScheduler;
MeshCat(SprocketConfig cfg, OtaConfig otaCfg, WebServerConfig webCfg) : IlluCat(cfg, otaCfg, webCfg) {
meshScheduler = new Scheduler();
}
Sprocket* join(Network& net){
PRINT_MSG(Serial, SPROCKET_TYPE, "join mesh network");
net.init(meshScheduler);
net.onReceive(bind(&IlluCat::dispatch,this, _1, _2));
net.connect();
network = net;
return activate(&scheduler, &net);
}
void loop() {
meshScheduler->execute();
yield();
Sprocket::loop();
yield();
}
};
#endif

View File

@@ -1,6 +1,6 @@
#include "config.h"
#include "MeshNet.h"
#include "IlluCat.h"
#include "MeshCat.h"
MeshNet net({
SPROCKET_MODE, WIFI_CHANNEL,
@@ -8,11 +8,10 @@ MeshNet net({
STATION_SSID, STATION_PASSWORD, HOSTNAME,
MESH_DEBUG_TYPES
});
IlluCat sprocket(
MeshCat sprocket(
{ STARTUP_DELAY, SERIAL_BAUD_RATE },
{ OTA_PORT, OTA_PASSWORD },
{ WEB_CONTEXT_PATH, WEB_DOC_ROOT, WEB_DEFAULT_FILE }/* ,
{ LED_STRIP_PIN, LED_STRIP_LENGTH, LED_STRIP_BRIGHTNESS, LED_STRIP_UPDATE_INTERVAL, LED_STRIP_DEFAULT_COLOR } */
{ WEB_CONTEXT_PATH, WEB_DOC_ROOT, WEB_DEFAULT_FILE }
);
void setup() {