diff --git a/devices_example.json b/devices_example.json index e69de29..6231228 100644 --- a/devices_example.json +++ b/devices_example.json @@ -0,0 +1,11 @@ +[ + { + // Required + "ID": "MAC ADDRESS", + + // Auto managed + "api_key": "api key", + "friendly_id": "917F0B", + "refresh_rate": 600 + } +] \ No newline at end of file diff --git a/main.cpp b/main.cpp index b79654d..6b24d75 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,10 @@ #include +#include +#include #include +#include #include +#include #include @@ -13,6 +17,139 @@ using nlohmann::json; 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 m_devices; + map::iterator> m_by_id; + map::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) { string config_filename = "config.json"; @@ -25,13 +162,16 @@ int main(int argc, char **argv) bool ok; json cfg; + json devs; + vector devices; + DeviceContainer container; if (argc > 2) { config_filename = argv[1]; } - ok = read_config_json(cfg, config_filename, &cout); + ok = read_file_json(cfg, config_filename, &cout); if (!ok) { return -1; @@ -64,14 +204,73 @@ int main(int argc, char **argv) server = make_shared(); } - auto setup_handler = [](const httplib::Request& req, httplib::Response& res) + ok = read_file_json(devs, devices_filename, &cout); + if (!ok) { - cout << req.headers.size() << endl; - for (auto header : req.headers) + return -1; + } + + if (devs.is_array()) + { + for (int i = 0; i < devs.size(); ++i) { - cout << header.first << ": " << header.second << endl; + 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(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; } - res.status = 400; }; auto log_handler = [](const httplib::Request& req, httplib::Response& res)