Files
HC900-Crawler/industrial-comm/cpp/include/gateway.h
windpacer 16fc7a2598 Initial commit: HC900 Crawler
Honeywell HC900을 Modbus TCP로 직접 폴링 → gRPC → C# 크롤러 → PostgreSQL.
기존 Experion OPC UA 데이터 경로를 HC900 직접 통신으로 대체.

- industrial-comm/cpp: C++ Modbus 게이트웨이 (gRPC 서버)
- src: C# .NET 8 ASP.NET Core 크롤러 + 웹 UI (3-Layer)
- mcp-server: Python FastMCP (RAG/NL2SQL/P&ID)
- 다중 컨트롤러(N-Controller) 지원

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 20:28:14 +09:00

104 lines
3.2 KiB
C++

#ifndef HC900_GATEWAY_H
#define HC900_GATEWAY_H
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <atomic>
#include <thread>
#include <mutex>
#include <chrono>
#include "modbus_gateway.grpc.pb.h"
#include "modbus_gateway.pb.h"
class Controller;
struct RegisterEntry {
std::string tag;
uint32_t addr;
uint32_t count; // register count (1 or 2)
std::string type; // "float32" or "uint16"
std::string access; // "R" or "RW"
};
struct CachedValue {
float float32_val;
uint32_t uint16_val;
bool is_float;
uint32_t quality; // 192=good, 0=bad
std::chrono::system_clock::time_point timestamp;
};
class Hc900Gateway final {
public:
Hc900Gateway(const std::string& host, uint16_t port,
const std::string& map_path,
int poll_interval_ms = 1000,
int grpc_port = 50051);
~Hc900Gateway();
bool Start();
void Stop();
private:
void PollLoop();
void LoadRegisterMap(const std::string& path);
void ReadAllRegisters();
CachedValue ReadRegister(const RegisterEntry& entry);
// gRPC service implementation
class GatewayServiceImpl final : public hc900::ModbusGateway::Service {
public:
GatewayServiceImpl(Hc900Gateway& gateway);
grpc::Status ReadTags(grpc::ServerContext* ctx,
const hc900::ReadTagsRequest* req,
hc900::ReadTagsResponse* resp) override;
grpc::Status WriteTag(grpc::ServerContext* ctx,
const hc900::WriteTagRequest* req,
hc900::WriteTagResponse* resp) override;
grpc::Status ListTags(grpc::ServerContext* ctx,
const hc900::ListTagsRequest* req,
hc900::ListTagsResponse* resp) override;
grpc::Status HealthCheck(grpc::ServerContext* ctx,
const hc900::HealthCheckRequest* req,
hc900::HealthCheckResponse* resp) override;
grpc::Status StreamTags(grpc::ServerContext* ctx,
const hc900::StreamTagsRequest* req,
grpc::ServerWriter<hc900::TagValue>* writer) override;
private:
Hc900Gateway& gateway_;
};
std::string host_;
uint16_t port_;
int poll_interval_ms_;
std::unique_ptr<Controller> controller_;
// Register map
std::vector<RegisterEntry> registers_;
std::unordered_map<std::string, size_t> tag_index_;
std::vector<size_t> sorted_indices_; // indices into registers_, sorted by address
// Cache
std::unordered_map<std::string, CachedValue> cache_;
mutable std::mutex cache_mutex_;
// Transport — shared between poll thread and gRPC handlers
mutable std::mutex transport_mutex_;
// Poller
std::atomic<bool> running_;
std::thread poll_thread_;
uint64_t poll_count_{0};
std::chrono::milliseconds last_poll_duration_{0};
// gRPC server
std::unique_ptr<grpc::Server> grpc_server_;
std::unique_ptr<GatewayServiceImpl> grpc_service_;
std::string grpc_listen_;
};
#endif // HC900_GATEWAY_H