Files
trmnl_server_cpp/main.cpp

202 lines
3.9 KiB
C++

#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <random>
#include <string>
#include <vector>
#include <stdint.h>
#include "httplib.h"
#include "json.hpp"
#include "helpers.h"
#include "TRMNL.h"
using nlohmann::json;
using namespace std;
int main(int argc, char **argv)
{
string config_filename = "config.json";
string devices_filename = "devices.json";
string host = "";
string folder_images = "images";
string cert_file = "";
string key_file = "";
uint16_t port = 0;
shared_ptr<httplib::Server> server = nullptr;
bool ok;
json cfg;
json devs;
TRMNLContainer container;
if (argc > 2)
{
config_filename = argv[1];
}
ok = read_file_json(cfg, config_filename, &cout);
if (!ok)
{
return -1;
}
json_extract(cfg, "devices_filename", devices_filename);
json_extract(cfg, "host", host);
json_extract(cfg, "port", port);
json_extract(cfg, "folder_images", folder_images);
// json_extract(cfg, "cert_file", cert_file);
// json_extract(cfg, "key_file", cert_file);
if (host.empty())
{
cout << "host not provided" << endl;
return -1;
}
if (0 == port)
{
cout << "port number not provided" << endl;
return -1;
}
if (folder_images.empty())
{
cout << "folder for images is empty" << endl;
return -1;
}
if (!cert_file.empty() && !key_file.empty())
{
// TODO: Implement SSL Server Properly
}
else
{
server = make_shared<httplib::Server>();
}
ok = read_file_json(devs, devices_filename, &cout);
if (!ok)
{
return -1;
}
container.clear();
container = devs;
auto setup_handler = [&container, &devices_filename](const httplib::Request& req, httplib::Response& res)
{
if (req.has_header("ID"))
{
json response;
string id = req.get_header_value("ID");
TRMNL* trmnl = container.get_device_by_id(id);
// Refresh date from file
// Someone might have put the new device in
if (nullptr == trmnl)
{
json j;
read_file_json(j, devices_filename, &cout);
container.clear();
container = j;
trmnl = container.get_device_by_id(id);
}
if (nullptr == trmnl)
{
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
{
bool should_dump = false;
res.status = 200;
if (trmnl->friendly_id().empty())
{
should_dump = true;
trmnl->friendly_id(TRMNL::friendly_from_id(id));
}
if (trmnl->api_key().empty())
{
should_dump = true;
trmnl->api_key("nullptr");
}
response["status"] = 200;
response["api_key"] = trmnl->api_key();
response["friendly_id"] = trmnl->friendly_id();
// TODO: Check for image in folder
response["image_url"] = "https://trmnl.com/images/setup/setup-logo.bmp";
response["filename"] = "welcome";
res.body = response.dump();
if (should_dump)
{
write_file_json(container, devices_filename, &cout);
}
}
}
else
{
// Bad Request - No ID header
res.status = 400;
}
};
auto display_handler = [&container, &devices_filename](const httplib::Request& req, httplib::Response& res)
{
res.status = 500;
for (auto header : res.headers)
{
cout << header.first << ": " << header.second << endl;
}
};
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;
};
server->Get("/api/setup/*", setup_handler);
server->Get("/api/display/*", display_handler);
server->Post("/api/log/*", log_handler);
ok = server->set_mount_point("/images", folder_images);
if (!ok)
{
cout << "Could not mount images folder" << endl;
return -1;
}
cout << "Server listening on " << host << ":" << port << endl;
server->listen(host, port);
return 0;
}