Initial idea

This commit is contained in:
2026-03-28 12:05:34 +11:00
commit 6c6bb79cab
21 changed files with 3860 additions and 0 deletions

57
CMSCore.sln Normal file
View File

@@ -0,0 +1,57 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "anscloud-common", "anscloud-common\anscloud-common.vcxproj", "{B1A2C3D4-0001-4000-8000-000000000001}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "anscloud-device", "anscloud-device\anscloud-device.vcxproj", "{B1A2C3D4-0001-4000-8000-000000000002}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "anscloud-gateway", "anscloud-gateway\anscloud-gateway.vcxproj", "{B1A2C3D4-0001-4000-8000-000000000003}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test-device", "test-device\test-device.vcxproj", "{B1A2C3D4-0001-4000-8000-000000000004}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test-gateway", "test-gateway\test-gateway.vcxproj", "{B1A2C3D4-0001-4000-8000-000000000005}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{F0000000-0000-4000-8000-000000000001}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{F0000000-0000-4000-8000-000000000002}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B1A2C3D4-0001-4000-8000-000000000001}.Debug|x64.ActiveCfg = Debug|x64
{B1A2C3D4-0001-4000-8000-000000000001}.Debug|x64.Build.0 = Debug|x64
{B1A2C3D4-0001-4000-8000-000000000001}.Release|x64.ActiveCfg = Release|x64
{B1A2C3D4-0001-4000-8000-000000000001}.Release|x64.Build.0 = Release|x64
{B1A2C3D4-0001-4000-8000-000000000002}.Debug|x64.ActiveCfg = Debug|x64
{B1A2C3D4-0001-4000-8000-000000000002}.Debug|x64.Build.0 = Debug|x64
{B1A2C3D4-0001-4000-8000-000000000002}.Release|x64.ActiveCfg = Release|x64
{B1A2C3D4-0001-4000-8000-000000000002}.Release|x64.Build.0 = Release|x64
{B1A2C3D4-0001-4000-8000-000000000003}.Debug|x64.ActiveCfg = Debug|x64
{B1A2C3D4-0001-4000-8000-000000000003}.Debug|x64.Build.0 = Debug|x64
{B1A2C3D4-0001-4000-8000-000000000003}.Release|x64.ActiveCfg = Release|x64
{B1A2C3D4-0001-4000-8000-000000000003}.Release|x64.Build.0 = Release|x64
{B1A2C3D4-0001-4000-8000-000000000004}.Debug|x64.ActiveCfg = Debug|x64
{B1A2C3D4-0001-4000-8000-000000000004}.Debug|x64.Build.0 = Debug|x64
{B1A2C3D4-0001-4000-8000-000000000004}.Release|x64.ActiveCfg = Release|x64
{B1A2C3D4-0001-4000-8000-000000000004}.Release|x64.Build.0 = Release|x64
{B1A2C3D4-0001-4000-8000-000000000005}.Debug|x64.ActiveCfg = Debug|x64
{B1A2C3D4-0001-4000-8000-000000000005}.Debug|x64.Build.0 = Debug|x64
{B1A2C3D4-0001-4000-8000-000000000005}.Release|x64.ActiveCfg = Release|x64
{B1A2C3D4-0001-4000-8000-000000000005}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{B1A2C3D4-0001-4000-8000-000000000001} = {F0000000-0000-4000-8000-000000000001}
{B1A2C3D4-0001-4000-8000-000000000002} = {F0000000-0000-4000-8000-000000000001}
{B1A2C3D4-0001-4000-8000-000000000003} = {F0000000-0000-4000-8000-000000000001}
{B1A2C3D4-0001-4000-8000-000000000004} = {F0000000-0000-4000-8000-000000000002}
{B1A2C3D4-0001-4000-8000-000000000005} = {F0000000-0000-4000-8000-000000000002}
EndGlobalSection
EndGlobal

247
_gen_src_01.py Normal file
View File

@@ -0,0 +1,247 @@
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}")
# ============================================================================
# 1. anscloud-common/include/anscloud/common/types.h
# ============================================================================
w("anscloud-common/include/anscloud/common/types.h", r'''#pragma once
// ==========================================================================
// ANSCloud SDK - Common Types
// ANSCENTER Pty Ltd - Cloud Messaging Protocol Types
// ==========================================================================
#include <string>
#include <vector>
#include <functional>
#include <cstdint>
#include <chrono>
namespace anscloud {
// --------------------------------------------------------------------------
// Protocol version
// --------------------------------------------------------------------------
constexpr const char* PROTOCOL_VERSION = "1.0.0";
// --------------------------------------------------------------------------
// Exchange names (must match RabbitMQ broker topology)
// --------------------------------------------------------------------------
namespace exchange {
constexpr const char* DEVICE_TELEMETRY = "ex.device.telemetry";
constexpr const char* DEVICE_STATUS = "ex.device.status";
constexpr const char* DEVICE_EVENTS = "ex.device.events";
constexpr const char* COMMAND = "ex.command";
constexpr const char* COMMAND_RESPONSE = "ex.command.response";
constexpr const char* BROADCAST = "ex.broadcast";
}
// --------------------------------------------------------------------------
// Queue name builders
// --------------------------------------------------------------------------
namespace queue {
inline std::string device_command(const std::string& device_id) { return "q.cmd." + device_id; }
inline std::string device_broadcast(const std::string& device_id){ return "q.broadcast." + device_id; }
// Gateway-side queues (shared)
constexpr const char* TELEMETRY_INGEST = "q.telemetry.ingest";
constexpr const char* EVENTS_PROCESSOR = "q.events.processor";
constexpr const char* STATUS_TRACKER = "q.status.tracker";
constexpr const char* COMMAND_RESPONSES = "q.command.responses";
}
// --------------------------------------------------------------------------
// Device Status
// --------------------------------------------------------------------------
enum class DeviceStatus {
Unknown = 0,
Online,
Offline,
Connecting,
Error
};
const char* to_string(DeviceStatus s);
DeviceStatus device_status_from_string(const std::string& s);
// --------------------------------------------------------------------------
// Command Types
// --------------------------------------------------------------------------
enum class CommandType {
Custom = 0,
GetSystemInfo,
GetConfig,
SetConfig,
GetCameraList,
AddCamera,
RemoveCamera,
UpdateCamera,
GetCameraSnapshot,
StartStream,
StopStream,
RestartService,
RebootDevice,
UpdateFirmware,
RunDiagnostics,
GetLogs,
SetSchedule,
GetSchedule
};
const char* to_string(CommandType t);
CommandType command_type_from_string(const std::string& s);
// --------------------------------------------------------------------------
// Event Types
// --------------------------------------------------------------------------
enum class EventType {
Custom = 0,
Alert,
DetectionLPR,
DetectionFace,
DetectionObject,
DetectionMotion,
LineCrossing,
Intrusion,
Loitering,
CameraDisconnected,
CameraReconnected,
StorageWarning,
SystemError
};
const char* to_string(EventType t);
EventType event_type_from_string(const std::string& s);
// --------------------------------------------------------------------------
// Command Status
// --------------------------------------------------------------------------
enum class CommandStatus {
Success = 0,
Failed,
Timeout,
Rejected,
Pending,
PartialSuccess
};
const char* to_string(CommandStatus s);
// --------------------------------------------------------------------------
// Data structures
// --------------------------------------------------------------------------
struct SystemMetrics {
double cpu_usage_percent = 0.0;
double ram_usage_percent = 0.0;
uint64_t ram_total_mb = 0;
uint64_t ram_used_mb = 0;
double gpu_usage_percent = 0.0;
double gpu_memory_percent = 0.0;
double gpu_temperature_c = 0.0;
double disk_usage_percent = 0.0;
uint64_t disk_total_gb = 0;
uint64_t disk_used_gb = 0;
double cpu_temperature_c = 0.0;
uint32_t process_count = 0;
double network_rx_mbps = 0.0;
double network_tx_mbps = 0.0;
};
struct CameraInfo {
std::string camera_id;
std::string name;
std::string rtsp_url;
std::string status; // "online", "offline", "error"
int width = 0;
int height = 0;
double fps = 0.0;
std::string codec;
std::string ai_models; // comma-separated model names
bool recording = false;
};
struct InferenceMetrics {
uint32_t active_models = 0;
double avg_latency_ms = 0.0;
double total_fps = 0.0;
uint64_t total_detections = 0;
};
struct Heartbeat {
std::string device_id;
std::string timestamp; // ISO 8601
DeviceStatus status = DeviceStatus::Online;
uint64_t uptime_seconds = 0;
std::string firmware_version;
std::string ansvis_version;
};
struct DeviceTelemetry {
std::string device_id;
std::string timestamp;
SystemMetrics metrics;
std::vector<CameraInfo> cameras;
InferenceMetrics inference;
};
struct Command {
std::string command_id; // UUID
std::string device_id; // target device
CommandType type = CommandType::Custom;
std::string type_name; // string name for Custom commands
std::string params_json; // JSON string with command parameters
std::string correlation_id; // for RPC matching
std::string reply_to; // reply queue/routing key
int timeout_seconds = 30;
std::string timestamp;
};
struct CommandResponse {
std::string command_id;
std::string device_id;
CommandStatus status = CommandStatus::Success;
std::string result_json; // JSON string with results
std::string error_message;
std::string correlation_id;
double execution_time_ms = 0.0;
std::string timestamp;
};
struct DeviceEvent {
std::string event_id; // UUID
std::string device_id;
EventType type = EventType::Custom;
std::string type_name;
std::string camera_id; // optional, which camera
std::string data_json; // event payload
std::string thumbnail_base64;// optional snapshot
std::string timestamp;
int severity = 0; // 0=info, 1=warning, 2=critical
};
struct DeviceStatusMessage {
std::string device_id;
DeviceStatus status = DeviceStatus::Unknown;
std::string timestamp;
std::string firmware_version;
std::string ansvis_version;
std::string ip_address;
std::string message;
};
// --------------------------------------------------------------------------
// Callback types
// --------------------------------------------------------------------------
using CommandCallback = std::function<CommandResponse(const Command&)>;
using TelemetryCallback = std::function<void(const DeviceTelemetry&)>;
using HeartbeatCallback = std::function<void(const Heartbeat&)>;
using EventCallback = std::function<void(const DeviceEvent&)>;
using StatusCallback = std::function<void(const DeviceStatusMessage&)>;
using ConnectionCallback = std::function<void(bool connected, const std::string& info)>;
using ErrorCallback = std::function<void(int code, const std::string& message)>;
using BroadcastCallback = std::function<void(const std::string& message_json)>;
} // namespace anscloud
''')
print(" [1/15] types.h done")

288
_gen_src_02.py Normal file
View File

@@ -0,0 +1,288 @@
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}")
# ============================================================================
# 2. i_message_broker.h - Abstract interface (your existing RabbitMQ API plugs in)
# ============================================================================
w("anscloud-common/include/anscloud/common/i_message_broker.h", r'''#pragma once
// ==========================================================================
// ANSCloud SDK - Abstract Message Broker Interface
//
// Your existing RabbitMQ C++ API implements this interface.
// The SDK never depends on rabbitmq-c directly.
// ==========================================================================
#include <string>
#include <functional>
#include <cstdint>
namespace anscloud {
// Callback when a message is received on a consumer
using MessageReceivedFn = std::function<void(
const std::string& consumer_tag,
const std::string& exchange,
const std::string& routing_key,
const std::string& correlation_id,
const std::string& reply_to,
const std::string& body
)>;
// Callback for connection state changes
using BrokerConnectionFn = std::function<void(bool connected, const std::string& info)>;
// Callback for errors
using BrokerErrorFn = std::function<void(int code, const std::string& message)>;
// --------------------------------------------------------------------------
// IMessageBroker - Abstract interface for AMQP operations
//
// Implement this by wrapping your existing RabbitMQ C++ API.
// Both DeviceAgent and GatewayAgent receive an IMessageBroker* at configure().
// --------------------------------------------------------------------------
class IMessageBroker {
public:
virtual ~IMessageBroker() = default;
// --- Connection lifecycle ---
virtual bool connect() = 0;
virtual void disconnect() = 0;
virtual bool is_connected() const = 0;
// --- Topology declaration ---
virtual bool declare_exchange(
const std::string& exchange_name,
const std::string& type = "topic", // "topic", "direct", "fanout"
bool durable = true
) = 0;
virtual bool declare_queue(
const std::string& queue_name,
bool durable = true,
bool exclusive = false,
bool auto_delete = false
) = 0;
virtual bool bind_queue(
const std::string& queue_name,
const std::string& exchange_name,
const std::string& routing_key
) = 0;
// --- Publishing ---
virtual bool publish(
const std::string& exchange,
const std::string& routing_key,
const std::string& body,
const std::string& correlation_id = "",
const std::string& reply_to = "",
bool persistent = true
) = 0;
// --- Consuming ---
// Start consuming from a queue. Returns consumer tag (or empty on failure).
virtual std::string start_consuming(
const std::string& queue_name,
MessageReceivedFn on_message
) = 0;
// Cancel a consumer by tag.
virtual bool cancel_consumer(const std::string& consumer_tag) = 0;
// Process pending messages (call from your event loop).
// timeout_ms: max time to block waiting for messages (0 = non-blocking).
// Returns number of messages processed.
virtual int process_messages(uint32_t timeout_ms = 100) = 0;
// --- Connection callbacks ---
virtual void on_connected(BrokerConnectionFn fn) = 0;
virtual void on_error(BrokerErrorFn fn) = 0;
};
} // namespace anscloud
''')
# ============================================================================
# 3. json_serializer.h
# ============================================================================
w("anscloud-common/include/anscloud/common/json_serializer.h", r'''#pragma once
// ==========================================================================
// ANSCloud SDK - JSON Serialization
// Uses nlohmann/json (or simple manual serialization for now)
// ==========================================================================
#include <anscloud/common/types.h>
#include <string>
#include <vector>
namespace anscloud {
namespace json {
// --- Serialize to JSON string ---
std::string serialize(const Heartbeat& hb);
std::string serialize(const DeviceTelemetry& tel);
std::string serialize(const SystemMetrics& m);
std::string serialize(const Command& cmd);
std::string serialize(const CommandResponse& resp);
std::string serialize(const DeviceEvent& evt);
std::string serialize(const DeviceStatusMessage& status);
std::string serialize(const CameraInfo& cam);
std::string serialize(const std::vector<CameraInfo>& cams);
std::string serialize(const InferenceMetrics& inf);
// --- Deserialize from JSON string ---
Heartbeat deserialize_heartbeat(const std::string& json);
DeviceTelemetry deserialize_telemetry(const std::string& json);
SystemMetrics deserialize_metrics(const std::string& json);
Command deserialize_command(const std::string& json);
CommandResponse deserialize_response(const std::string& json);
DeviceEvent deserialize_event(const std::string& json);
DeviceStatusMessage deserialize_status_message(const std::string& json);
CameraInfo deserialize_camera(const std::string& json);
std::vector<CameraInfo> deserialize_camera_list(const std::string& json);
// --- Utilities ---
std::string now_iso8601();
std::string generate_uuid();
} // namespace json
} // namespace anscloud
''')
# ============================================================================
# 4. types.cpp
# ============================================================================
w("anscloud-common/src/types.cpp", r'''#include <anscloud/common/types.h>
#include <unordered_map>
namespace anscloud {
// --- DeviceStatus ---
const char* to_string(DeviceStatus s) {
switch (s) {
case DeviceStatus::Online: return "online";
case DeviceStatus::Offline: return "offline";
case DeviceStatus::Connecting: return "connecting";
case DeviceStatus::Error: return "error";
default: return "unknown";
}
}
DeviceStatus device_status_from_string(const std::string& s) {
static const std::unordered_map<std::string, DeviceStatus> m = {
{"online", DeviceStatus::Online}, {"offline", DeviceStatus::Offline},
{"connecting", DeviceStatus::Connecting}, {"error", DeviceStatus::Error}
};
auto it = m.find(s);
return it != m.end() ? it->second : DeviceStatus::Unknown;
}
// --- CommandType ---
const char* to_string(CommandType t) {
switch (t) {
case CommandType::GetSystemInfo: return "get_system_info";
case CommandType::GetConfig: return "get_config";
case CommandType::SetConfig: return "set_config";
case CommandType::GetCameraList: return "get_camera_list";
case CommandType::AddCamera: return "add_camera";
case CommandType::RemoveCamera: return "remove_camera";
case CommandType::UpdateCamera: return "update_camera";
case CommandType::GetCameraSnapshot:return "get_camera_snapshot";
case CommandType::StartStream: return "start_stream";
case CommandType::StopStream: return "stop_stream";
case CommandType::RestartService: return "restart_service";
case CommandType::RebootDevice: return "reboot_device";
case CommandType::UpdateFirmware: return "update_firmware";
case CommandType::RunDiagnostics: return "run_diagnostics";
case CommandType::GetLogs: return "get_logs";
case CommandType::SetSchedule: return "set_schedule";
case CommandType::GetSchedule: return "get_schedule";
default: return "custom";
}
}
CommandType command_type_from_string(const std::string& s) {
static const std::unordered_map<std::string, CommandType> m = {
{"get_system_info", CommandType::GetSystemInfo},
{"get_config", CommandType::GetConfig},
{"set_config", CommandType::SetConfig},
{"get_camera_list", CommandType::GetCameraList},
{"add_camera", CommandType::AddCamera},
{"remove_camera", CommandType::RemoveCamera},
{"update_camera", CommandType::UpdateCamera},
{"get_camera_snapshot", CommandType::GetCameraSnapshot},
{"start_stream", CommandType::StartStream},
{"stop_stream", CommandType::StopStream},
{"restart_service", CommandType::RestartService},
{"reboot_device", CommandType::RebootDevice},
{"update_firmware", CommandType::UpdateFirmware},
{"run_diagnostics", CommandType::RunDiagnostics},
{"get_logs", CommandType::GetLogs},
{"set_schedule", CommandType::SetSchedule},
{"get_schedule", CommandType::GetSchedule}
};
auto it = m.find(s);
return it != m.end() ? it->second : CommandType::Custom;
}
// --- EventType ---
const char* to_string(EventType t) {
switch (t) {
case EventType::Alert: return "alert";
case EventType::DetectionLPR: return "detection_lpr";
case EventType::DetectionFace: return "detection_face";
case EventType::DetectionObject: return "detection_object";
case EventType::DetectionMotion: return "detection_motion";
case EventType::LineCrossing: return "line_crossing";
case EventType::Intrusion: return "intrusion";
case EventType::Loitering: return "loitering";
case EventType::CameraDisconnected: return "camera_disconnected";
case EventType::CameraReconnected: return "camera_reconnected";
case EventType::StorageWarning: return "storage_warning";
case EventType::SystemError: return "system_error";
default: return "custom";
}
}
EventType event_type_from_string(const std::string& s) {
static const std::unordered_map<std::string, EventType> m = {
{"alert", EventType::Alert},
{"detection_lpr", EventType::DetectionLPR},
{"detection_face", EventType::DetectionFace},
{"detection_object", EventType::DetectionObject},
{"detection_motion", EventType::DetectionMotion},
{"line_crossing", EventType::LineCrossing},
{"intrusion", EventType::Intrusion},
{"loitering", EventType::Loitering},
{"camera_disconnected", EventType::CameraDisconnected},
{"camera_reconnected", EventType::CameraReconnected},
{"storage_warning", EventType::StorageWarning},
{"system_error", EventType::SystemError}
};
auto it = m.find(s);
return it != m.end() ? it->second : EventType::Custom;
}
// --- CommandStatus ---
const char* to_string(CommandStatus s) {
switch (s) {
case CommandStatus::Success: return "success";
case CommandStatus::Failed: return "failed";
case CommandStatus::Timeout: return "timeout";
case CommandStatus::Rejected: return "rejected";
case CommandStatus::Pending: return "pending";
case CommandStatus::PartialSuccess: return "partial_success";
default: return "unknown";
}
}
} // namespace anscloud
''')
print(" [2-4] i_message_broker.h, json_serializer.h, types.cpp done")

207
_gen_src_03.py Normal file
View File

@@ -0,0 +1,207 @@
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")

195
_gen_src_04.py Normal file
View File

@@ -0,0 +1,195 @@
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}")
# ============================================================================
# 6. device_agent.h
# ============================================================================
w("anscloud-device/include/anscloud/device/device_agent.h", r'''#pragma once
// ==========================================================================
// ANSCloud SDK - Device Agent (AIBOX side)
//
// Manages the full device lifecycle:
// - Connects to broker via IMessageBroker (your existing RabbitMQ API)
// - Declares device queues, binds to exchanges
// - Listens for commands, dispatches to your CommandHandler
// - Publishes heartbeat, telemetry, events, status
// - Background threads for timers and message processing
// ==========================================================================
#include <anscloud/common/types.h>
#include <anscloud/common/i_message_broker.h>
#include <string>
#include <functional>
#include <memory>
#include <atomic>
#include <thread>
#include <mutex>
#include <chrono>
namespace anscloud {
// --------------------------------------------------------------------------
// Configuration
// --------------------------------------------------------------------------
struct DeviceAgentConfig {
std::string device_id;
std::string firmware_version;
std::string ansvis_version;
std::string local_ansvis_api; // e.g. "http://127.0.0.1:8080"
// Telemetry intervals (seconds)
int heartbeat_interval_sec = 30;
int metrics_interval_sec = 60;
// Logging
bool verbose_logging = false;
};
// --------------------------------------------------------------------------
// Provider callbacks - your application implements these
// --------------------------------------------------------------------------
using MetricsProvider = std::function<SystemMetrics()>;
using CameraListProvider = std::function<std::vector<CameraInfo>()>;
using InferenceProvider = std::function<InferenceMetrics()>;
// --------------------------------------------------------------------------
// Agent status info
// --------------------------------------------------------------------------
struct DeviceAgentStatus {
bool connected = false;
bool running = false;
uint64_t uptime_seconds = 0;
uint64_t commands_received = 0;
uint64_t commands_executed = 0;
uint64_t heartbeats_sent = 0;
uint64_t telemetry_sent = 0;
uint64_t events_sent = 0;
uint64_t reconnect_count = 0;
std::string last_error;
};
// --------------------------------------------------------------------------
// DeviceAgent
// --------------------------------------------------------------------------
class DeviceAgent {
public:
DeviceAgent();
~DeviceAgent();
// Non-copyable
DeviceAgent(const DeviceAgent&) = delete;
DeviceAgent& operator=(const DeviceAgent&) = delete;
// --- Setup ---
// Pass YOUR existing RabbitMQ API instance (already configured with host/port/credentials).
// DeviceAgent does NOT own the broker - you manage its lifetime.
void configure(IMessageBroker* broker, const DeviceAgentConfig& config);
// --- Provider registration ---
void set_command_handler(CommandCallback handler);
void set_metrics_provider(MetricsProvider provider);
void set_camera_list_provider(CameraListProvider provider);
void set_inference_provider(InferenceProvider provider);
// --- Lifecycle ---
bool start(); // NON-BLOCKING: connects, declares topology, starts background threads
void stop(); // Publishes offline status, stops threads, disconnects
bool is_running() const;
bool is_connected() const;
// --- Manual publishing ---
bool publish_event(const DeviceEvent& evt);
bool publish_telemetry(); // gathers from providers and publishes
bool send_heartbeat();
bool send_metrics();
// --- Callbacks ---
void on_connection_changed(ConnectionCallback cb);
void on_error(ErrorCallback cb);
void on_broadcast(BroadcastCallback cb);
// --- Status ---
DeviceAgentStatus get_status() const;
private:
struct Impl;
std::unique_ptr<Impl> m_impl;
};
} // namespace anscloud
''')
# ============================================================================
# 7. device_agent_c.h (C API for FFI)
# ============================================================================
w("anscloud-device/include/anscloud/device/device_agent_c.h", r'''#pragma once
// ==========================================================================
// ANSCloud SDK - Device Agent C API (for FFI: Go, Python, C#, etc.)
// ==========================================================================
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
// Opaque handle
typedef void* AnsDeviceHandle;
// C callback types
typedef const char* (*AnsDeviceCmdHandlerFn)(
void* user_data,
const char* command_json // full Command as JSON
); // returns CommandResponse as JSON (caller frees with ansdevice_free_string)
typedef void (*AnsDeviceConnectionFn)(void* user_data, bool connected, const char* info);
typedef void (*AnsDeviceErrorFn)(void* user_data, int code, const char* message);
typedef void (*AnsDeviceBroadcastFn)(void* user_data, const char* message_json);
// --- Lifecycle ---
AnsDeviceHandle ansdevice_create(void);
void ansdevice_destroy(AnsDeviceHandle h);
// Configure: broker_ptr is your IMessageBroker* cast to void*
bool ansdevice_configure(AnsDeviceHandle h, void* broker_ptr, const char* config_json);
// --- Handlers ---
void ansdevice_set_command_handler(AnsDeviceHandle h, AnsDeviceCmdHandlerFn fn, void* user_data);
void ansdevice_on_connection_changed(AnsDeviceHandle h, AnsDeviceConnectionFn fn, void* user_data);
void ansdevice_on_error(AnsDeviceHandle h, AnsDeviceErrorFn fn, void* user_data);
void ansdevice_on_broadcast(AnsDeviceHandle h, AnsDeviceBroadcastFn fn, void* user_data);
// --- Lifecycle ---
bool ansdevice_start(AnsDeviceHandle h);
void ansdevice_stop(AnsDeviceHandle h);
bool ansdevice_is_running(AnsDeviceHandle h);
bool ansdevice_is_connected(AnsDeviceHandle h);
// --- Publishing ---
bool ansdevice_publish_event(AnsDeviceHandle h, const char* event_json);
bool ansdevice_send_heartbeat(AnsDeviceHandle h);
bool ansdevice_send_metrics(AnsDeviceHandle h);
// --- Status ---
const char* ansdevice_get_status(AnsDeviceHandle h); // returns JSON, free with ansdevice_free_string
// --- Memory ---
void ansdevice_free_string(const char* str);
// --- Version ---
const char* ansdevice_version(void);
#ifdef __cplusplus
}
#endif
''')
print(" [6-7] device_agent.h, device_agent_c.h done")

336
_gen_src_05.py Normal file
View File

@@ -0,0 +1,336 @@
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}")
# ============================================================================
# 8. device_agent.cpp
# ============================================================================
w("anscloud-device/src/device_agent.cpp", r'''#include <anscloud/device/device_agent.h>
#include <anscloud/common/json_serializer.h>
#include <iostream>
#include <thread>
#include <chrono>
namespace anscloud {
// ==========================================================================
// DeviceAgent::Impl (PIMPL)
// ==========================================================================
struct DeviceAgent::Impl {
IMessageBroker* broker = nullptr;
DeviceAgentConfig config;
// Callbacks
CommandCallback cmd_handler;
MetricsProvider metrics_provider;
CameraListProvider camera_provider;
InferenceProvider inference_provider;
ConnectionCallback connection_cb;
ErrorCallback error_cb;
BroadcastCallback broadcast_cb;
// State
std::atomic<bool> running{false};
std::atomic<bool> connected{false};
std::chrono::steady_clock::time_point start_time;
// Stats
std::atomic<uint64_t> commands_received{0};
std::atomic<uint64_t> commands_executed{0};
std::atomic<uint64_t> heartbeats_sent{0};
std::atomic<uint64_t> telemetry_sent{0};
std::atomic<uint64_t> events_sent{0};
std::atomic<uint64_t> reconnect_count{0};
std::string last_error;
mutable std::mutex error_mutex;
// Threads
std::thread message_thread;
std::thread heartbeat_thread;
std::thread metrics_thread;
// Consumer tags
std::string cmd_consumer_tag;
std::string broadcast_consumer_tag;
void set_error(const std::string& err) {
std::lock_guard<std::mutex> lk(error_mutex);
last_error = err;
if (error_cb) error_cb(-1, err);
}
void log(const std::string& msg) {
if (config.verbose_logging) {
std::cout << "[DeviceAgent:" << config.device_id << "] " << msg << std::endl;
}
}
// --- Boot sequence ---
bool boot() {
log("Boot: connecting to broker...");
if (!broker->is_connected()) {
if (!broker->connect()) {
set_error("Failed to connect to broker");
return false;
}
}
connected = true;
log("Boot: connected.");
// Declare exchanges (idempotent)
broker->declare_exchange(exchange::DEVICE_TELEMETRY, "topic");
broker->declare_exchange(exchange::DEVICE_STATUS, "topic");
broker->declare_exchange(exchange::DEVICE_EVENTS, "topic");
broker->declare_exchange(exchange::COMMAND, "topic");
broker->declare_exchange(exchange::COMMAND_RESPONSE, "topic");
broker->declare_exchange(exchange::BROADCAST, "fanout");
log("Boot: exchanges declared.");
// Declare device command queue
std::string cmd_q = queue::device_command(config.device_id);
broker->declare_queue(cmd_q, true, false, false);
broker->bind_queue(cmd_q, exchange::COMMAND, config.device_id);
log("Boot: command queue " + cmd_q + " bound.");
// Start consuming commands
cmd_consumer_tag = broker->start_consuming(cmd_q,
[this](const std::string&, const std::string&, const std::string&,
const std::string& corr_id, const std::string&, const std::string& body)
{
handle_command(body, corr_id);
});
// Declare broadcast queue
std::string bcast_q = queue::device_broadcast(config.device_id);
broker->declare_queue(bcast_q, false, true, true); // exclusive, auto-delete
broker->bind_queue(bcast_q, exchange::BROADCAST, "");
broadcast_consumer_tag = broker->start_consuming(bcast_q,
[this](const std::string&, const std::string&, const std::string&,
const std::string&, const std::string&, const std::string& body)
{
if (broadcast_cb) broadcast_cb(body);
});
log("Boot: consumers started.");
// Publish online status
publish_status(DeviceStatus::Online, "Device started");
// Send initial heartbeat
send_heartbeat_impl();
log("Boot: COMPLETE");
return true;
}
// --- Command handler ---
void handle_command(const std::string& body, const std::string& corr_id) {
commands_received++;
log("Command received: " + body.substr(0, 80) + "...");
Command cmd = json::deserialize_command(body);
cmd.correlation_id = corr_id;
CommandResponse resp;
resp.command_id = cmd.command_id;
resp.device_id = config.device_id;
resp.correlation_id = corr_id;
resp.timestamp = json::now_iso8601();
if (cmd_handler) {
auto t0 = std::chrono::steady_clock::now();
resp = cmd_handler(cmd);
auto t1 = std::chrono::steady_clock::now();
resp.execution_time_ms = std::chrono::duration<double, std::milli>(t1 - t0).count();
resp.correlation_id = corr_id;
commands_executed++;
} else {
resp.status = CommandStatus::Rejected;
resp.error_message = "No command handler registered";
}
// Publish response
std::string resp_json = json::serialize(resp);
broker->publish(exchange::COMMAND_RESPONSE, config.device_id, resp_json, corr_id);
log("Command response sent.");
}
// --- Publishing helpers ---
void publish_status(DeviceStatus status, const std::string& msg) {
DeviceStatusMessage sm;
sm.device_id = config.device_id;
sm.status = status;
sm.timestamp = json::now_iso8601();
sm.firmware_version = config.firmware_version;
sm.ansvis_version = config.ansvis_version;
sm.message = msg;
broker->publish(exchange::DEVICE_STATUS, config.device_id, json::serialize(sm));
}
bool send_heartbeat_impl() {
Heartbeat hb;
hb.device_id = config.device_id;
hb.timestamp = json::now_iso8601();
hb.status = DeviceStatus::Online;
auto elapsed = std::chrono::steady_clock::now() - start_time;
hb.uptime_seconds = (uint64_t)std::chrono::duration_cast<std::chrono::seconds>(elapsed).count();
hb.firmware_version = config.firmware_version;
hb.ansvis_version = config.ansvis_version;
bool ok = broker->publish(exchange::DEVICE_TELEMETRY,
config.device_id + ".heartbeat",
json::serialize(hb));
if (ok) heartbeats_sent++;
return ok;
}
bool send_telemetry_impl() {
DeviceTelemetry tel;
tel.device_id = config.device_id;
tel.timestamp = json::now_iso8601();
if (metrics_provider) tel.metrics = metrics_provider();
if (camera_provider) tel.cameras = camera_provider();
if (inference_provider) tel.inference = inference_provider();
bool ok = broker->publish(exchange::DEVICE_TELEMETRY,
config.device_id + ".metrics",
json::serialize(tel));
if (ok) telemetry_sent++;
return ok;
}
// --- Background threads ---
void message_loop() {
while (running) {
if (broker && broker->is_connected()) {
broker->process_messages(100);
} else {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
}
void heartbeat_loop() {
while (running) {
std::this_thread::sleep_for(std::chrono::seconds(config.heartbeat_interval_sec));
if (running && connected) {
send_heartbeat_impl();
}
}
}
void metrics_loop() {
while (running) {
std::this_thread::sleep_for(std::chrono::seconds(config.metrics_interval_sec));
if (running && connected) {
send_telemetry_impl();
}
}
}
};
// ==========================================================================
// DeviceAgent public methods
// ==========================================================================
DeviceAgent::DeviceAgent() : m_impl(std::make_unique<Impl>()) {}
DeviceAgent::~DeviceAgent() { stop(); }
void DeviceAgent::configure(IMessageBroker* broker, const DeviceAgentConfig& config) {
m_impl->broker = broker;
m_impl->config = config;
}
void DeviceAgent::set_command_handler(CommandCallback handler) { m_impl->cmd_handler = std::move(handler); }
void DeviceAgent::set_metrics_provider(MetricsProvider provider) { m_impl->metrics_provider = std::move(provider); }
void DeviceAgent::set_camera_list_provider(CameraListProvider prov) { m_impl->camera_provider = std::move(prov); }
void DeviceAgent::set_inference_provider(InferenceProvider provider) { m_impl->inference_provider = std::move(provider); }
bool DeviceAgent::start() {
if (m_impl->running) return true;
m_impl->start_time = std::chrono::steady_clock::now();
m_impl->running = true;
if (!m_impl->boot()) {
m_impl->running = false;
return false;
}
// Start background threads
m_impl->message_thread = std::thread([this] { m_impl->message_loop(); });
m_impl->heartbeat_thread = std::thread([this] { m_impl->heartbeat_loop(); });
m_impl->metrics_thread = std::thread([this] { m_impl->metrics_loop(); });
return true;
}
void DeviceAgent::stop() {
if (!m_impl->running) return;
m_impl->running = false;
// Publish offline
if (m_impl->broker && m_impl->broker->is_connected()) {
m_impl->publish_status(DeviceStatus::Offline, "Device stopping");
if (!m_impl->cmd_consumer_tag.empty())
m_impl->broker->cancel_consumer(m_impl->cmd_consumer_tag);
if (!m_impl->broadcast_consumer_tag.empty())
m_impl->broker->cancel_consumer(m_impl->broadcast_consumer_tag);
}
// Join threads
if (m_impl->message_thread.joinable()) m_impl->message_thread.join();
if (m_impl->heartbeat_thread.joinable()) m_impl->heartbeat_thread.join();
if (m_impl->metrics_thread.joinable()) m_impl->metrics_thread.join();
m_impl->connected = false;
}
bool DeviceAgent::is_running() const { return m_impl->running; }
bool DeviceAgent::is_connected() const { return m_impl->connected && m_impl->broker && m_impl->broker->is_connected(); }
bool DeviceAgent::publish_event(const DeviceEvent& evt) {
if (!m_impl->connected) return false;
std::string routing = m_impl->config.device_id + "." + to_string(evt.type);
bool ok = m_impl->broker->publish(exchange::DEVICE_EVENTS, routing, json::serialize(evt));
if (ok) m_impl->events_sent++;
return ok;
}
bool DeviceAgent::publish_telemetry() { return m_impl->send_telemetry_impl(); }
bool DeviceAgent::send_heartbeat() { return m_impl->send_heartbeat_impl(); }
bool DeviceAgent::send_metrics() { return m_impl->send_telemetry_impl(); }
void DeviceAgent::on_connection_changed(ConnectionCallback cb) { m_impl->connection_cb = std::move(cb); }
void DeviceAgent::on_error(ErrorCallback cb) { m_impl->error_cb = std::move(cb); }
void DeviceAgent::on_broadcast(BroadcastCallback cb) { m_impl->broadcast_cb = std::move(cb); }
DeviceAgentStatus DeviceAgent::get_status() const {
DeviceAgentStatus s;
s.connected = m_impl->connected;
s.running = m_impl->running;
if (m_impl->running) {
auto elapsed = std::chrono::steady_clock::now() - m_impl->start_time;
s.uptime_seconds = (uint64_t)std::chrono::duration_cast<std::chrono::seconds>(elapsed).count();
}
s.commands_received = m_impl->commands_received;
s.commands_executed = m_impl->commands_executed;
s.heartbeats_sent = m_impl->heartbeats_sent;
s.telemetry_sent = m_impl->telemetry_sent;
s.events_sent = m_impl->events_sent;
s.reconnect_count = m_impl->reconnect_count;
{
std::lock_guard<std::mutex> lk(m_impl->error_mutex);
s.last_error = m_impl->last_error;
}
return s;
}
} // namespace anscloud
''')
print(" [8] device_agent.cpp done")

287
_gen_src_06.py Normal file
View File

@@ -0,0 +1,287 @@
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}")
# ============================================================================
# 9. device_agent_c.cpp
# ============================================================================
w("anscloud-device/src/device_agent_c.cpp", r'''#include <anscloud/device/device_agent_c.h>
#include <anscloud/device/device_agent.h>
#include <anscloud/common/json_serializer.h>
#include <cstring>
#include <string>
using namespace anscloud;
static char* alloc_copy(const std::string& s) {
char* p = new char[s.size() + 1];
memcpy(p, s.c_str(), s.size() + 1);
return p;
}
extern "C" {
AnsDeviceHandle ansdevice_create(void) {
return new DeviceAgent();
}
void ansdevice_destroy(AnsDeviceHandle h) {
delete static_cast<DeviceAgent*>(h);
}
bool ansdevice_configure(AnsDeviceHandle h, void* broker_ptr, const char* config_json) {
if (!h || !broker_ptr) return false;
auto* agent = static_cast<DeviceAgent*>(h);
auto* broker = static_cast<IMessageBroker*>(broker_ptr);
// TODO: parse config_json into DeviceAgentConfig
DeviceAgentConfig cfg;
// For now just a minimal config
cfg.device_id = "device";
cfg.verbose_logging = true;
agent->configure(broker, cfg);
return true;
}
void ansdevice_set_command_handler(AnsDeviceHandle h, AnsDeviceCmdHandlerFn fn, void* user_data) {
if (!h || !fn) return;
auto* agent = static_cast<DeviceAgent*>(h);
agent->set_command_handler([fn, user_data](const Command& cmd) -> CommandResponse {
std::string cmd_json = json::serialize(cmd);
const char* resp_str = fn(user_data, cmd_json.c_str());
CommandResponse resp;
if (resp_str) {
resp = json::deserialize_response(resp_str);
ansdevice_free_string(resp_str);
}
return resp;
});
}
void ansdevice_on_connection_changed(AnsDeviceHandle h, AnsDeviceConnectionFn fn, void* ud) {
if (!h || !fn) return;
static_cast<DeviceAgent*>(h)->on_connection_changed(
[fn, ud](bool c, const std::string& info) { fn(ud, c, info.c_str()); });
}
void ansdevice_on_error(AnsDeviceHandle h, AnsDeviceErrorFn fn, void* ud) {
if (!h || !fn) return;
static_cast<DeviceAgent*>(h)->on_error(
[fn, ud](int code, const std::string& msg) { fn(ud, code, msg.c_str()); });
}
void ansdevice_on_broadcast(AnsDeviceHandle h, AnsDeviceBroadcastFn fn, void* ud) {
if (!h || !fn) return;
static_cast<DeviceAgent*>(h)->on_broadcast(
[fn, ud](const std::string& msg) { fn(ud, msg.c_str()); });
}
bool ansdevice_start(AnsDeviceHandle h) { return h ? static_cast<DeviceAgent*>(h)->start() : false; }
void ansdevice_stop(AnsDeviceHandle h) { if (h) static_cast<DeviceAgent*>(h)->stop(); }
bool ansdevice_is_running(AnsDeviceHandle h) { return h ? static_cast<DeviceAgent*>(h)->is_running() : false; }
bool ansdevice_is_connected(AnsDeviceHandle h){ return h ? static_cast<DeviceAgent*>(h)->is_connected() : false; }
bool ansdevice_publish_event(AnsDeviceHandle h, const char* event_json) {
if (!h || !event_json) return false;
DeviceEvent evt = json::deserialize_event(event_json);
return static_cast<DeviceAgent*>(h)->publish_event(evt);
}
bool ansdevice_send_heartbeat(AnsDeviceHandle h) { return h ? static_cast<DeviceAgent*>(h)->send_heartbeat() : false; }
bool ansdevice_send_metrics(AnsDeviceHandle h) { return h ? static_cast<DeviceAgent*>(h)->send_metrics() : false; }
const char* ansdevice_get_status(AnsDeviceHandle h) {
if (!h) return alloc_copy("{}");
auto s = static_cast<DeviceAgent*>(h)->get_status();
// Simple JSON
std::string j = "{\"connected\":" + std::string(s.connected ? "true" : "false")
+ ",\"running\":" + std::string(s.running ? "true" : "false")
+ ",\"uptime_seconds\":" + std::to_string(s.uptime_seconds)
+ ",\"commands_received\":" + std::to_string(s.commands_received)
+ ",\"commands_executed\":" + std::to_string(s.commands_executed)
+ ",\"heartbeats_sent\":" + std::to_string(s.heartbeats_sent) + "}";
return alloc_copy(j);
}
void ansdevice_free_string(const char* str) {
delete[] str;
}
const char* ansdevice_version(void) {
return "1.0.0";
}
} // extern "C"
''')
# ============================================================================
# 10. gateway_agent.h
# ============================================================================
w("anscloud-gateway/include/anscloud/gateway/gateway_agent.h", r'''#pragma once
// ==========================================================================
// ANSCloud SDK - Gateway Agent (CMS side)
//
// Manages CMS gateway lifecycle:
// - Connects to broker via IMessageBroker (your existing RabbitMQ API)
// - Consumes telemetry, heartbeats, events, status from all devices
// - Sends commands to devices (synchronous RPC via correlation_id)
// - Tracks device online/offline state
// ==========================================================================
#include <anscloud/common/types.h>
#include <anscloud/common/i_message_broker.h>
#include <string>
#include <vector>
#include <memory>
#include <future>
namespace anscloud {
// --------------------------------------------------------------------------
// Configuration
// --------------------------------------------------------------------------
struct GatewayAgentConfig {
int device_timeout_seconds = 90; // mark offline if no heartbeat
int default_command_timeout_seconds = 30;
int max_pending_commands = 1000;
bool verbose_logging = false;
};
// --------------------------------------------------------------------------
// Command result (from synchronous RPC)
// --------------------------------------------------------------------------
struct CommandResult {
bool success = false;
CommandStatus status = CommandStatus::Timeout;
std::string result_json;
std::string error_message;
double execution_time_ms = 0.0;
};
// --------------------------------------------------------------------------
// Device state as tracked by the gateway
// --------------------------------------------------------------------------
struct DeviceState {
std::string device_id;
DeviceStatus status = DeviceStatus::Unknown;
std::string firmware_version;
std::string ansvis_version;
std::string ip_address;
std::string last_heartbeat; // ISO 8601 timestamp
std::string last_telemetry;
uint64_t uptime_seconds = 0;
SystemMetrics last_metrics;
uint32_t camera_count = 0;
};
// --------------------------------------------------------------------------
// Batch command result
// --------------------------------------------------------------------------
struct BatchResult {
std::vector<std::pair<std::string, CommandResult>> results; // device_id -> result
int succeeded = 0;
int failed = 0;
int timed_out = 0;
};
// --------------------------------------------------------------------------
// Gateway statistics
// --------------------------------------------------------------------------
struct GatewayStats {
uint64_t commands_sent = 0;
uint64_t responses_received = 0;
uint64_t timeouts = 0;
uint64_t telemetry_received = 0;
uint64_t heartbeats_received= 0;
uint64_t events_received = 0;
uint32_t devices_online = 0;
uint32_t devices_total = 0;
uint32_t pending_commands = 0;
uint64_t uptime_seconds = 0;
};
// --------------------------------------------------------------------------
// GatewayAgent
// --------------------------------------------------------------------------
class GatewayAgent {
public:
GatewayAgent();
~GatewayAgent();
GatewayAgent(const GatewayAgent&) = delete;
GatewayAgent& operator=(const GatewayAgent&) = delete;
// --- Setup ---
void configure(IMessageBroker* broker, const GatewayAgentConfig& config);
// --- Lifecycle ---
bool start();
void stop();
bool is_running() const;
bool is_connected() const;
// --- Commands ---
// Synchronous RPC: sends command, blocks until response or timeout
CommandResult send_command(
const std::string& device_id,
CommandType type,
const std::string& params_json = "{}",
int timeout_seconds = 0 // 0 = use default
);
// Async version
std::future<CommandResult> send_command_async(
const std::string& device_id,
CommandType type,
const std::string& params_json = "{}",
int timeout_seconds = 0
);
// Fire-and-forget (no response expected)
bool send_command_fire_and_forget(
const std::string& device_id,
CommandType type,
const std::string& params_json = "{}"
);
// Send to multiple devices
BatchResult send_batch_command(
const std::vector<std::string>& device_ids,
CommandType type,
const std::string& params_json = "{}",
int timeout_seconds = 0
);
// Broadcast to all devices
bool send_broadcast(const std::string& message_json);
// --- Device tracking ---
std::vector<DeviceState> get_all_devices() const;
DeviceState get_device(const std::string& device_id) const;
std::vector<DeviceState> get_online_devices() const;
bool is_device_online(const std::string& device_id) const;
// --- Callbacks ---
void on_telemetry(TelemetryCallback cb);
void on_heartbeat(HeartbeatCallback cb);
void on_event(EventCallback cb);
void on_device_status_changed(StatusCallback cb);
void on_connection_changed(ConnectionCallback cb);
void on_error(ErrorCallback cb);
// --- Stats ---
GatewayStats get_stats() const;
private:
struct Impl;
std::unique_ptr<Impl> m_impl;
};
} // namespace anscloud
''')
print(" [9-10] device_agent_c.cpp, gateway_agent.h done")

323
_gen_vcxproj.py Normal file
View File

@@ -0,0 +1,323 @@
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}")
# === VCXPROJ: anscloud-common (StaticLibrary) ===
w("anscloud-common/anscloud-common.vcxproj", r'''<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64"><Configuration>Debug</Configuration><Platform>x64</Platform></ProjectConfiguration>
<ProjectConfiguration Include="Release|x64"><Configuration>Release</Configuration><Platform>x64</Platform></ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{11111111-1111-4000-8000-000000000001}</ProjectGuid>
<RootNamespace>anscloudcommon</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType><UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset><CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType><UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset><WholeProgramOptimization>true</WholeProgramOptimization><CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel><SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode><LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel><SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode><LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="include\anscloud\common\types.h" />
<ClInclude Include="include\anscloud\common\i_message_broker.h" />
<ClInclude Include="include\anscloud\common\json_serializer.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\types.cpp" />
<ClCompile Include="src\json_serializer.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
''')
# === VCXPROJ: anscloud-device (StaticLibrary) ===
w("anscloud-device/anscloud-device.vcxproj", r'''<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64"><Configuration>Debug</Configuration><Platform>x64</Platform></ProjectConfiguration>
<ProjectConfiguration Include="Release|x64"><Configuration>Release</Configuration><Platform>x64</Platform></ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{22222222-2222-4000-8000-000000000002}</ProjectGuid>
<RootNamespace>ansclouddevice</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType><UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset><CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType><UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset><WholeProgramOptimization>true</WholeProgramOptimization><CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel><SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode><LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)include;$(SolutionDir)anscloud-common\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel><SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode><LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)include;$(SolutionDir)anscloud-common\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="include\anscloud\device\device_agent.h" />
<ClInclude Include="include\anscloud\device\device_agent_c.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\device_agent.cpp" />
<ClCompile Include="src\device_agent_c.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\anscloud-common\anscloud-common.vcxproj">
<Project>{11111111-1111-4000-8000-000000000001}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
''')
# === VCXPROJ: anscloud-gateway (StaticLibrary) ===
w("anscloud-gateway/anscloud-gateway.vcxproj", r'''<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64"><Configuration>Debug</Configuration><Platform>x64</Platform></ProjectConfiguration>
<ProjectConfiguration Include="Release|x64"><Configuration>Release</Configuration><Platform>x64</Platform></ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{33333333-3333-4000-8000-000000000003}</ProjectGuid>
<RootNamespace>anscloudgateway</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType><UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset><CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType><UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset><WholeProgramOptimization>true</WholeProgramOptimization><CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel><SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode><LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)include;$(SolutionDir)anscloud-common\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel><SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode><LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)include;$(SolutionDir)anscloud-common\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="include\anscloud\gateway\gateway_agent.h" />
<ClInclude Include="include\anscloud\gateway\gateway_agent_c.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\gateway_agent.cpp" />
<ClCompile Include="src\gateway_agent_c.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\anscloud-common\anscloud-common.vcxproj">
<Project>{11111111-1111-4000-8000-000000000001}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
''')
# === VCXPROJ: test-device (Console Application) ===
w("test-device/test-device.vcxproj", r'''<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64"><Configuration>Debug</Configuration><Platform>x64</Platform></ProjectConfiguration>
<ProjectConfiguration Include="Release|x64"><Configuration>Release</Configuration><Platform>x64</Platform></ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{44444444-4444-4000-8000-000000000004}</ProjectGuid>
<RootNamespace>testdevice</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType><UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset><CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType><UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset><WholeProgramOptimization>true</WholeProgramOptimization><CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel><SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode><LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)anscloud-common\include;$(SolutionDir)anscloud-device\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link><SubSystem>Console</SubSystem></Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel><SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode><LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)anscloud-common\include;$(SolutionDir)anscloud-device\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link><SubSystem>Console</SubSystem></Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\anscloud-common\anscloud-common.vcxproj">
<Project>{11111111-1111-4000-8000-000000000001}</Project>
</ProjectReference>
<ProjectReference Include="..\anscloud-device\anscloud-device.vcxproj">
<Project>{22222222-2222-4000-8000-000000000002}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
''')
# === VCXPROJ: test-gateway (Console Application) ===
w("test-gateway/test-gateway.vcxproj", r'''<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64"><Configuration>Debug</Configuration><Platform>x64</Platform></ProjectConfiguration>
<ProjectConfiguration Include="Release|x64"><Configuration>Release</Configuration><Platform>x64</Platform></ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{55555555-5555-4000-8000-000000000005}</ProjectGuid>
<RootNamespace>testgateway</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType><UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset><CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType><UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset><WholeProgramOptimization>true</WholeProgramOptimization><CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel><SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode><LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)anscloud-common\include;$(SolutionDir)anscloud-gateway\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link><SubSystem>Console</SubSystem></Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel><SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode><LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)anscloud-common\include;$(SolutionDir)anscloud-gateway\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link><SubSystem>Console</SubSystem></Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\anscloud-common\anscloud-common.vcxproj">
<Project>{11111111-1111-4000-8000-000000000001}</Project>
</ProjectReference>
<ProjectReference Include="..\anscloud-gateway\anscloud-gateway.vcxproj">
<Project>{33333333-3333-4000-8000-000000000003}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
''')
print("\n=== All vcxproj files created ===")

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{B1A2C3D4-0001-4000-8000-000000000001}</ProjectGuid>
<RootNamespace>anscloudcommon</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>anscloud-common</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_LIB;ANSCLOUD_COMMON_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)include;$(SolutionDir)packages\nlohmann-json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_LIB;ANSCLOUD_COMMON_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)include;$(SolutionDir)packages\nlohmann-json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="include\anscloud\common\types.h" />
<ClInclude Include="include\anscloud\common\i_message_broker.h" />
<ClInclude Include="include\anscloud\common\json_serializer.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\types.cpp" />
<ClCompile Include="src\json_serializer.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@@ -0,0 +1,125 @@
#pragma once
//=============================================================================
// IMessageBroker - Abstract interface for message broker operations
//
// Your existing RabbitMQ C++ API implements this interface.
// The SDK (DeviceAgent / GatewayAgent) depends only on this abstraction,
// not on any concrete AMQP library.
//=============================================================================
#ifndef ANSCLOUD_COMMON_I_MESSAGE_BROKER_H
#define ANSCLOUD_COMMON_I_MESSAGE_BROKER_H
#include <string>
#include <functional>
#include <memory>
#include <cstdint>
namespace anscloud {
// Forward declare
struct BrokerConfig;
//-----------------------------------------------------------------------------
// Message received from broker
//-----------------------------------------------------------------------------
struct BrokerMessage {
std::string exchange;
std::string routing_key;
std::string body; // JSON payload
std::string correlation_id; // For RPC matching
std::string reply_to; // Reply queue/routing key
std::string message_id;
std::string content_type; // "application/json"
uint64_t delivery_tag = 0;
bool redelivered = false;
};
//-----------------------------------------------------------------------------
// Publish options
//-----------------------------------------------------------------------------
struct PublishOptions {
std::string correlation_id;
std::string reply_to;
std::string message_id;
std::string content_type = "application/json";
bool persistent = true;
int expiration_ms = 0; // 0 = no expiry (TTL)
};
//-----------------------------------------------------------------------------
// Callback types
//-----------------------------------------------------------------------------
using MessageCallback = std::function<void(const BrokerMessage& msg)>;
using ConnectionCallback = std::function<void(bool connected)>;
using ErrorCallback = std::function<void(const std::string& error)>;
//=============================================================================
// IMessageBroker - Pure virtual interface
//
// Your existing RabbitMQ C++ API creates a class that inherits from this:
//
// class MyRabbitMQBroker : public anscloud::IMessageBroker {
// // ... implement all pure virtual methods using your existing API
// };
//
//=============================================================================
class IMessageBroker {
public:
virtual ~IMessageBroker() = default;
//--- Connection lifecycle ------------------------------------------------
virtual bool connect(const std::string& host, int port,
const std::string& username, const std::string& password,
const std::string& vhost) = 0;
virtual void disconnect() = 0;
virtual bool is_connected() const = 0;
//--- Exchange & Queue declarations (idempotent) --------------------------
virtual bool declare_exchange(const std::string& name,
const std::string& type = "topic",
bool durable = true) = 0;
virtual bool declare_queue(const std::string& name,
bool durable = true,
bool exclusive = false,
bool auto_delete = false) = 0;
virtual bool bind_queue(const std::string& queue,
const std::string& exchange,
const std::string& routing_key) = 0;
//--- Publishing ----------------------------------------------------------
virtual bool publish(const std::string& exchange,
const std::string& routing_key,
const std::string& body,
const PublishOptions& options = {}) = 0;
//--- Consuming -----------------------------------------------------------
// Start consuming from a queue. Messages delivered via callback.
// Returns a consumer tag (string) that can be used to cancel.
virtual std::string start_consuming(const std::string& queue,
MessageCallback callback,
bool auto_ack = true) = 0;
// Cancel a consumer by tag
virtual void cancel_consumer(const std::string& consumer_tag) = 0;
// Process pending messages (call from event loop).
// timeout_ms: max time to wait for messages. 0 = non-blocking poll.
// Returns number of messages processed.
virtual int process_messages(int timeout_ms = 100) = 0;
//--- Callbacks -----------------------------------------------------------
virtual void on_connected(ConnectionCallback cb) = 0;
virtual void on_error(ErrorCallback cb) = 0;
};
//=============================================================================
// Factory function type - your application provides this
//=============================================================================
using BrokerFactory = std::function<std::unique_ptr<IMessageBroker>()>;
} // namespace anscloud
#endif // ANSCLOUD_COMMON_I_MESSAGE_BROKER_H

View File

@@ -0,0 +1,47 @@
#pragma once
#ifndef ANSCLOUD_COMMON_JSON_SERIALIZER_H
#define ANSCLOUD_COMMON_JSON_SERIALIZER_H
#include "types.h"
#include <string>
#include <vector>
namespace anscloud {
namespace json {
// Serialization (struct -> JSON string)
std::string serialize(const Heartbeat& hb);
std::string serialize(const DeviceTelemetry& tel);
std::string serialize(const SystemMetrics& m);
std::string serialize(const Command& cmd);
std::string serialize(const CommandResponse& resp);
std::string serialize(const DeviceEvent& evt);
std::string serialize(const DeviceStatusMessage& msg);
std::string serialize(const CameraInfo& cam);
std::string serialize(const std::vector<CameraInfo>& cams);
std::string serialize(const DeviceState& state);
std::string serialize(const std::vector<DeviceState>& states);
std::string serialize(const CommandResult& result);
// Deserialization (JSON string -> struct)
Heartbeat deserialize_heartbeat(const std::string& json);
DeviceTelemetry deserialize_telemetry(const std::string& json);
SystemMetrics deserialize_metrics(const std::string& json);
Command deserialize_command(const std::string& json);
CommandResponse deserialize_response(const std::string& json);
DeviceEvent deserialize_event(const std::string& json);
DeviceStatusMessage deserialize_status_message(const std::string& json);
CameraInfo deserialize_camera(const std::string& json);
std::vector<CameraInfo> deserialize_cameras(const std::string& json);
DeviceState deserialize_device_state(const std::string& json);
std::vector<DeviceState> deserialize_device_states(const std::string& json);
CommandResult deserialize_command_result(const std::string& json);
// Utility
std::string now_iso8601();
std::string generate_uuid();
} // namespace json
} // namespace anscloud
#endif // ANSCLOUD_COMMON_JSON_SERIALIZER_H

View File

@@ -0,0 +1,255 @@
#pragma once
#ifndef ANSCLOUD_COMMON_TYPES_H
#define ANSCLOUD_COMMON_TYPES_H
#include <string>
#include <vector>
#include <functional>
#include <cstdint>
#include <chrono>
namespace anscloud {
//=============================================================================
// Protocol Constants - Exchange & Queue names
//=============================================================================
namespace protocol {
// Exchanges
constexpr const char* EX_DEVICE_TELEMETRY = "ex.device.telemetry";
constexpr const char* EX_DEVICE_STATUS = "ex.device.status";
constexpr const char* EX_DEVICE_EVENTS = "ex.device.events";
constexpr const char* EX_COMMAND = "ex.command";
constexpr const char* EX_COMMAND_RESPONSE = "ex.command.response";
constexpr const char* EX_BROADCAST = "ex.broadcast";
// Queue name patterns (format with device_id)
inline std::string queue_cmd(const std::string& device_id) {
return "q.cmd." + device_id;
}
inline std::string queue_broadcast(const std::string& device_id) {
return "q.broadcast." + device_id;
}
// Gateway consumer queues
constexpr const char* Q_TELEMETRY_INGEST = "q.telemetry.ingest";
constexpr const char* Q_EVENTS_PROCESSOR = "q.events.processor";
constexpr const char* Q_STATUS_TRACKER = "q.status.tracker";
constexpr const char* Q_COMMAND_RESPONSES = "q.command.responses";
} // namespace protocol
//=============================================================================
// Broker Configuration
//=============================================================================
struct BrokerConfig {
std::string host = "localhost";
int port = 5672;
std::string username = "guest";
std::string password = "guest";
std::string vhost = "/";
bool use_tls = false;
int heartbeat_sec = 60;
int reconnect_delay_ms = 1000;
int reconnect_max_delay_ms = 30000;
int connection_timeout_ms = 10000;
};
//=============================================================================
// Device Identity
//=============================================================================
struct DeviceCredentials {
std::string device_id; // e.g. "AIBOX-001"
std::string device_secret; // Authentication token
std::string tenant_id; // Multi-tenancy isolation
};
//=============================================================================
// Device Status
//=============================================================================
enum class DeviceStatus {
Online,
Offline,
Connecting,
Error
};
const char* to_string(DeviceStatus status);
DeviceStatus device_status_from_string(const std::string& str);
struct DeviceStatusMessage {
std::string device_id;
DeviceStatus status = DeviceStatus::Offline;
std::string timestamp; // ISO 8601
std::string firmware_version;
std::string ansvis_version;
std::string ip_address;
};
//=============================================================================
// Telemetry Types
//=============================================================================
struct SystemMetrics {
double cpu_usage_percent = 0.0;
double ram_usage_percent = 0.0;
double ram_used_mb = 0.0;
double ram_total_mb = 0.0;
double gpu_usage_percent = 0.0;
double gpu_memory_used_mb = 0.0;
double gpu_memory_total_mb = 0.0;
double gpu_temp_celsius = 0.0;
double disk_usage_percent = 0.0;
double disk_used_gb = 0.0;
double disk_total_gb = 0.0;
int process_count = 0;
double uptime_hours = 0.0;
};
struct CameraInfo {
std::string camera_id;
std::string name;
std::string rtsp_url;
std::string status; // "active", "error", "disabled"
int width = 0;
int height = 0;
double fps = 0.0;
std::string error_message;
};
struct InferenceMetrics {
int active_models = 0;
double total_fps = 0.0;
double avg_latency_ms = 0.0;
int detections_per_second = 0;
};
struct Heartbeat {
std::string device_id;
std::string timestamp;
uint64_t uptime_seconds = 0;
int active_cameras = 0;
int active_models = 0;
};
struct DeviceTelemetry {
std::string device_id;
std::string timestamp;
SystemMetrics system;
std::vector<CameraInfo> cameras;
InferenceMetrics inference;
};
//=============================================================================
// Command Types
//=============================================================================
enum class CommandType {
// System
GetSystemInfo,
GetConfig,
SetConfig,
RestartService,
RebootDevice,
UpdateFirmware,
RunDiagnostics,
// Camera
GetCameraList,
AddCamera,
RemoveCamera,
UpdateCamera,
GetCameraSnapshot,
// AI Model
GetModelList,
LoadModel,
UnloadModel,
// Custom
Custom
};
const char* to_string(CommandType type);
CommandType command_type_from_string(const std::string& str);
enum class CommandStatus {
Pending,
Executing,
Success,
Failed,
Timeout,
Cancelled
};
const char* to_string(CommandStatus status);
CommandStatus command_status_from_string(const std::string& str);
struct Command {
std::string command_id; // UUID
std::string device_id; // Target device
CommandType type = CommandType::Custom;
std::string custom_type; // When type == Custom
std::string params_json; // JSON parameters
std::string correlation_id; // For RPC matching
std::string timestamp;
int timeout_seconds = 30;
};
struct CommandResponse {
std::string command_id;
std::string device_id;
CommandStatus status = CommandStatus::Pending;
std::string result_json; // JSON result payload
std::string error_message;
std::string correlation_id;
std::string timestamp;
int execution_time_ms = 0;
};
//=============================================================================
// Event Types
//=============================================================================
enum class EventType {
Alert,
DetectionLPR,
DetectionFace,
DetectionObject,
CameraStatusChanged,
ModelStatusChanged,
SystemAlert,
Custom
};
const char* to_string(EventType type);
EventType event_type_from_string(const std::string& str);
struct DeviceEvent {
std::string event_id; // UUID
std::string device_id;
EventType type = EventType::Custom;
std::string custom_type;
std::string data_json; // Event payload
std::string camera_id; // Optional: related camera
std::string timestamp;
std::string severity; // "info", "warning", "critical"
};
//=============================================================================
// Gateway-side types
//=============================================================================
struct CommandResult {
bool success = false;
CommandStatus status = CommandStatus::Pending;
std::string result_json;
std::string error_message;
int execution_time_ms = 0;
};
struct DeviceState {
std::string device_id;
DeviceStatus status = DeviceStatus::Offline;
std::string last_seen; // ISO 8601
std::string ip_address;
std::string firmware_version;
std::string ansvis_version;
SystemMetrics last_metrics;
int camera_count = 0;
};
} // namespace anscloud
#endif // ANSCLOUD_COMMON_TYPES_H

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{B1A2C3D4-0001-4000-8000-000000000002}</ProjectGuid>
<RootNamespace>ansclouddevice</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>anscloud-device</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;ANSCLOUD_DEVICE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)include;$(SolutionDir)anscloud-common\include;$(SolutionDir)packages\nlohmann-json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>anscloud-common.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;ANSCLOUD_DEVICE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)include;$(SolutionDir)anscloud-common\include;$(SolutionDir)packages\nlohmann-json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>anscloud-common.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="include\anscloud\device\device_agent.h" />
<ClInclude Include="include\anscloud\device\device_agent_c.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\device_agent.cpp" />
<ClCompile Include="src\device_agent_c.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\anscloud-common\anscloud-common.vcxproj">
<Project>{B1A2C3D4-0001-4000-8000-000000000001}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@@ -0,0 +1,123 @@
#pragma once
#ifndef ANSCLOUD_DEVICE_AGENT_H
#define ANSCLOUD_DEVICE_AGENT_H
#include <anscloud/common/types.h>
#include <anscloud/common/i_message_broker.h>
#include <string>
#include <functional>
#include <memory>
#include <atomic>
#ifdef ANSCLOUD_DEVICE_EXPORTS
#define ANSCLOUD_DEVICE_API __declspec(dllexport)
#else
#define ANSCLOUD_DEVICE_API __declspec(dllimport)
#endif
namespace anscloud {
//=============================================================================
// DeviceAgent Configuration
//=============================================================================
struct DeviceAgentConfig {
BrokerConfig broker;
DeviceCredentials credentials;
// Telemetry intervals (seconds)
int heartbeat_interval_sec = 30;
int metrics_interval_sec = 60;
int snapshot_interval_sec = 0; // 0 = disabled
// Device info
std::string firmware_version;
std::string ansvis_version;
std::string ip_address;
std::string local_api_endpoint; // e.g. "http://127.0.0.1:8080"
};
//=============================================================================
// Application callback types - your app implements these
//=============================================================================
using CommandHandler = std::function<CommandResponse(const Command& cmd)>;
using MetricsProvider = std::function<SystemMetrics()>;
using CameraListProvider = std::function<std::vector<CameraInfo>()>;
using InferenceProvider = std::function<InferenceMetrics()>;
using SnapshotProvider = std::function<std::string(const std::string& camera_id)>; // returns base64 JPEG
//=============================================================================
// Agent runtime status
//=============================================================================
struct AgentStatus {
bool connected = false;
bool running = false;
uint64_t uptime_seconds = 0;
uint64_t commands_received = 0;
uint64_t commands_executed = 0;
uint64_t heartbeats_sent = 0;
uint64_t telemetry_sent = 0;
uint64_t events_published = 0;
uint64_t reconnect_count = 0;
std::string last_error;
};
//=============================================================================
// DeviceAgent - AIBOX cloud agent
//
// Inject your existing RabbitMQ C++ API via BrokerFactory:
//
// DeviceAgent agent([](){ return std::make_unique<MyRabbitMQBroker>(); });
// agent.configure(config);
// agent.set_command_handler(...);
// agent.start(); // non-blocking
//
//=============================================================================
class ANSCLOUD_DEVICE_API DeviceAgent {
public:
// Construct with broker factory (your RabbitMQ API)
explicit DeviceAgent(BrokerFactory factory);
~DeviceAgent();
// Non-copyable, movable
DeviceAgent(const DeviceAgent&) = delete;
DeviceAgent& operator=(const DeviceAgent&) = delete;
DeviceAgent(DeviceAgent&&) noexcept;
DeviceAgent& operator=(DeviceAgent&&) noexcept;
//--- Configuration (call before start) -----------------------------------
void configure(const DeviceAgentConfig& config);
void set_command_handler(CommandHandler handler);
void set_metrics_provider(MetricsProvider provider);
void set_camera_list_provider(CameraListProvider provider);
void set_inference_provider(InferenceProvider provider);
void set_snapshot_provider(SnapshotProvider provider);
//--- Lifecycle (non-blocking) --------------------------------------------
bool start(); // Connects, declares queues, starts background threads
void stop(); // Publishes offline, disconnects, stops threads
bool is_running() const;
bool is_connected() const;
//--- Manual publishing ---------------------------------------------------
void publish_event(const DeviceEvent& event);
void publish_telemetry(const DeviceTelemetry& telemetry);
void send_heartbeat_now();
void send_metrics_now();
//--- Status & callbacks --------------------------------------------------
AgentStatus get_status() const;
void on_connection_changed(ConnectionCallback cb);
void on_error(ErrorCallback cb);
void on_broadcast(std::function<void(const std::string& message)> cb);
private:
class Impl;
std::unique_ptr<Impl> m_impl;
};
} // namespace anscloud
#endif // ANSCLOUD_DEVICE_AGENT_H

View File

@@ -0,0 +1,114 @@
#pragma once
#ifndef ANSCLOUD_DEVICE_AGENT_C_H
#define ANSCLOUD_DEVICE_AGENT_C_H
#ifdef ANSCLOUD_DEVICE_EXPORTS
#define ANSCLOUD_DEVICE_CAPI __declspec(dllexport)
#else
#define ANSCLOUD_DEVICE_CAPI __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
//=============================================================================
// Opaque handle
//=============================================================================
typedef struct AnsDeviceAgent* AnsDeviceAgentHandle;
//=============================================================================
// C-compatible config structs
//=============================================================================
typedef struct {
const char* host;
int port;
const char* username;
const char* password;
const char* vhost;
int use_tls;
} AnsDeviceBrokerConfig;
typedef struct {
const char* device_id;
const char* device_secret;
const char* tenant_id;
} AnsDeviceCredentials;
typedef struct {
AnsDeviceBrokerConfig broker;
AnsDeviceCredentials credentials;
int heartbeat_interval_sec;
int metrics_interval_sec;
const char* firmware_version;
const char* ansvis_version;
const char* ip_address;
} AnsDeviceConfig;
//=============================================================================
// Callback types
//=============================================================================
// command_json: JSON string of Command. Return: JSON string of CommandResponse.
// Caller must free returned string with ansdevice_free_string().
typedef const char* (*AnsDeviceCommandHandlerFn)(const char* command_json, void* user_data);
// metrics_json: caller must free returned JSON string
typedef const char* (*AnsDeviceMetricsProviderFn)(void* user_data);
typedef void (*AnsDeviceConnectionCallbackFn)(int connected, void* user_data);
typedef void (*AnsDeviceErrorCallbackFn)(const char* error, void* user_data);
typedef void (*AnsDeviceBroadcastCallbackFn)(const char* message, void* user_data);
//=============================================================================
// Lifecycle
//=============================================================================
// broker_factory_fn: function pointer that creates your IMessageBroker.
// For simplicity in C API, pass NULL to use a default (if you register one).
ANSCLOUD_DEVICE_CAPI AnsDeviceAgentHandle ansdevice_create(void);
ANSCLOUD_DEVICE_CAPI void ansdevice_destroy(AnsDeviceAgentHandle handle);
ANSCLOUD_DEVICE_CAPI int ansdevice_configure(AnsDeviceAgentHandle handle, const AnsDeviceConfig* config);
ANSCLOUD_DEVICE_CAPI int ansdevice_start(AnsDeviceAgentHandle handle);
ANSCLOUD_DEVICE_CAPI void ansdevice_stop(AnsDeviceAgentHandle handle);
ANSCLOUD_DEVICE_CAPI int ansdevice_is_running(AnsDeviceAgentHandle handle);
ANSCLOUD_DEVICE_CAPI int ansdevice_is_connected(AnsDeviceAgentHandle handle);
//=============================================================================
// Handlers & providers
//=============================================================================
ANSCLOUD_DEVICE_CAPI void ansdevice_set_command_handler(AnsDeviceAgentHandle handle,
AnsDeviceCommandHandlerFn fn, void* user_data);
ANSCLOUD_DEVICE_CAPI void ansdevice_set_metrics_provider(AnsDeviceAgentHandle handle,
AnsDeviceMetricsProviderFn fn, void* user_data);
//=============================================================================
// Publishing
//=============================================================================
ANSCLOUD_DEVICE_CAPI int ansdevice_publish_event(AnsDeviceAgentHandle handle, const char* event_json);
ANSCLOUD_DEVICE_CAPI void ansdevice_send_heartbeat(AnsDeviceAgentHandle handle);
ANSCLOUD_DEVICE_CAPI void ansdevice_send_metrics(AnsDeviceAgentHandle handle);
//=============================================================================
// Callbacks
//=============================================================================
ANSCLOUD_DEVICE_CAPI void ansdevice_on_connection_changed(AnsDeviceAgentHandle handle,
AnsDeviceConnectionCallbackFn fn, void* user_data);
ANSCLOUD_DEVICE_CAPI void ansdevice_on_error(AnsDeviceAgentHandle handle,
AnsDeviceErrorCallbackFn fn, void* user_data);
ANSCLOUD_DEVICE_CAPI void ansdevice_on_broadcast(AnsDeviceAgentHandle handle,
AnsDeviceBroadcastCallbackFn fn, void* user_data);
//=============================================================================
// Status & memory
//=============================================================================
// Returns JSON string. Caller must free with ansdevice_free_string().
ANSCLOUD_DEVICE_CAPI const char* ansdevice_get_status(AnsDeviceAgentHandle handle);
ANSCLOUD_DEVICE_CAPI void ansdevice_free_string(const char* str);
ANSCLOUD_DEVICE_CAPI const char* ansdevice_version(void);
#ifdef __cplusplus
}
#endif
#endif // ANSCLOUD_DEVICE_AGENT_C_H

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{B1A2C3D4-0001-4000-8000-000000000003}</ProjectGuid>
<RootNamespace>anscloudgateway</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>anscloud-gateway</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;ANSCLOUD_GATEWAY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)include;$(SolutionDir)anscloud-common\include;$(SolutionDir)packages\nlohmann-json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>anscloud-common.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;ANSCLOUD_GATEWAY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)include;$(SolutionDir)anscloud-common\include;$(SolutionDir)packages\nlohmann-json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>anscloud-common.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="include\anscloud\gateway\gateway_agent.h" />
<ClInclude Include="include\anscloud\gateway\gateway_agent_c.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\gateway_agent.cpp" />
<ClCompile Include="src\gateway_agent_c.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\anscloud-common\anscloud-common.vcxproj">
<Project>{B1A2C3D4-0001-4000-8000-000000000001}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@@ -0,0 +1,145 @@
#pragma once
#ifndef ANSCLOUD_GATEWAY_AGENT_H
#define ANSCLOUD_GATEWAY_AGENT_H
#include <anscloud/common/types.h>
#include <anscloud/common/i_message_broker.h>
#include <string>
#include <functional>
#include <memory>
#include <vector>
#include <future>
#ifdef ANSCLOUD_GATEWAY_EXPORTS
#define ANSCLOUD_GATEWAY_API __declspec(dllexport)
#else
#define ANSCLOUD_GATEWAY_API __declspec(dllimport)
#endif
namespace anscloud {
//=============================================================================
// Gateway Configuration
//=============================================================================
struct GatewayCredentials {
std::string username;
std::string password;
std::string vhost = "/";
};
struct GatewayAgentConfig {
BrokerConfig broker;
GatewayCredentials credentials;
int device_timeout_seconds = 90;
int default_command_timeout_seconds = 30;
int max_pending_commands = 1000;
};
struct GatewayStats {
uint64_t commands_sent = 0;
uint64_t commands_responded = 0;
uint64_t commands_timed_out = 0;
uint64_t telemetry_received = 0;
uint64_t events_received = 0;
uint64_t heartbeats_received = 0;
int devices_online = 0;
int devices_total = 0;
int pending_commands = 0;
uint64_t uptime_seconds = 0;
};
struct BatchResult {
std::vector<std::pair<std::string, CommandResult>> results; // device_id -> result
int succeeded = 0;
int failed = 0;
int timed_out = 0;
};
//=============================================================================
// GatewayAgent - CMS gateway for consuming device messages & sending commands
//
// GatewayAgent gw([](){ return std::make_unique<MyRabbitMQBroker>(); });
// gw.configure(config);
// gw.on_telemetry([](const DeviceTelemetry& t){ /* store */ });
// gw.on_event([](const DeviceEvent& e){ /* process */ });
// gw.start();
//
// auto result = gw.send_command("AIBOX-001", CommandType::GetConfig);
//
//=============================================================================
class ANSCLOUD_GATEWAY_API GatewayAgent {
public:
explicit GatewayAgent(BrokerFactory factory);
~GatewayAgent();
GatewayAgent(const GatewayAgent&) = delete;
GatewayAgent& operator=(const GatewayAgent&) = delete;
GatewayAgent(GatewayAgent&&) noexcept;
GatewayAgent& operator=(GatewayAgent&&) noexcept;
//--- Configuration -------------------------------------------------------
void configure(const GatewayAgentConfig& config);
//--- Lifecycle -----------------------------------------------------------
bool start();
void stop();
bool is_running() const;
bool is_connected() const;
//--- Commands (synchronous RPC) ------------------------------------------
CommandResult send_command(const std::string& device_id,
CommandType type,
const std::string& params_json = "{}",
int timeout_seconds = 0); // 0 = use default
std::future<CommandResult> send_command_async(const std::string& device_id,
CommandType type,
const std::string& params_json = "{}",
int timeout_seconds = 0);
CommandResult send_custom_command(const std::string& device_id,
const std::string& custom_type,
const std::string& params_json = "{}",
int timeout_seconds = 0);
void send_command_fire_and_forget(const std::string& device_id,
CommandType type,
const std::string& params_json = "{}");
BatchResult send_batch_command(const std::vector<std::string>& device_ids,
CommandType type,
const std::string& params_json = "{}",
int timeout_seconds = 0);
void send_broadcast(const std::string& message);
//--- Device tracking -----------------------------------------------------
std::vector<DeviceState> get_all_devices() const;
DeviceState get_device(const std::string& device_id) const;
std::vector<DeviceState> get_online_devices() const;
bool is_device_online(const std::string& device_id) const;
//--- Callbacks -----------------------------------------------------------
using TelemetryCallback = std::function<void(const DeviceTelemetry&)>;
using HeartbeatCallback = std::function<void(const Heartbeat&)>;
using EventCallback = std::function<void(const DeviceEvent&)>;
using DeviceStatusCallback = std::function<void(const std::string& device_id, DeviceStatus status)>;
void on_telemetry(TelemetryCallback cb);
void on_heartbeat(HeartbeatCallback cb);
void on_event(EventCallback cb);
void on_device_status_changed(DeviceStatusCallback cb);
void on_connection_changed(ConnectionCallback cb);
void on_error(ErrorCallback cb);
//--- Stats ---------------------------------------------------------------
GatewayStats get_stats() const;
private:
class Impl;
std::unique_ptr<Impl> m_impl;
};
} // namespace anscloud
#endif // ANSCLOUD_GATEWAY_AGENT_H

View File

@@ -0,0 +1,57 @@
#pragma once
#ifndef ANSCLOUD_GATEWAY_AGENT_C_H
#define ANSCLOUD_GATEWAY_AGENT_C_H
#ifdef ANSCLOUD_GATEWAY_EXPORTS
#define ANSCLOUD_GATEWAY_CAPI __declspec(dllexport)
#else
#define ANSCLOUD_GATEWAY_CAPI __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct AnsGatewayAgent* AnsGatewayAgentHandle;
typedef struct {
const char* host;
int port;
const char* username;
const char* password;
const char* vhost;
int use_tls;
} AnsGatewayBrokerConfig;
typedef struct {
const char* username;
const char* password;
const char* vhost;
} AnsGatewayCredentials;
typedef struct {
AnsGatewayBrokerConfig broker;
AnsGatewayCredentials credentials;
int device_timeout_seconds;
int default_command_timeout_seconds;
int max_pending_commands;
} AnsGatewayConfig;
// Callbacks - all receive JSON strings
typedef void (*AnsGatewayTelemetryCallbackFn)(const char* telemetry_json, void* user_data);
typedef void (*AnsGatewayHeartbeatCallbackFn)(const char* heartbeat_json, void* user_data);
typedef void (*AnsGatewayEventCallbackFn)(const char* event_json, void* user_data);
typedef void (*AnsGatewayDeviceStatusCallbackFn)(const char* device_id, const char* status, void* user_data);
typedef void (*AnsGatewayConnectionCallbackFn)(int connected, void* user_data);
typedef void (*AnsGatewayErrorCallbackFn)(const char* error, void* user_data);
//=============================================================================
// Lifecycle
//=============================================================================
ANSCLOUD_GATEWAY_CAPI AnsGatewayAgentHandle ansgateway_create(void);
ANSCLOUD_GATEWAY_CAPI void ansgateway_destroy(AnsGatewayAgentHandle handle);
ANSCLOUD_GATEWAY_CAPI int ansgateway_configure(AnsGatewayAgentHandle handle, const AnsGatewayConfig* config);
ANSCLOUD_GATEWAY_CAPI int ansgateway_start(AnsGatewayAgentHandle handle);
ANSCLOUD_GATEWAY_CAPI void ansgateway_stop(AnsGatewayAgentHandle handle);
ANSCLOUD_GATEWAY_CAPI int ansgateway_is_running(AnsGatewayAgentHandle handle);
ANSCLOUD_GATEWAY_CAPI int ansgateway_is_connected(AnsGatewayAgentHandle handle);

636
architecture-diagram.html Normal file
View File

@@ -0,0 +1,636 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ANSCloud Integration Architecture</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600;700&family=DM+Sans:wght@400;500;600;700&display=swap');
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'DM Sans', sans-serif;
background: #0a0e1a;
color: #e0e4ef;
min-height: 100vh;
padding: 30px 20px;
overflow-x: hidden;
}
.page-title {
text-align: center;
margin-bottom: 40px;
}
.page-title h1 {
font-family: 'JetBrains Mono', monospace;
font-size: 22px;
font-weight: 700;
color: #fff;
letter-spacing: -0.5px;
margin-bottom: 6px;
}
.page-title .sub {
font-size: 13px;
color: #6b7394;
font-weight: 400;
}
/* ── Main Architecture ── */
.arch-container {
max-width: 1100px;
margin: 0 auto 50px;
position: relative;
}
/* ── Tier Section ── */
.tier-section {
margin-bottom: 30px;
position: relative;
}
.tier-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 14px;
}
.tier-badge {
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
font-weight: 700;
padding: 4px 10px;
border-radius: 4px;
letter-spacing: 0.5px;
white-space: nowrap;
}
.tier-1 .tier-badge { background: #1a3a2a; color: #4ade80; border: 1px solid #2d5a3e; }
.tier-2 .tier-badge { background: #1a2a4a; color: #60a5fa; border: 1px solid #2d4a6e; }
.tier-3 .tier-badge { background: #2a1a3a; color: #c084fc; border: 1px solid #4a2d6e; }
.tier-label {
font-size: 15px;
font-weight: 600;
color: #c0c8e0;
}
.tier-desc {
font-size: 12px;
color: #6b7394;
margin-left: auto;
font-style: italic;
}
/* ── Flow Row ── */
.flow-row {
display: flex;
align-items: center;
gap: 0;
padding: 16px 20px;
border-radius: 10px;
position: relative;
overflow: hidden;
}
.tier-1 .flow-row { background: linear-gradient(135deg, #0d1a14 0%, #0f1820 100%); border: 1px solid #1a3a2a; }
.tier-2 .flow-row { background: linear-gradient(135deg, #0d1420 0%, #0f1828 100%); border: 1px solid #1a2a4a; }
.tier-3 .flow-row { background: linear-gradient(135deg, #14101e 0%, #18122a 100%); border: 1px solid #2a1a3a; }
/* ── Boxes ── */
.box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 12px 16px;
border-radius: 8px;
min-width: 120px;
text-align: center;
position: relative;
flex-shrink: 0;
}
.box-icon {
font-size: 20px;
margin-bottom: 5px;
}
.box-title {
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
font-weight: 700;
margin-bottom: 3px;
white-space: nowrap;
}
.box-sub {
font-size: 10px;
color: #6b7394;
line-height: 1.3;
}
/* Box themes */
.box-partner {
background: #141824;
border: 1px solid #2a3050;
min-width: 150px;
}
.box-partner .box-title { color: #94a3c8; }
.box-api {
background: linear-gradient(145deg, #1a3a2a, #153020);
border: 1px solid #2d5a3e;
}
.box-api .box-title { color: #4ade80; }
.box-protocol {
background: linear-gradient(145deg, #1a2a4a, #152040);
border: 1px solid #2d4a6e;
}
.box-protocol .box-title { color: #60a5fa; }
.box-lib {
background: linear-gradient(145deg, #2a1a3a, #201530);
border: 1px solid #4a2d6e;
}
.box-lib .box-title { color: #c084fc; }
.box-broker {
background: linear-gradient(145deg, #2a2010, #201810);
border: 1px solid #5a4a2d;
}
.box-broker .box-title { color: #fbbf24; }
.box-device {
background: linear-gradient(145deg, #1a1418, #201820);
border: 1px solid #4a3040;
}
.box-device .box-title { color: #f472b6; }
.box-gateway {
background: linear-gradient(145deg, #1a2820, #152218);
border: 1px solid #2d5a3e;
}
.box-gateway .box-title { color: #34d399; }
/* ── Arrows ── */
.arrow {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 8px;
flex-shrink: 0;
}
.arrow-line {
font-family: 'JetBrains Mono', monospace;
font-size: 14px;
color: #3a4060;
letter-spacing: -2px;
white-space: nowrap;
}
.arrow-label {
font-family: 'JetBrains Mono', monospace;
font-size: 9px;
font-weight: 600;
white-space: nowrap;
margin-top: 2px;
}
.tier-1 .arrow-label { color: #4ade80; }
.tier-2 .arrow-label { color: #60a5fa; }
.tier-3 .arrow-label { color: #c084fc; }
/* ── Languages list ── */
.lang-tags {
display: flex;
flex-wrap: wrap;
gap: 4px;
margin-top: 6px;
justify-content: center;
}
.lang-tag {
font-family: 'JetBrains Mono', monospace;
font-size: 9px;
padding: 2px 6px;
border-radius: 3px;
background: rgba(255,255,255,0.06);
color: #8890a8;
border: 1px solid rgba(255,255,255,0.08);
}
/* ── Cloud B Detail ── */
.cloud-b-section {
max-width: 1100px;
margin: 0 auto 40px;
}
.cloud-b-section h2 {
font-family: 'JetBrains Mono', monospace;
font-size: 16px;
font-weight: 700;
color: #fbbf24;
margin-bottom: 16px;
display: flex;
align-items: center;
gap: 8px;
}
.cloud-b-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 14px;
}
.cloud-b-card {
background: linear-gradient(145deg, #12161f 0%, #0e1218 100%);
border: 1px solid #1e2438;
border-radius: 10px;
padding: 18px;
position: relative;
}
.cloud-b-card::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 2px;
border-radius: 10px 10px 0 0;
}
.cloud-b-card:nth-child(1)::before { background: #4ade80; }
.cloud-b-card:nth-child(2)::before { background: #fbbf24; }
.cloud-b-card:nth-child(3)::before { background: #f472b6; }
.cloud-b-card h3 {
font-family: 'JetBrains Mono', monospace;
font-size: 12px;
font-weight: 700;
margin-bottom: 10px;
}
.cloud-b-card:nth-child(1) h3 { color: #4ade80; }
.cloud-b-card:nth-child(2) h3 { color: #fbbf24; }
.cloud-b-card:nth-child(3) h3 { color: #f472b6; }
.cb-item {
font-size: 12px;
color: #8890a8;
padding: 4px 0;
border-bottom: 1px solid rgba(255,255,255,0.04);
display: flex;
align-items: flex-start;
gap: 6px;
}
.cb-item:last-child { border: none; }
.cb-dot {
width: 5px;
height: 5px;
border-radius: 50%;
margin-top: 5px;
flex-shrink: 0;
}
.cloud-b-card:nth-child(1) .cb-dot { background: #4ade80; }
.cloud-b-card:nth-child(2) .cb-dot { background: #fbbf24; }
.cloud-b-card:nth-child(3) .cb-dot { background: #f472b6; }
/* ── Comparison Table ── */
.compare-section {
max-width: 1100px;
margin: 0 auto 40px;
}
.compare-section h2 {
font-family: 'JetBrains Mono', monospace;
font-size: 16px;
font-weight: 700;
color: #c0c8e0;
margin-bottom: 16px;
}
.compare-table {
width: 100%;
border-collapse: collapse;
font-size: 12px;
}
.compare-table th {
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
font-weight: 700;
text-align: left;
padding: 10px 14px;
border-bottom: 2px solid #1e2438;
color: #8890a8;
}
.compare-table td {
padding: 10px 14px;
border-bottom: 1px solid #141824;
color: #a0a8c0;
}
.compare-table tr:hover td {
background: rgba(255,255,255,0.02);
}
.compare-table .tier-name {
font-family: 'JetBrains Mono', monospace;
font-weight: 600;
}
.t1c { color: #4ade80; }
.t2c { color: #60a5fa; }
.t3c { color: #c084fc; }
.star { color: #fbbf24; }
.check { color: #4ade80; }
.cross { color: #f87171; opacity: 0.6; }
/* ── RPC Flow ── */
.rpc-section {
max-width: 1100px;
margin: 0 auto 40px;
}
.rpc-section h2 {
font-family: 'JetBrains Mono', monospace;
font-size: 16px;
font-weight: 700;
color: #c0c8e0;
margin-bottom: 16px;
}
.rpc-flow {
background: linear-gradient(145deg, #0e1218 0%, #12161f 100%);
border: 1px solid #1e2438;
border-radius: 10px;
padding: 24px;
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
line-height: 1.8;
overflow-x: auto;
}
.rpc-flow .actor { color: #fbbf24; font-weight: 700; }
.rpc-flow .action { color: #4ade80; }
.rpc-flow .proto { color: #60a5fa; }
.rpc-flow .data { color: #c084fc; }
.rpc-flow .dim { color: #3a4060; }
.rpc-flow .step { color: #f472b6; font-weight: 700; }
/* ── Responsive ── */
@media (max-width: 900px) {
.cloud-b-grid { grid-template-columns: 1fr; }
.flow-row { flex-wrap: wrap; justify-content: center; gap: 8px; }
.arrow { padding: 4px 6px; }
.compare-table { font-size: 11px; }
.compare-table th, .compare-table td { padding: 8px 8px; }
}
</style>
</head>
<body>
<div class="page-title">
<h1>ANSCloud — Partner Integration Architecture</h1>
<div class="sub">3-Tier Integration Strategy: REST API → AMQP Protocol → C++ FFI Library</div>
</div>
<!-- ════════════════════════════════════════════════════ -->
<!-- TIER 1 -->
<!-- ════════════════════════════════════════════════════ -->
<div class="arch-container">
<div class="tier-section tier-1">
<div class="tier-header">
<span class="tier-badge">TIER 1</span>
<span class="tier-label">REST / WebSocket API Gateway</span>
<span class="tier-desc">★ Recommended for most partners</span>
</div>
<div class="flow-row">
<div class="box box-partner">
<div class="box-icon">🌐</div>
<div class="box-title">Partner CMS</div>
<div class="box-sub">Any language</div>
<div class="lang-tags">
<span class="lang-tag">Node.js</span>
<span class="lang-tag">Python</span>
<span class="lang-tag">Go</span>
<span class="lang-tag">Java</span>
<span class="lang-tag">C#</span>
<span class="lang-tag">PHP</span>
<span class="lang-tag">Ruby</span>
</div>
</div>
<div class="arrow">
<div class="arrow-line">──────►</div>
<div class="arrow-label">HTTPS / WSS</div>
</div>
<div class="box box-api">
<div class="box-icon">🛡️</div>
<div class="box-title">API Gateway</div>
<div class="box-sub">Cloud B<br>Auth + Rate Limit</div>
</div>
<div class="arrow">
<div class="arrow-line">──────►</div>
<div class="arrow-label">AMQP internal</div>
</div>
<div class="box box-broker">
<div class="box-icon">📨</div>
<div class="box-title">RabbitMQ</div>
<div class="box-sub">Cloud B<br>Exchanges + Queues</div>
</div>
<div class="arrow">
<div class="arrow-line">──────►</div>
<div class="arrow-label">AMQP TLS</div>
</div>
<div class="box box-device">
<div class="box-icon">📷</div>
<div class="box-title">AIBOX</div>
<div class="box-sub">anscloud-device<br>C++ + Your RabbitMQ API</div>
</div>
</div>
</div>
<!-- ════════════════════════════════════════════════════ -->
<!-- TIER 2 -->
<!-- ════════════════════════════════════════════════════ -->
<div class="tier-section tier-2">
<div class="tier-header">
<span class="tier-badge">TIER 2</span>
<span class="tier-label">Native AMQP Protocol (Direct Broker Access)</span>
<span class="tier-desc">Advanced integrators, on-prem</span>
</div>
<div class="flow-row">
<div class="box box-partner">
<div class="box-icon"></div>
<div class="box-title">Partner CMS</div>
<div class="box-sub">Native AMQP lib</div>
<div class="lang-tags">
<span class="lang-tag">amqplib</span>
<span class="lang-tag">pika</span>
<span class="lang-tag">amqp091-go</span>
<span class="lang-tag">Spring AMQP</span>
</div>
</div>
<div class="arrow">
<div class="arrow-line">════════════════════════►</div>
<div class="arrow-label">AMQP 0-9-1 (direct, same protocol)</div>
</div>
<div class="box box-broker">
<div class="box-icon">📨</div>
<div class="box-title">RabbitMQ</div>
<div class="box-sub">Cloud B<br>Partner vhost</div>
</div>
<div class="arrow">
<div class="arrow-line">──────►</div>
<div class="arrow-label">AMQP TLS</div>
</div>
<div class="box box-device">
<div class="box-icon">📷</div>
<div class="box-title">AIBOX</div>
<div class="box-sub">anscloud-device<br>C++ + Your RabbitMQ API</div>
</div>
</div>
</div>
<!-- ════════════════════════════════════════════════════ -->
<!-- TIER 3 -->
<!-- ════════════════════════════════════════════════════ -->
<div class="tier-section tier-3">
<div class="tier-header">
<span class="tier-badge">TIER 3</span>
<span class="tier-label">C++ Gateway Library via FFI</span>
<span class="tier-desc">Your CMS, embedded, C/C++ partners</span>
</div>
<div class="flow-row">
<div class="box box-partner">
<div class="box-icon">🔧</div>
<div class="box-title">Partner CMS</div>
<div class="box-sub">Links .dll / .so</div>
<div class="lang-tags">
<span class="lang-tag">cgo</span>
<span class="lang-tag">ctypes</span>
<span class="lang-tag">P/Invoke</span>
<span class="lang-tag">ffi-napi</span>
<span class="lang-tag">JNI</span>
</div>
</div>
<div class="arrow">
<div class="arrow-line">──────►</div>
<div class="arrow-label">C API (FFI)</div>
</div>
<div class="box box-lib">
<div class="box-icon">📦</div>
<div class="box-title">anscloud-gateway</div>
<div class="box-sub">C++ lib (CMSCore)<br>gateway_agent_c.h</div>
</div>
<div class="arrow">
<div class="arrow-line">──────►</div>
<div class="arrow-label">Your RabbitMQ API</div>
</div>
<div class="box box-broker">
<div class="box-icon">📨</div>
<div class="box-title">RabbitMQ</div>
<div class="box-sub">Cloud B</div>
</div>
<div class="arrow">
<div class="arrow-line">──────►</div>
<div class="arrow-label">AMQP TLS</div>
</div>
<div class="box box-device">
<div class="box-icon">📷</div>
<div class="box-title">AIBOX</div>
<div class="box-sub">anscloud-device<br>C++ + Your RabbitMQ API</div>
</div>
</div>
</div>
</div>
<!-- ════════════════════════════════════════════════════ -->
<!-- Cloud B Detail -->
<!-- ════════════════════════════════════════════════════ -->
<div class="cloud-b-section">
<h2>☁️ Cloud B — Messaging Platform (You Own)</h2>
<div class="cloud-b-grid">
<div class="cloud-b-card">
<h3>API Gateway Layer</h3>
<div class="cb-item"><div class="cb-dot"></div>REST endpoints for commands, status, telemetry</div>
<div class="cb-item"><div class="cb-dot"></div>WebSocket for real-time event streaming</div>
<div class="cb-item"><div class="cb-dot"></div>Webhook push to partner URLs</div>
<div class="cb-item"><div class="cb-dot"></div>API key auth + JWT per tenant</div>
<div class="cb-item"><div class="cb-dot"></div>Rate limiting per partner tier</div>
<div class="cb-item"><div class="cb-dot"></div>Serves Tier 1 partners</div>
</div>
<div class="cloud-b-card">
<h3>RabbitMQ Broker</h3>
<div class="cb-item"><div class="cb-dot"></div>ex.command → direct → device queues</div>
<div class="cb-item"><div class="cb-dot"></div>ex.device.telemetry → topic → ingest</div>
<div class="cb-item"><div class="cb-dot"></div>ex.device.events → topic → processor</div>
<div class="cb-item"><div class="cb-dot"></div>ex.device.status → topic → tracker</div>
<div class="cb-item"><div class="cb-dot"></div>ex.broadcast → fanout → all devices</div>
<div class="cb-item"><div class="cb-dot"></div>vhost isolation per tenant</div>
</div>
<div class="cloud-b-card">
<h3>AIBOX Devices</h3>
<div class="cb-item"><div class="cb-dot"></div>anscloud-device (C++ static lib)</div>
<div class="cb-item"><div class="cb-dot"></div>Uses YOUR existing RabbitMQ C++ API</div>
<div class="cb-item"><div class="cb-dot"></div>IMessageBroker adapter pattern</div>
<div class="cb-item"><div class="cb-dot"></div>Auto boot → connect → heartbeat</div>
<div class="cb-item"><div class="cb-dot"></div>Publishes telemetry, events, status</div>
<div class="cb-item"><div class="cb-dot"></div>Receives & executes commands</div>
</div>
</div>
</div>
<!-- ════════════════════════════════════════════════════ -->
<!-- RPC Command Flow -->
<!-- ════════════════════════════════════════════════════ -->
<div class="rpc-section">
<h2>Command RPC Flow (Tier 1 Example)</h2>
<div class="rpc-flow">
<span class="step"></span> <span class="actor">Partner</span> <span class="action">POST</span> <span class="proto">/api/v1/devices/AIBOX-001/commands</span> <span class="data">{"command":"get_config"}</span><br>
<span class="dim"></span><br>
<span class="step"></span> <span class="actor">API GW</span> <span class="action">generates</span> <span class="data">cmd_id + correlation_id</span><span class="action">publish to</span> <span class="proto">ex.command</span> <span class="dim">routing_key=AIBOX-001</span><br>
<span class="dim"></span><br>
<span class="step"></span> <span class="actor">RabbitMQ</span> <span class="action">routes</span><span class="proto">q.cmd.AIBOX-001</span><br>
<span class="dim"></span><br>
<span class="step"></span> <span class="actor">AIBOX</span> <span class="action">consumes</span><span class="action">executes locally</span><span class="action">publishes response</span><span class="proto">ex.command.response</span><br>
<span class="dim"></span><br>
<span class="step"></span> <span class="actor">API GW</span> <span class="action">matches</span> <span class="data">correlation_id</span><span class="action">resolves pending request</span><br>
<span class="dim"></span><br>
<span class="step"></span> <span class="actor">Partner</span> <span class="action">receives</span> <span class="proto">HTTP 200</span> <span class="data">{"status":"success","result":{"version":"3.2.0","cameras":3}}</span><br>
<br>
<span class="dim">── Partner sees a simple REST call. RabbitMQ is completely hidden. ──</span>
</div>
</div>
<!-- ════════════════════════════════════════════════════ -->
<!-- Comparison -->
<!-- ════════════════════════════════════════════════════ -->
<div class="compare-section">
<h2>Tier Comparison</h2>
<table class="compare-table">
<thead>
<tr>
<th></th>
<th>Language Support</th>
<th>Setup Effort</th>
<th>Latency</th>
<th>Partner Needs</th>
<th>You Control</th>
<th>Best For</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tier-name t1c">Tier 1 — REST API</td>
<td>Any <span class="star"></span></td>
<td>Minutes <span class="star"></span></td>
<td>~50ms added</td>
<td>API key + docs</td>
<td>Auth, rate limits, versioning <span class="star"></span></td>
<td>SaaS partners, web/mobile</td>
</tr>
<tr>
<td class="tier-name t2c">Tier 2 — AMQP Direct</td>
<td>Has AMQP lib</td>
<td>Hours</td>
<td>Lowest <span class="star"></span></td>
<td>Protocol guide + credentials</td>
<td>vhost isolation</td>
<td>Large integrators, on-prem</td>
</tr>
<tr>
<td class="tier-name t3c">Tier 3 — C++ FFI</td>
<td>Has FFI support</td>
<td>Days</td>
<td>Low</td>
<td>DLL/so + C headers</td>
<td>Full protocol encapsulated</td>
<td>Your CMS, embedded, C++ devs</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{B1A2C3D4-0001-4000-8000-000000000004}</ProjectGuid>
<RootNamespace>testdevice</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>test-device</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)anscloud-common\include;$(SolutionDir)anscloud-device\include;$(SolutionDir)packages\nlohmann-json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>anscloud-common.lib;anscloud-device.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)anscloud-common\include;$(SolutionDir)anscloud-device\include;$(SolutionDir)packages\nlohmann-json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>anscloud-common.lib;anscloud-device.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\anscloud-common\anscloud-common.vcxproj">
<Project>{B1A2C3D4-0001-4000-8000-000000000001}</Project>
</ProjectReference>
<ProjectReference Include="..\anscloud-device\anscloud-device.vcxproj">
<Project>{B1A2C3D4-0001-4000-8000-000000000002}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{B1A2C3D4-0001-4000-8000-000000000005}</ProjectGuid>
<RootNamespace>testgateway</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>test-gateway</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)anscloud-common\include;$(SolutionDir)anscloud-gateway\include;$(SolutionDir)packages\nlohmann-json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>anscloud-common.lib;anscloud-gateway.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)anscloud-common\include;$(SolutionDir)anscloud-gateway\include;$(SolutionDir)packages\nlohmann-json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>anscloud-common.lib;anscloud-gateway.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\anscloud-common\anscloud-common.vcxproj">
<Project>{B1A2C3D4-0001-4000-8000-000000000001}</Project>
</ProjectReference>
<ProjectReference Include="..\anscloud-gateway\anscloud-gateway.vcxproj">
<Project>{B1A2C3D4-0001-4000-8000-000000000003}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>