Files
ANSCMSCORE/_gen_src_06.py

288 lines
10 KiB
Python
Raw Normal View History

2026-03-28 12:05:34 +11:00
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")