208 lines
8.1 KiB
Python
208 lines
8.1 KiB
Python
|
|
import os
|
||
|
|
R = r"C:\Projects\CMSCore"
|
||
|
|
def w(rel, txt):
|
||
|
|
p = os.path.join(R, rel)
|
||
|
|
os.makedirs(os.path.dirname(p), exist_ok=True)
|
||
|
|
with open(p, "w", encoding="utf-8", newline="\r\n") as f:
|
||
|
|
f.write(txt.lstrip("\n"))
|
||
|
|
print(f" OK: {rel}")
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# 5. json_serializer.cpp (simple manual JSON - no nlohmann dependency yet)
|
||
|
|
# ============================================================================
|
||
|
|
w("anscloud-common/src/json_serializer.cpp", r'''#include <anscloud/common/json_serializer.h>
|
||
|
|
#include <sstream>
|
||
|
|
#include <chrono>
|
||
|
|
#include <iomanip>
|
||
|
|
#include <random>
|
||
|
|
#include <ctime>
|
||
|
|
|
||
|
|
// ==========================================================================
|
||
|
|
// Minimal JSON builder/parser (no external dependency).
|
||
|
|
// Replace with nlohmann/json when you add it via NuGet/vcpkg.
|
||
|
|
// ==========================================================================
|
||
|
|
|
||
|
|
namespace anscloud {
|
||
|
|
namespace json {
|
||
|
|
|
||
|
|
// ---- Utilities ----
|
||
|
|
|
||
|
|
std::string now_iso8601() {
|
||
|
|
auto now = std::chrono::system_clock::now();
|
||
|
|
auto t = std::chrono::system_clock::to_time_t(now);
|
||
|
|
struct tm buf;
|
||
|
|
#ifdef _WIN32
|
||
|
|
gmtime_s(&buf, &t);
|
||
|
|
#else
|
||
|
|
gmtime_r(&t, &buf);
|
||
|
|
#endif
|
||
|
|
std::ostringstream ss;
|
||
|
|
ss << std::put_time(&buf, "%Y-%m-%dT%H:%M:%SZ");
|
||
|
|
return ss.str();
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string generate_uuid() {
|
||
|
|
static std::random_device rd;
|
||
|
|
static std::mt19937 gen(rd());
|
||
|
|
static std::uniform_int_distribution<uint32_t> dist(0, 0xFFFFFFFF);
|
||
|
|
auto hex = [](uint32_t v, int digits) {
|
||
|
|
std::ostringstream s;
|
||
|
|
s << std::hex << std::setfill('0') << std::setw(digits) << v;
|
||
|
|
return s.str();
|
||
|
|
};
|
||
|
|
uint32_t a = dist(gen), b = dist(gen), c = dist(gen), d = dist(gen);
|
||
|
|
return hex(a, 8) + "-" + hex(b >> 16, 4) + "-4" + hex((b & 0xFFF), 3)
|
||
|
|
+ "-" + hex(0x8000 | (c & 0x3FFF), 4) + "-" + hex(d, 8) + hex(c >> 16, 4);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Simple JSON escape
|
||
|
|
static std::string esc(const std::string& s) {
|
||
|
|
std::string r;
|
||
|
|
r.reserve(s.size() + 8);
|
||
|
|
for (char c : s) {
|
||
|
|
switch (c) {
|
||
|
|
case '"': r += "\\\""; break;
|
||
|
|
case '\\': r += "\\\\"; break;
|
||
|
|
case '\n': r += "\\n"; break;
|
||
|
|
case '\r': r += "\\r"; break;
|
||
|
|
case '\t': r += "\\t"; break;
|
||
|
|
default: r += c;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return r;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Helper macros for building JSON
|
||
|
|
#define JS_STR(k, v) "\"" k "\":\"" + esc(v) + "\""
|
||
|
|
#define JS_NUM(k, v) "\"" k "\":" + std::to_string(v)
|
||
|
|
#define JS_BOOL(k, v) "\"" k "\":" + std::string((v) ? "true" : "false")
|
||
|
|
|
||
|
|
// ---- Serialize implementations ----
|
||
|
|
|
||
|
|
std::string serialize(const SystemMetrics& m) {
|
||
|
|
return "{" + JS_NUM("cpu_usage_percent", m.cpu_usage_percent) + ","
|
||
|
|
+ JS_NUM("ram_usage_percent", m.ram_usage_percent) + ","
|
||
|
|
+ JS_NUM("ram_total_mb", m.ram_total_mb) + ","
|
||
|
|
+ JS_NUM("ram_used_mb", m.ram_used_mb) + ","
|
||
|
|
+ JS_NUM("gpu_usage_percent", m.gpu_usage_percent) + ","
|
||
|
|
+ JS_NUM("gpu_memory_percent", m.gpu_memory_percent) + ","
|
||
|
|
+ JS_NUM("gpu_temperature_c", m.gpu_temperature_c) + ","
|
||
|
|
+ JS_NUM("disk_usage_percent", m.disk_usage_percent) + ","
|
||
|
|
+ JS_NUM("disk_total_gb", m.disk_total_gb) + ","
|
||
|
|
+ JS_NUM("disk_used_gb", m.disk_used_gb) + ","
|
||
|
|
+ JS_NUM("cpu_temperature_c", m.cpu_temperature_c) + ","
|
||
|
|
+ JS_NUM("process_count", m.process_count) + ","
|
||
|
|
+ JS_NUM("network_rx_mbps", m.network_rx_mbps) + ","
|
||
|
|
+ JS_NUM("network_tx_mbps", m.network_tx_mbps) + "}";
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string serialize(const CameraInfo& cam) {
|
||
|
|
return "{" + JS_STR("camera_id", cam.camera_id) + ","
|
||
|
|
+ JS_STR("name", cam.name) + ","
|
||
|
|
+ JS_STR("rtsp_url", cam.rtsp_url) + ","
|
||
|
|
+ JS_STR("status", cam.status) + ","
|
||
|
|
+ JS_NUM("width", cam.width) + ","
|
||
|
|
+ JS_NUM("height", cam.height) + ","
|
||
|
|
+ JS_NUM("fps", cam.fps) + ","
|
||
|
|
+ JS_STR("codec", cam.codec) + ","
|
||
|
|
+ JS_STR("ai_models", cam.ai_models) + ","
|
||
|
|
+ JS_BOOL("recording", cam.recording) + "}";
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string serialize(const std::vector<CameraInfo>& cams) {
|
||
|
|
std::string r = "[";
|
||
|
|
for (size_t i = 0; i < cams.size(); ++i) {
|
||
|
|
if (i > 0) r += ",";
|
||
|
|
r += serialize(cams[i]);
|
||
|
|
}
|
||
|
|
return r + "]";
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string serialize(const InferenceMetrics& inf) {
|
||
|
|
return "{" + JS_NUM("active_models", inf.active_models) + ","
|
||
|
|
+ JS_NUM("avg_latency_ms", inf.avg_latency_ms) + ","
|
||
|
|
+ JS_NUM("total_fps", inf.total_fps) + ","
|
||
|
|
+ JS_NUM("total_detections", inf.total_detections) + "}";
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string serialize(const Heartbeat& hb) {
|
||
|
|
return "{" + JS_STR("device_id", hb.device_id) + ","
|
||
|
|
+ JS_STR("timestamp", hb.timestamp) + ","
|
||
|
|
+ JS_STR("status", to_string(hb.status)) + ","
|
||
|
|
+ JS_NUM("uptime_seconds", hb.uptime_seconds) + ","
|
||
|
|
+ JS_STR("firmware_version", hb.firmware_version) + ","
|
||
|
|
+ JS_STR("ansvis_version", hb.ansvis_version) + "}";
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string serialize(const DeviceTelemetry& tel) {
|
||
|
|
return "{" + JS_STR("device_id", tel.device_id) + ","
|
||
|
|
+ JS_STR("timestamp", tel.timestamp) + ","
|
||
|
|
+ "\"metrics\":" + serialize(tel.metrics) + ","
|
||
|
|
+ "\"cameras\":" + serialize(tel.cameras) + ","
|
||
|
|
+ "\"inference\":" + serialize(tel.inference) + "}";
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string serialize(const Command& cmd) {
|
||
|
|
return "{" + JS_STR("command_id", cmd.command_id) + ","
|
||
|
|
+ JS_STR("device_id", cmd.device_id) + ","
|
||
|
|
+ JS_STR("type", to_string(cmd.type)) + ","
|
||
|
|
+ JS_STR("type_name", cmd.type_name) + ","
|
||
|
|
+ "\"params\":" + (cmd.params_json.empty() ? "{}" : cmd.params_json) + ","
|
||
|
|
+ JS_STR("correlation_id", cmd.correlation_id) + ","
|
||
|
|
+ JS_STR("reply_to", cmd.reply_to) + ","
|
||
|
|
+ JS_NUM("timeout_seconds", cmd.timeout_seconds) + ","
|
||
|
|
+ JS_STR("timestamp", cmd.timestamp) + "}";
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string serialize(const CommandResponse& r) {
|
||
|
|
return "{" + JS_STR("command_id", r.command_id) + ","
|
||
|
|
+ JS_STR("device_id", r.device_id) + ","
|
||
|
|
+ JS_STR("status", to_string(r.status)) + ","
|
||
|
|
+ "\"result\":" + (r.result_json.empty() ? "{}" : r.result_json) + ","
|
||
|
|
+ JS_STR("error_message", r.error_message) + ","
|
||
|
|
+ JS_STR("correlation_id", r.correlation_id) + ","
|
||
|
|
+ JS_NUM("execution_time_ms", r.execution_time_ms) + ","
|
||
|
|
+ JS_STR("timestamp", r.timestamp) + "}";
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string serialize(const DeviceEvent& e) {
|
||
|
|
return "{" + JS_STR("event_id", e.event_id) + ","
|
||
|
|
+ JS_STR("device_id", e.device_id) + ","
|
||
|
|
+ JS_STR("type", to_string(e.type)) + ","
|
||
|
|
+ JS_STR("type_name", e.type_name) + ","
|
||
|
|
+ JS_STR("camera_id", e.camera_id) + ","
|
||
|
|
+ "\"data\":" + (e.data_json.empty() ? "{}" : e.data_json) + ","
|
||
|
|
+ JS_STR("timestamp", e.timestamp) + ","
|
||
|
|
+ JS_NUM("severity", e.severity) + "}";
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string serialize(const DeviceStatusMessage& s) {
|
||
|
|
return "{" + JS_STR("device_id", s.device_id) + ","
|
||
|
|
+ JS_STR("status", to_string(s.status)) + ","
|
||
|
|
+ JS_STR("timestamp", s.timestamp) + ","
|
||
|
|
+ JS_STR("firmware_version", s.firmware_version) + ","
|
||
|
|
+ JS_STR("ansvis_version", s.ansvis_version) + ","
|
||
|
|
+ JS_STR("ip_address", s.ip_address) + ","
|
||
|
|
+ JS_STR("message", s.message) + "}";
|
||
|
|
}
|
||
|
|
|
||
|
|
// ---- Deserialize stubs (TODO: implement with proper JSON parser) ----
|
||
|
|
// For now these return default-constructed objects.
|
||
|
|
// Replace with nlohmann/json parsing when ready.
|
||
|
|
|
||
|
|
Heartbeat deserialize_heartbeat(const std::string&) { return {}; }
|
||
|
|
DeviceTelemetry deserialize_telemetry(const std::string&) { return {}; }
|
||
|
|
SystemMetrics deserialize_metrics(const std::string&) { return {}; }
|
||
|
|
Command deserialize_command(const std::string&) { return {}; }
|
||
|
|
CommandResponse deserialize_response(const std::string&) { return {}; }
|
||
|
|
DeviceEvent deserialize_event(const std::string&) { return {}; }
|
||
|
|
DeviceStatusMessage deserialize_status_message(const std::string&) { return {}; }
|
||
|
|
CameraInfo deserialize_camera(const std::string&) { return {}; }
|
||
|
|
std::vector<CameraInfo> deserialize_camera_list(const std::string&){ return {}; }
|
||
|
|
|
||
|
|
} // namespace json
|
||
|
|
} // namespace anscloud
|
||
|
|
''')
|
||
|
|
|
||
|
|
print(" [5] json_serializer.cpp done")
|