Run clang-format on source
This commit is contained in:
parent
e070010401
commit
eb14a20f89
3 changed files with 253 additions and 241 deletions
|
@ -1,12 +1,13 @@
|
||||||
#include <string>
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
struct InterpreterConfig {
|
struct InterpreterConfig {
|
||||||
unsigned int begin;
|
unsigned int begin;
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
std::string scriptkey; // To change the script in this part of the interpreter and get logger output
|
std::string scriptkey; // To change the script in this part of the interpreter
|
||||||
std::string persistkey; // To persist the current running script to disk
|
// and get logger output
|
||||||
Log logger;
|
std::string persistkey; // To persist the current running script to disk
|
||||||
|
Log logger;
|
||||||
};
|
};
|
74
main/log.h
74
main/log.h
|
@ -1,55 +1,53 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifndef _LOG_
|
#ifndef _LOG_
|
||||||
#define _LOG_
|
#define _LOG_
|
||||||
|
|
||||||
class Log {
|
class Log {
|
||||||
public:
|
public:
|
||||||
Log() {}
|
Log() {}
|
||||||
Log(unsigned int s) {size = s;}
|
Log(unsigned int s) { size = s; }
|
||||||
~Log() {
|
~Log() {}
|
||||||
}
|
template <typename T> Log &operator<<(const T &msg) {
|
||||||
template<typename T>
|
std::stringstream current_string;
|
||||||
Log& operator<<(const T &msg) {
|
current_string << msg;
|
||||||
std::stringstream current_string;
|
os << msg;
|
||||||
current_string << msg;
|
|
||||||
os << msg;
|
|
||||||
|
|
||||||
if (current_string.str().back() == '\n') {
|
if (current_string.str().back() == '\n') {
|
||||||
std::cout << "LOG: " << os.str();
|
std::cout << "LOG: " << os.str();
|
||||||
if (current >= size || full) {
|
if (current >= size || full) {
|
||||||
if (ctr >= size) {
|
if (ctr >= size) {
|
||||||
ctr = 0;
|
ctr = 0;
|
||||||
}
|
|
||||||
buffer[ctr] = os.str();
|
|
||||||
full = true;
|
|
||||||
} else {
|
|
||||||
buffer.push_back(os.str());
|
|
||||||
}
|
|
||||||
ctr++;
|
|
||||||
current++;
|
|
||||||
os.str("");
|
|
||||||
}
|
}
|
||||||
return *this;
|
buffer[ctr] = os.str();
|
||||||
}
|
full = true;
|
||||||
std::vector<std::string> getLogs() {
|
} else {
|
||||||
std::vector<std::string> result;
|
buffer.push_back(os.str());
|
||||||
int iterator_limit = std::min(size, current);
|
|
||||||
for (int i = iterator_limit - 1; i >= 0; i--) {
|
|
||||||
result.emplace_back(buffer[(current - 1 - i) % size]);
|
|
||||||
}
|
}
|
||||||
return result;
|
ctr++;
|
||||||
|
current++;
|
||||||
|
os.str("");
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
std::vector<std::string> getLogs() {
|
||||||
|
std::vector<std::string> result;
|
||||||
|
int iterator_limit = std::min(size, current);
|
||||||
|
for (int i = iterator_limit - 1; i >= 0; i--) {
|
||||||
|
result.emplace_back(buffer[(current - 1 - i) % size]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int current = 0;
|
unsigned int current = 0;
|
||||||
unsigned int ctr = 0;
|
unsigned int ctr = 0;
|
||||||
bool full = false;
|
bool full = false;
|
||||||
std::vector<std::string> buffer;
|
std::vector<std::string> buffer;
|
||||||
std::stringstream os;
|
std::stringstream os;
|
||||||
unsigned int size = 255;
|
unsigned int size = 255;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
405
main/main.cpp
405
main/main.cpp
|
@ -1,18 +1,18 @@
|
||||||
#include <cstdio>
|
|
||||||
#include <thread>
|
|
||||||
#include <chrono>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <csignal>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <chrono>
|
||||||
|
#include <csignal>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <thread>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "interpreter_config.h"
|
||||||
|
#include "json.hpp"
|
||||||
|
#include "log.h"
|
||||||
#include "lua.hpp"
|
#include "lua.hpp"
|
||||||
#include "ws2811.h"
|
#include "ws2811.h"
|
||||||
#include "interpreter_config.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "json.hpp"
|
|
||||||
|
|
||||||
#include "httplib.h"
|
#include "httplib.h"
|
||||||
|
|
||||||
|
@ -21,194 +21,210 @@ using std::chrono::duration_cast;
|
||||||
using std::chrono::milliseconds;
|
using std::chrono::milliseconds;
|
||||||
using std::chrono::system_clock;
|
using std::chrono::system_clock;
|
||||||
|
|
||||||
|
#define TARGET_FREQ WS2811_TARGET_FREQ
|
||||||
|
#define GPIO_PIN 18
|
||||||
|
#define DMA 10
|
||||||
|
#define STRIP_TYPE WS2812_STRIP // WS2812/SK6812RGB integrated chip+leds
|
||||||
|
#define LED_COUNT 30 * 5
|
||||||
|
|
||||||
#define TARGET_FREQ WS2811_TARGET_FREQ
|
#define FPS 15
|
||||||
#define GPIO_PIN 18
|
|
||||||
#define DMA 10
|
|
||||||
#define STRIP_TYPE WS2812_STRIP // WS2812/SK6812RGB integrated chip+leds
|
|
||||||
#define LED_COUNT 30*5
|
|
||||||
|
|
||||||
#define FPS 15
|
|
||||||
|
|
||||||
int frametime = 1000 / FPS;
|
int frametime = 1000 / FPS;
|
||||||
|
|
||||||
struct LedSegment {
|
struct LedSegment {
|
||||||
std::optional<std::thread> lua_thread;
|
std::optional<std::thread> lua_thread;
|
||||||
InterpreterConfig* interpreter_config;
|
InterpreterConfig *interpreter_config;
|
||||||
std::string owner;
|
std::string owner;
|
||||||
std::string lua_code;
|
std::string lua_code;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<LedSegment*> ledsegments;
|
std::vector<LedSegment *> ledsegments;
|
||||||
|
|
||||||
// this map is used to be able to see allowed leds from lua
|
// this map is used to be able to see allowed leds from lua
|
||||||
std::unordered_map<lua_State*, InterpreterConfig*> statemap;
|
std::unordered_map<lua_State *, InterpreterConfig *> statemap;
|
||||||
std::atomic<std::uint64_t> framecounter = {0};
|
std::atomic<std::uint64_t> framecounter = {0};
|
||||||
ws2811_t ledstring =
|
ws2811_t ledstring = {
|
||||||
{
|
|
||||||
.freq = TARGET_FREQ,
|
.freq = TARGET_FREQ,
|
||||||
.dmanum = DMA,
|
.dmanum = DMA,
|
||||||
.channel =
|
.channel =
|
||||||
{
|
{
|
||||||
[0] = {
|
[0] =
|
||||||
.gpionum = GPIO_PIN,
|
{
|
||||||
.invert = 0,
|
.gpionum = GPIO_PIN,
|
||||||
.count = LED_COUNT,
|
.invert = 0,
|
||||||
.strip_type = STRIP_TYPE,
|
.count = LED_COUNT,
|
||||||
.brightness = 10,
|
.strip_type = STRIP_TYPE,
|
||||||
|
.brightness = 10,
|
||||||
|
},
|
||||||
|
[1] =
|
||||||
|
{
|
||||||
|
.gpionum = 0,
|
||||||
|
.invert = 0,
|
||||||
|
.count = 0,
|
||||||
|
.brightness = 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
[1] = {
|
|
||||||
.gpionum = 0,
|
|
||||||
.invert = 0,
|
|
||||||
.count = 0,
|
|
||||||
.brightness = 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
void hook(lua_State* L, lua_Debug *ar);
|
void hook(lua_State *L, lua_Debug *ar);
|
||||||
|
|
||||||
inline bool kill_thread_if_desired(lua_State *L) {
|
inline bool kill_thread_if_desired(lua_State *L) {
|
||||||
if (!statemap[L]->enabled)
|
if (!statemap[L]->enabled) {
|
||||||
{
|
cout << "putting errors on the stack" << endl;
|
||||||
cout << "putting errors on the stack" << endl;
|
lua_sethook(L, hook, LUA_MASKLINE, 0);
|
||||||
lua_sethook(L, hook, LUA_MASKLINE, 0);
|
luaL_error(L, "killed by manager");
|
||||||
luaL_error(L, "killed by manager");
|
return true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO also call this hook about once every second
|
// TODO also call this hook about once every second
|
||||||
void hook(lua_State* L, lua_Debug *ar)
|
void hook(lua_State *L, lua_Debug *ar) { kill_thread_if_desired(L); }
|
||||||
{
|
|
||||||
kill_thread_if_desired(L);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
static int c_override_print (lua_State *L) {
|
static int c_override_print(lua_State *L) {
|
||||||
kill_thread_if_desired(L);
|
kill_thread_if_desired(L);
|
||||||
int n = lua_gettop(L); /* number of arguments */
|
int n = lua_gettop(L); /* number of arguments */
|
||||||
int i;
|
int i;
|
||||||
for (i = 1; i <= n; i++) { /* for each argument */
|
for (i = 1; i <= n; i++) { /* for each argument */
|
||||||
size_t l;
|
size_t l;
|
||||||
const char *s = luaL_tolstring(L, i, &l); /* convert it to string */
|
const char *s = luaL_tolstring(L, i, &l); /* convert it to string */
|
||||||
if (i > 1) /* not the first element? */
|
if (i > 1) /* not the first element? */
|
||||||
statemap[L]->logger << '\t'; /* add a tab before it */
|
statemap[L]->logger << '\t'; /* add a tab before it */
|
||||||
statemap[L]->logger << s; /* print it */
|
statemap[L]->logger << s; /* print it */
|
||||||
lua_pop(L, 1); /* pop result */
|
lua_pop(L, 1); /* pop result */
|
||||||
}
|
}
|
||||||
statemap[L]->logger << '\n';
|
statemap[L]->logger << '\n';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int c_led(lua_State *L) {
|
||||||
|
kill_thread_if_desired(L);
|
||||||
|
int virtual_location = luaL_checkinteger(L, 1);
|
||||||
|
int red = luaL_checkinteger(L, 2);
|
||||||
|
int green = luaL_checkinteger(L, 3);
|
||||||
|
int blue = luaL_checkinteger(L, 4);
|
||||||
|
InterpreterConfig *config = statemap[L];
|
||||||
|
|
||||||
|
// Lua is one-based, let's keep it consistent and also make our API one-based
|
||||||
|
if (virtual_location <= 0 || virtual_location > (int)config->length) {
|
||||||
|
std::ostringstream errstream;
|
||||||
|
errstream << "setting led " << virtual_location << " of strip with lenght "
|
||||||
|
<< config->length << "";
|
||||||
|
luaL_argerror(L, 1, errstream.str().c_str());
|
||||||
|
return 0;
|
||||||
|
} else if (red < 0 || red > 0xff) {
|
||||||
|
std::ostringstream errstream;
|
||||||
|
errstream << "setting red channel to " << red
|
||||||
|
<< " but should be between 0 and 255";
|
||||||
|
luaL_argerror(L, 2, errstream.str().c_str());
|
||||||
|
return 0;
|
||||||
|
} else if (green < 0 || green > 0xff) {
|
||||||
|
std::ostringstream errstream;
|
||||||
|
errstream << "setting green channel to " << green
|
||||||
|
<< " but should be between 0 and 255";
|
||||||
|
luaL_argerror(L, 3, errstream.str().c_str());
|
||||||
|
return 0;
|
||||||
|
} else if (blue < 0 || blue > 0xff) {
|
||||||
|
std::ostringstream errstream;
|
||||||
|
errstream << "setting blue channel to " << blue
|
||||||
|
<< " but should be between 0 and 255";
|
||||||
|
luaL_argerror(L, 4, errstream.str().c_str());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
unsigned int real_location = config->begin + virtual_location - 1;
|
||||||
|
// TODO remove this debugging line
|
||||||
|
ledstring.channel[0].leds[real_location] = (red << 16) | (green << 8) | blue;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int c_led (lua_State *L) {
|
static int c_ledamount(lua_State *L) {
|
||||||
kill_thread_if_desired(L);
|
kill_thread_if_desired(L);
|
||||||
int virtual_location = luaL_checkinteger(L, 1);
|
lua_pushinteger(L, statemap[L]->length);
|
||||||
int red = luaL_checkinteger(L, 2);
|
return 1;
|
||||||
int green = luaL_checkinteger(L, 3);
|
}
|
||||||
int blue = luaL_checkinteger(L, 4);
|
|
||||||
InterpreterConfig* config = statemap[L];
|
|
||||||
|
|
||||||
// Lua is one-based, let's keep it consistent and also make our API one-based
|
static int c_delay(lua_State *L) {
|
||||||
if (virtual_location <= 0 || virtual_location > (int) config->length) {
|
if (kill_thread_if_desired(L)) {
|
||||||
std::ostringstream errstream;
|
return 0;
|
||||||
errstream << "setting led " << virtual_location << " of strip with lenght " << config->length << "";
|
}
|
||||||
luaL_argerror(L, 1, errstream.str().c_str());
|
uint64_t millis = luaL_checkinteger(L, 1);
|
||||||
return 0;
|
uint64_t begin =
|
||||||
} else if (red < 0 || red > 0xff) {
|
duration_cast<milliseconds>(system_clock::now().time_since_epoch())
|
||||||
std::ostringstream errstream;
|
.count();
|
||||||
errstream << "setting red channel to " << red << " but should be between 0 and 255";
|
|
||||||
luaL_argerror(L, 2, errstream.str().c_str());
|
while (duration_cast<milliseconds>(system_clock::now().time_since_epoch())
|
||||||
return 0;
|
.count() -
|
||||||
} else if (green < 0 || green > 0xff) {
|
begin <
|
||||||
std::ostringstream errstream;
|
millis - 100) {
|
||||||
errstream << "setting green channel to " << green << " but should be between 0 and 255";
|
std::this_thread::sleep_for(std::chrono::milliseconds(100 - 5));
|
||||||
luaL_argerror(L, 3, errstream.str().c_str());
|
if (kill_thread_if_desired(L)) {
|
||||||
return 0;
|
|
||||||
} else if (blue < 0 || blue > 0xff) {
|
|
||||||
std::ostringstream errstream;
|
|
||||||
errstream << "setting blue channel to " << blue << " but should be between 0 and 255";
|
|
||||||
luaL_argerror(L, 4, errstream.str().c_str());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
unsigned int real_location = config->begin + virtual_location - 1;
|
|
||||||
// TODO remove this debugging line
|
|
||||||
ledstring.channel[0].leds[real_location] = (red << 16) | (green << 8)| blue;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
static int c_ledamount(lua_State *L) {
|
|
||||||
kill_thread_if_desired(L);
|
|
||||||
lua_pushinteger(L, statemap[L]->length);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int c_delay(lua_State *L) {
|
|
||||||
if (kill_thread_if_desired(L)) {return 0;}
|
|
||||||
uint64_t millis = luaL_checkinteger (L, 1);
|
|
||||||
uint64_t begin = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
|
|
||||||
|
|
||||||
while (duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count() - begin < millis - 100) {
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100-5));
|
|
||||||
if (kill_thread_if_desired(L)) {return 0;}
|
|
||||||
}
|
}
|
||||||
uint64_t passed = (duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count() - begin);
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(millis-passed));
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
uint64_t passed =
|
||||||
|
(duration_cast<milliseconds>(system_clock::now().time_since_epoch())
|
||||||
|
.count() -
|
||||||
|
begin);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(millis - passed));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int c_waitframes(lua_State *L) {
|
static int c_waitframes(lua_State *L) {
|
||||||
kill_thread_if_desired(L);
|
kill_thread_if_desired(L);
|
||||||
// TODO this is incorrect, fix this
|
// TODO this is incorrect, fix this
|
||||||
int amount = luaL_checkinteger(L, 1);
|
int amount = luaL_checkinteger(L, 1);
|
||||||
uint64_t destination = amount + framecounter;
|
uint64_t destination = amount + framecounter;
|
||||||
if (amount >= 2 * FPS) {
|
if (amount >= 2 * FPS) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000 * ((amount / FPS) - 1)));
|
std::this_thread::sleep_for(
|
||||||
}
|
std::chrono::milliseconds(1000 * ((amount / FPS) - 1)));
|
||||||
while (framecounter <= destination) {
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(frametime / 2));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
while (framecounter <= destination) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(frametime / 2));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Thanks to https://www.stefanmisik.com/post/sandboxing-lua-from-c.html
|
// Thanks to https://www.stefanmisik.com/post/sandboxing-lua-from-c.html
|
||||||
static void LuaLoadAndUndefine(lua_State* L, lua_CFunction openFunction, const char* moduleName, const char* functions[])
|
static void LuaLoadAndUndefine(lua_State *L, lua_CFunction openFunction,
|
||||||
{
|
const char *moduleName,
|
||||||
/* Load the module, the module table gets placed on the top of the stack */
|
const char *functions[]) {
|
||||||
luaL_requiref(L, moduleName, openFunction, 1);
|
/* Load the module, the module table gets placed on the top of the stack */
|
||||||
|
luaL_requiref(L, moduleName, openFunction, 1);
|
||||||
|
|
||||||
/* Undefine the unwanted functions */
|
/* Undefine the unwanted functions */
|
||||||
for (int i = 0; functions[i] != NULL; i++)
|
for (int i = 0; functions[i] != NULL; i++) {
|
||||||
{
|
lua_pushnil(L);
|
||||||
lua_pushnil(L);
|
lua_setfield(L, -2, functions[i]);
|
||||||
lua_setfield(L, -2, functions[i]);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Pop the module table */
|
/* Pop the module table */
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_State* setup_lua_sandbox(const char* luacode) {
|
lua_State *setup_lua_sandbox(const char *luacode) {
|
||||||
lua_State* L = luaL_newstate();
|
lua_State *L = luaL_newstate();
|
||||||
L = luaL_newstate();
|
L = luaL_newstate();
|
||||||
if (!L) {
|
if (!L) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* remove_base[] = {"assert",
|
static const char *remove_base[] = {"assert", "collectgarbage",
|
||||||
"collectgarbage", "dofile", "getmetatable", "loadfile", "load",
|
"dofile", "getmetatable",
|
||||||
"loadstring", "rawequal", "rawlen", "rawget", "rawset",
|
"loadfile", "load",
|
||||||
"setmetatable", "print", NULL};
|
"loadstring", "rawequal",
|
||||||
|
"rawlen", "rawget",
|
||||||
|
"rawset", "setmetatable",
|
||||||
|
"print", NULL};
|
||||||
LuaLoadAndUndefine(L, luaopen_base, "_G", remove_base);
|
LuaLoadAndUndefine(L, luaopen_base, "_G", remove_base);
|
||||||
static const char* remove_str[] = {"dump", NULL};
|
static const char *remove_str[] = {"dump", NULL};
|
||||||
LuaLoadAndUndefine(L, luaopen_string, LUA_STRLIBNAME, remove_str);
|
LuaLoadAndUndefine(L, luaopen_string, LUA_STRLIBNAME, remove_str);
|
||||||
|
|
||||||
static const char* all_allowed[] = {NULL};
|
static const char *all_allowed[] = {NULL};
|
||||||
LuaLoadAndUndefine(L, luaopen_table, LUA_TABLIBNAME, all_allowed);
|
LuaLoadAndUndefine(L, luaopen_table, LUA_TABLIBNAME, all_allowed);
|
||||||
LuaLoadAndUndefine(L, luaopen_math, LUA_MATHLIBNAME, all_allowed);
|
LuaLoadAndUndefine(L, luaopen_math, LUA_MATHLIBNAME, all_allowed);
|
||||||
|
|
||||||
lua_pushcfunction(L, c_led);
|
lua_pushcfunction(L, c_led);
|
||||||
lua_setglobal(L, "led");
|
lua_setglobal(L, "led");
|
||||||
lua_pushcfunction(L, c_ledamount);
|
lua_pushcfunction(L, c_ledamount);
|
||||||
lua_setglobal(L, "ledamount");
|
lua_setglobal(L, "ledamount");
|
||||||
|
@ -225,7 +241,7 @@ lua_State* setup_lua_sandbox(const char* luacode) {
|
||||||
return L;
|
return L;
|
||||||
}
|
}
|
||||||
|
|
||||||
int execute_lua_sandbox(lua_State* L) {
|
int execute_lua_sandbox(lua_State *L) {
|
||||||
int ret = lua_pcall(L, 0, 0, 0);
|
int ret = lua_pcall(L, 0, 0, 0);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
// TODO get full stacktrace
|
// TODO get full stacktrace
|
||||||
|
@ -238,66 +254,61 @@ int execute_lua_sandbox(lua_State* L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::thread spawn_lua_tread(const char* luacode, InterpreterConfig* config) {
|
std::thread spawn_lua_tread(const char *luacode, InterpreterConfig *config) {
|
||||||
lua_State* L = setup_lua_sandbox(luacode);
|
lua_State *L = setup_lua_sandbox(luacode);
|
||||||
statemap[L] = config;
|
statemap[L] = config;
|
||||||
std::thread t(execute_lua_sandbox, L);
|
std::thread t(execute_lua_sandbox, L);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void signal_callback_handler(int signum) {
|
void signal_callback_handler(int signum) {
|
||||||
(void) signum;
|
(void)signum;
|
||||||
ws2811_fini(&ledstring);
|
ws2811_fini(&ledstring);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
httplib::Server svr;
|
httplib::Server svr;
|
||||||
|
|
||||||
void starthttpserver() {
|
void starthttpserver() { svr.listen("0.0.0.0", 8080); }
|
||||||
svr.listen("0.0.0.0", 8080);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
unsigned int amount = 10;
|
unsigned int amount = 10;
|
||||||
unsigned int leds_per_segment = LED_COUNT / amount;
|
unsigned int leds_per_segment = LED_COUNT / amount;
|
||||||
for (unsigned int i = 0; i < amount; i++) {
|
for (unsigned int i = 0; i < amount; i++) {
|
||||||
InterpreterConfig* config = new InterpreterConfig {
|
InterpreterConfig *config =
|
||||||
.begin = leds_per_segment*i,
|
new InterpreterConfig{.begin = leds_per_segment * i,
|
||||||
.length = leds_per_segment,
|
.length = leds_per_segment,
|
||||||
.enabled = true
|
.enabled = true};
|
||||||
};
|
|
||||||
cout << config->begin << endl;
|
cout << config->begin << endl;
|
||||||
LedSegment* segment = new LedSegment {
|
LedSegment *segment = new LedSegment{.lua_thread = std::nullopt,
|
||||||
.lua_thread = std::nullopt,
|
.interpreter_config = config,
|
||||||
.interpreter_config = config,
|
.owner = "",
|
||||||
.owner = "",
|
.lua_code = ""};
|
||||||
.lua_code = ""
|
|
||||||
};
|
|
||||||
ledsegments.push_back(segment);
|
ledsegments.push_back(segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
svr.Get("/api/segments.json", [](const httplib::Request &, httplib::Response &res) {
|
svr.Get("/api/segments.json",
|
||||||
res.set_header("Access-Control-Allow-Origin", "*");
|
[](const httplib::Request &, httplib::Response &res) {
|
||||||
res.set_header("Access-Control-Allow-Methods", "GET");
|
res.set_header("Access-Control-Allow-Origin", "*");
|
||||||
json j;
|
res.set_header("Access-Control-Allow-Methods", "GET");
|
||||||
int i = 0;
|
json j;
|
||||||
for (LedSegment* ledsegment : ledsegments) {
|
int i = 0;
|
||||||
json o;
|
for (LedSegment *ledsegment : ledsegments) {
|
||||||
o["begin"] = ledsegment->interpreter_config->begin;
|
json o;
|
||||||
o["length"] = ledsegment->interpreter_config->length;
|
o["begin"] = ledsegment->interpreter_config->begin;
|
||||||
o["owner"] = ledsegment->owner;
|
o["length"] = ledsegment->interpreter_config->length;
|
||||||
o["code"] = ledsegment->lua_code;
|
o["owner"] = ledsegment->owner;
|
||||||
o["id"] = i;
|
o["code"] = ledsegment->lua_code;
|
||||||
i++;
|
o["id"] = i;
|
||||||
j.push_back(o);
|
i++;
|
||||||
}
|
j.push_back(o);
|
||||||
res.set_content(j.dump(), "text/json");
|
}
|
||||||
});
|
res.set_content(j.dump(), "text/json");
|
||||||
|
});
|
||||||
|
|
||||||
svr.Put("/api/code.json", [](const httplib::Request &req, httplib::Response &res, const httplib::ContentReader &content_reader) {
|
svr.Put("/api/code.json", [](const httplib::Request &req,
|
||||||
|
httplib::Response &res,
|
||||||
|
const httplib::ContentReader &content_reader) {
|
||||||
res.set_header("Access-Control-Allow-Origin", "*");
|
res.set_header("Access-Control-Allow-Origin", "*");
|
||||||
res.set_header("Access-Control-Allow-Methods", "PUT");
|
res.set_header("Access-Control-Allow-Methods", "PUT");
|
||||||
if (req.is_multipart_form_data()) {
|
if (req.is_multipart_form_data()) {
|
||||||
|
@ -307,7 +318,7 @@ int main(int argc, char** argv)
|
||||||
content_reader([&](const char *raw_data, size_t data_length) {
|
content_reader([&](const char *raw_data, size_t data_length) {
|
||||||
std::string data(raw_data, data_length);
|
std::string data(raw_data, data_length);
|
||||||
auto j = json::parse(data);
|
auto j = json::parse(data);
|
||||||
LedSegment* selected = ledsegments.at(j["id"].get<unsigned int>());
|
LedSegment *selected = ledsegments.at(j["id"].get<unsigned int>());
|
||||||
if (selected->lua_thread.has_value()) {
|
if (selected->lua_thread.has_value()) {
|
||||||
selected->interpreter_config->enabled = false;
|
selected->interpreter_config->enabled = false;
|
||||||
selected->lua_thread.value().join();
|
selected->lua_thread.value().join();
|
||||||
|
@ -315,27 +326,29 @@ int main(int argc, char** argv)
|
||||||
selected->owner = j["owner"].get<std::string>();
|
selected->owner = j["owner"].get<std::string>();
|
||||||
selected->lua_code = j["code"].get<std::string>();
|
selected->lua_code = j["code"].get<std::string>();
|
||||||
selected->interpreter_config->enabled = true;
|
selected->interpreter_config->enabled = true;
|
||||||
selected->lua_thread = spawn_lua_tread(selected->lua_code.c_str(), selected->interpreter_config);
|
selected->lua_thread = spawn_lua_tread(selected->lua_code.c_str(),
|
||||||
cout << "Uploaded new code from " << selected->owner << " to segment " << j["id"].get<unsigned int>() << endl;
|
selected->interpreter_config);
|
||||||
|
cout << "Uploaded new code from " << selected->owner << " to segment "
|
||||||
|
<< j["id"].get<unsigned int>() << endl;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
svr.Options("/api/code.json", [](const httplib::Request &req, httplib::Response &res) {
|
svr.Options("/api/code.json",
|
||||||
res.set_header("Access-Control-Allow-Origin", "*");
|
[](const httplib::Request &req, httplib::Response &res) {
|
||||||
res.set_header("Access-Control-Allow-Methods", "PUT");
|
res.set_header("Access-Control-Allow-Origin", "*");
|
||||||
return true;
|
res.set_header("Access-Control-Allow-Methods", "PUT");
|
||||||
});
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
std::thread httpserverthread(starthttpserver);
|
std::thread httpserverthread(starthttpserver);
|
||||||
|
|
||||||
ws2811_return_t ret;
|
ws2811_return_t ret;
|
||||||
if ((ret = ws2811_init(&ledstring)) != WS2811_SUCCESS)
|
if ((ret = ws2811_init(&ledstring)) != WS2811_SUCCESS) {
|
||||||
{
|
fprintf(stderr, "ws2811_init failed: %s\n", ws2811_get_return_t_str(ret));
|
||||||
fprintf(stderr, "ws2811_init failed: %s\n", ws2811_get_return_t_str(ret));
|
return ret;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
signal(SIGINT, signal_callback_handler);
|
signal(SIGINT, signal_callback_handler);
|
||||||
signal(SIGHUP, signal_callback_handler);
|
signal(SIGHUP, signal_callback_handler);
|
||||||
|
|
Loading…
Reference in a new issue