Initial idea
This commit is contained in:
86
anscloud-gateway/anscloud-gateway.vcxproj
Normal file
86
anscloud-gateway/anscloud-gateway.vcxproj
Normal 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>
|
||||
145
anscloud-gateway/include/anscloud/gateway/gateway_agent.h
Normal file
145
anscloud-gateway/include/anscloud/gateway/gateway_agent.h
Normal 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
|
||||
57
anscloud-gateway/include/anscloud/gateway/gateway_agent_c.h
Normal file
57
anscloud-gateway/include/anscloud/gateway/gateway_agent_c.h
Normal 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);
|
||||
Reference in New Issue
Block a user