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