Compare commits
3 Commits
52b0d6642f
...
fe8346925a
| Author | SHA1 | Date | |
|---|---|---|---|
| fe8346925a | |||
| 90bfbda9c7 | |||
| 5ae6fb711c |
@@ -0,0 +1,11 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
// Required
|
||||||
|
"ID": "MAC ADDRESS",
|
||||||
|
|
||||||
|
// Auto managed
|
||||||
|
"api_key": "api key",
|
||||||
|
"friendly_id": "917F0B",
|
||||||
|
"refresh_rate": 600
|
||||||
|
}
|
||||||
|
]
|
||||||
14
helpers.cpp
14
helpers.cpp
@@ -10,28 +10,28 @@ using std::istream;
|
|||||||
using std::ostream;
|
using std::ostream;
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
bool read_config_json(json& cfg, const string& filename, ostream* log)
|
bool read_file_json(json& j, const string& filename, ostream* log)
|
||||||
{
|
{
|
||||||
ifstream cfg_file(filename);
|
ifstream file(filename);
|
||||||
|
|
||||||
if (!cfg_file.is_open())
|
if (!file.is_open())
|
||||||
{
|
{
|
||||||
if (nullptr != log)
|
if (nullptr != log)
|
||||||
{
|
{
|
||||||
*log << "Could not open config file" << endl;
|
*log << "Could not open file" << endl;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return read_config_json(cfg, cfg_file, log);
|
return read_stream_json(j, file, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_config_json(json& cfg, istream& in, ostream* log)
|
bool read_stream_json(json& j, istream& in, ostream* log)
|
||||||
{
|
{
|
||||||
// Parse with comments
|
// Parse with comments
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
cfg = json::parse(in, nullptr, true, true);
|
j = json::parse(in, nullptr, true, true);
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception &e)
|
||||||
{
|
{
|
||||||
|
|||||||
10
helpers.h
10
helpers.h
@@ -9,19 +9,19 @@
|
|||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
|
|
||||||
|
|
||||||
// Reads configuration json from supplied filename
|
// Reads json from supplied filename
|
||||||
// cfg - output json
|
// j - output json
|
||||||
// filename - filepath from which to read json
|
// filename - filepath from which to read json
|
||||||
// log - ostream to log human readable errors to - can be nullptr
|
// log - ostream to log human readable errors to - can be nullptr
|
||||||
// Returns - true if read and parse is successful
|
// Returns - true if read and parse is successful
|
||||||
bool read_config_json(nlohmann::json& cfg, const std::string& filename, std::ostream* log);
|
bool read_file_json(nlohmann::json& j, const std::string& filename, std::ostream* log);
|
||||||
|
|
||||||
// Reads configuration json from supplied istream
|
// Reads configuration json from supplied istream
|
||||||
// cfg - output json
|
// j - output json
|
||||||
// in - istream from which to read json
|
// in - istream from which to read json
|
||||||
// log - ostream to log human readable errors to - can be nullptr
|
// log - ostream to log human readable errors to - can be nullptr
|
||||||
// Returns - true if read and parse is successful
|
// Returns - true if read and parse is successful
|
||||||
bool read_config_json(nlohmann::json& cfg, std::istream& in, std::ostream* log);
|
bool read_stream_json(nlohmann::json& j, std::istream& in, std::ostream* log);
|
||||||
|
|
||||||
// JSON Extraction Helpers
|
// JSON Extraction Helpers
|
||||||
// out value is modified only if an extraction happened
|
// out value is modified only if an extraction happened
|
||||||
|
|||||||
237
main.cpp
237
main.cpp
@@ -1,6 +1,10 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <random>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -13,6 +17,139 @@ using nlohmann::json;
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
struct device
|
||||||
|
{
|
||||||
|
string id;
|
||||||
|
string api_key;
|
||||||
|
string friendly_id;
|
||||||
|
int refresh_rate;
|
||||||
|
|
||||||
|
// Default constructor
|
||||||
|
device()
|
||||||
|
: id(""),
|
||||||
|
api_key(""),
|
||||||
|
friendly_id(""),
|
||||||
|
refresh_rate(600)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
void to_json(json& j, const device& d)
|
||||||
|
{
|
||||||
|
j = json{
|
||||||
|
{"ID", d.id},
|
||||||
|
{"api_key", d.api_key},
|
||||||
|
{"friendly_id", d.friendly_id},
|
||||||
|
{"refresh_rate", d.refresh_rate}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool json_extract(const json& j, const string& key, device& out)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (!key.empty())
|
||||||
|
{
|
||||||
|
if (j.contains(key) && j[key].is_object())
|
||||||
|
{
|
||||||
|
result |= json_extract(j[key], "ID", out.id);
|
||||||
|
result |= json_extract(j[key], "api_key", out.api_key);
|
||||||
|
result |= json_extract(j[key], "friendly_id", out.friendly_id);
|
||||||
|
result |= json_extract(j[key], "refresh_rate", out.refresh_rate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result |= json_extract(j, "ID", out.id);
|
||||||
|
result |= json_extract(j, "api_key", out.api_key);
|
||||||
|
result |= json_extract(j, "friendly_id", out.friendly_id);
|
||||||
|
result |= json_extract(j, "refresh_rate", out.refresh_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
string device_id_to_friendly(string id)
|
||||||
|
{
|
||||||
|
size_t pos = id.find(':');
|
||||||
|
while (pos != string::npos)
|
||||||
|
{
|
||||||
|
id.erase(pos, 1);
|
||||||
|
pos = id.find(':');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id.size() <= 6)
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return id.substr(id.size() - 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeviceContainer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
list<device> m_devices;
|
||||||
|
map<string, list<device>::iterator> m_by_id;
|
||||||
|
map<string, list<device>::iterator> m_by_friendly;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DeviceContainer() = default;
|
||||||
|
|
||||||
|
void add_device(const device& d)
|
||||||
|
{
|
||||||
|
if (d.id.empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = m_devices.insert(m_devices.end(), d);
|
||||||
|
m_by_id.insert(make_pair(it->id, it));
|
||||||
|
|
||||||
|
if (!it->friendly_id.empty())
|
||||||
|
{
|
||||||
|
m_by_friendly.insert(make_pair(it->friendly_id, it));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const device* get_device_by_id(const string& id)
|
||||||
|
{
|
||||||
|
if (0 == m_by_id.count(id))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return &(*(*(m_by_id.find(id))).second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const device* get_device_by_friendly(const string& friendly)
|
||||||
|
{
|
||||||
|
if (0 == m_by_friendly.count(friendly))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return &(*(*(m_by_friendly.find(friendly))).second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_device_friendly(const string& id, const string& friendly)
|
||||||
|
{
|
||||||
|
if (0 == m_by_id.count(id))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = m_by_id[id];
|
||||||
|
it->friendly_id = friendly;
|
||||||
|
m_by_friendly.insert(make_pair(it->friendly_id, it));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
string config_filename = "config.json";
|
string config_filename = "config.json";
|
||||||
@@ -25,13 +162,16 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
bool ok;
|
bool ok;
|
||||||
json cfg;
|
json cfg;
|
||||||
|
json devs;
|
||||||
|
vector<device> devices;
|
||||||
|
DeviceContainer container;
|
||||||
|
|
||||||
if (argc > 2)
|
if (argc > 2)
|
||||||
{
|
{
|
||||||
config_filename = argv[1];
|
config_filename = argv[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = read_config_json(cfg, config_filename, &cout);
|
ok = read_file_json(cfg, config_filename, &cout);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
@@ -64,21 +204,94 @@ int main(int argc, char **argv)
|
|||||||
server = make_shared<httplib::Server>();
|
server = make_shared<httplib::Server>();
|
||||||
}
|
}
|
||||||
|
|
||||||
server->Get("/api/setup/", [](const httplib::Request& req, httplib::Response& res)
|
ok = read_file_json(devs, devices_filename, &cout);
|
||||||
|
if (!ok)
|
||||||
{
|
{
|
||||||
cout << req.headers.size() << endl;
|
return -1;
|
||||||
for (auto header : req.headers)
|
}
|
||||||
{
|
|
||||||
cout << header.first << ": " << header.second << endl;
|
|
||||||
}
|
|
||||||
res.status = 400;
|
|
||||||
});
|
|
||||||
|
|
||||||
server->Post("/api/log/", [](const httplib::Request& req, httplib::Response& res)
|
if (devs.is_array())
|
||||||
{
|
{
|
||||||
cout << req.body << endl;
|
for (int i = 0; i < devs.size(); ++i)
|
||||||
|
{
|
||||||
|
device d;
|
||||||
|
json_extract(devs[i], "", d);
|
||||||
|
devices.push_back(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto device : devices)
|
||||||
|
{
|
||||||
|
container.add_device(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto setup_handler = [&container](const httplib::Request& req, httplib::Response& res)
|
||||||
|
{
|
||||||
|
if (req.has_header("ID"))
|
||||||
|
{
|
||||||
|
json response;
|
||||||
|
string id = req.get_header_value("ID");
|
||||||
|
const device* dev = container.get_device_by_id(id);
|
||||||
|
if (nullptr == dev)
|
||||||
|
{
|
||||||
|
res.status = 404;
|
||||||
|
|
||||||
|
response["status"] = 404;
|
||||||
|
response["api_key"] = nullptr;
|
||||||
|
response["friendly_id"] = nullptr;
|
||||||
|
response["image_url"] = nullptr;
|
||||||
|
response["filename"] = nullptr;
|
||||||
|
|
||||||
|
res.body = response.dump();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res.status = 200;
|
||||||
|
if (dev->friendly_id.empty())
|
||||||
|
{
|
||||||
|
container.set_device_friendly(id, device_id_to_friendly(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
device* dev_mut = const_cast<device*>(dev);
|
||||||
|
|
||||||
|
response["status"] = 200;
|
||||||
|
response["api_key"] = "nullptr";
|
||||||
|
response["friendly_id"] = dev->friendly_id;
|
||||||
|
response["image_url"] = "https://trmnl.com/images/setup/setup-logo.bmp";
|
||||||
|
response["filename"] = "welcome";
|
||||||
|
|
||||||
|
res.body = response.dump();
|
||||||
|
|
||||||
|
json test = *dev_mut;
|
||||||
|
cout << test.dump(4) << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res.status = 500;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto log_handler = [](const httplib::Request& req, httplib::Response& res)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
json j = json::parse(req.body);
|
||||||
|
cout << j.dump(4) << endl;
|
||||||
|
}
|
||||||
|
catch (const exception& e)
|
||||||
|
{
|
||||||
|
cout << req.body << endl;
|
||||||
|
}
|
||||||
res.status = 200;
|
res.status = 200;
|
||||||
});
|
};
|
||||||
|
|
||||||
|
server->Get("/api/setup/", setup_handler);
|
||||||
|
server->Get("/api/setup", setup_handler);
|
||||||
|
|
||||||
|
server->Post("/api/log/", log_handler);
|
||||||
|
server->Post("/api/log", log_handler);
|
||||||
|
|
||||||
server->listen(host, port);
|
server->listen(host, port);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user