|
@@ -0,0 +1,408 @@
|
|
|
+#include "devGrpcClient.h"
|
|
|
+#include <memory>
|
|
|
+#include <string>
|
|
|
+#include <vector>
|
|
|
+#include <thread>
|
|
|
+
|
|
|
+#include "absl/flags/flag.h"
|
|
|
+#include "absl/flags/parse.h"
|
|
|
+//#include "absl/log/check.h"
|
|
|
+
|
|
|
+#include <grpc/support/log.h>
|
|
|
+#include <grpcpp/grpcpp.h>
|
|
|
+
|
|
|
+// 引用protobuf生成的头文件(编译时自动生成)
|
|
|
+#include "device-sm.grpc.pb.h"
|
|
|
+
|
|
|
+using namespace std;
|
|
|
+using grpc::Channel;
|
|
|
+using grpc::ClientAsyncResponseReader;
|
|
|
+using grpc::ClientContext;
|
|
|
+using grpc::CompletionQueue;
|
|
|
+using grpc::Status;
|
|
|
+
|
|
|
+// LoadStringFromFile函数实现
|
|
|
+std::string LoadStringFromFile(std::string path) {
|
|
|
+ std::ifstream file(path);
|
|
|
+ if (!file.is_open()) {
|
|
|
+ std::cout << "Failed to open " << path << std::endl;
|
|
|
+ abort();
|
|
|
+ }
|
|
|
+ std::stringstream sstr;
|
|
|
+ sstr << file.rdbuf();
|
|
|
+ return sstr.str();
|
|
|
+}
|
|
|
+
|
|
|
+// 实现GrpcDeviceClient的派生类
|
|
|
+class GrpcDeviceClientImpl : public GrpcDeviceClient {
|
|
|
+private:
|
|
|
+ // 异步调用结构体(原始逻辑)
|
|
|
+ struct AsyncClientCall {
|
|
|
+ Device::V3::DoResponse reply;
|
|
|
+ ClientContext context;
|
|
|
+ Status status;
|
|
|
+ std::unique_ptr<ClientAsyncResponseReader<Device::V3::DoResponse>> response_reader;
|
|
|
+ };
|
|
|
+
|
|
|
+ std::unique_ptr<Device::V3::Device::Stub> stub_;
|
|
|
+ std::shared_ptr<Channel> channel_;
|
|
|
+ CompletionQueue cq_;
|
|
|
+ std::thread* pthread_ = nullptr;
|
|
|
+ std::vector<AsyncClientCall*> m_reqList;
|
|
|
+ int m_nNeedResult = 0;
|
|
|
+ string m_strDeviceTarget;
|
|
|
+ string m_strDestDeviceUri;
|
|
|
+ string m_strDeviceResource;
|
|
|
+
|
|
|
+ // 异步RPC完成处理(原始逻辑)
|
|
|
+ void AsyncCompleteRpc() {
|
|
|
+ void* got_tag;
|
|
|
+ bool ok = false;
|
|
|
+ int gots = 0;
|
|
|
+
|
|
|
+ while (cq_.Next(&got_tag, &ok)) {
|
|
|
+ AsyncClientCall* call = static_cast<AsyncClientCall*>(got_tag);
|
|
|
+ if (!ok) {
|
|
|
+ std::cerr << "Async RPC failed" << std::endl;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (call->status.ok()) {
|
|
|
+ std::cout << "Device Client received: " << call->reply.respresult() << std::endl;
|
|
|
+ } else {
|
|
|
+ std::cout << "RPC failed" << std::endl;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (++gots >= m_nNeedResult) break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+public:
|
|
|
+ GrpcDeviceClientImpl(std::shared_ptr<Channel> channel) : stub_(Device::V3::Device::NewStub(channel)) {
|
|
|
+ channel_ = channel;
|
|
|
+ }
|
|
|
+
|
|
|
+ ~GrpcDeviceClientImpl() override {
|
|
|
+ if (pthread_) delete pthread_;
|
|
|
+ EndAync();
|
|
|
+ }
|
|
|
+
|
|
|
+ void SetTarget(const char* pszTarget) { m_strDeviceTarget = pszTarget; }
|
|
|
+
|
|
|
+ // 实现纯虚函数(原始逻辑)
|
|
|
+ int OpenDevice(string devUri, string group) override {
|
|
|
+ Device::V3::OpenRequest request;
|
|
|
+ request.set_deviceuri(devUri);
|
|
|
+ request.set_devicegroup(group);
|
|
|
+ m_strDestDeviceUri = devUri;
|
|
|
+ m_strDeviceResource = "";
|
|
|
+
|
|
|
+ Device::V3::OpenReply reply;
|
|
|
+ ClientContext context;
|
|
|
+ Status status = stub_->Open(&context, request, &reply);
|
|
|
+
|
|
|
+ if (status.ok()) {
|
|
|
+ cout << "Open " << devUri << " Result:" << reply.message() << endl;
|
|
|
+ int retcode = atoi(reply.retcode().c_str());
|
|
|
+ if (2 == retcode) {
|
|
|
+ m_strDeviceResource = reply.retcontext();
|
|
|
+ }
|
|
|
+ return retcode;
|
|
|
+ } else {
|
|
|
+ std::cout << status.error_code() << ": " << status.error_message() << std::endl;
|
|
|
+ return -status.error_code();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ int CloseDevice() override { return 2; }
|
|
|
+
|
|
|
+ string GetDeviceTarget() override { return m_strDeviceTarget; }
|
|
|
+ int GetClientStatus() override { return channel_->GetState(true); }
|
|
|
+ string GetOpendDeviceResource() override { return m_strDeviceResource; }
|
|
|
+
|
|
|
+ // 同步接口实现(原始逻辑)
|
|
|
+ int Get(string devResource, string& devRes, string& calResMsg,
|
|
|
+ string devUri, string calSection, string calClientID) override {
|
|
|
+ Device::V3::DoRequest getq;
|
|
|
+ getq.set_deviceuri(devUri.empty() ? m_strDestDeviceUri : devUri);
|
|
|
+ getq.set_reqname(devResource);
|
|
|
+ getq.set_reqtransaction(calSection);
|
|
|
+ getq.set_reqclientid(calClientID);
|
|
|
+
|
|
|
+ ClientContext context2;
|
|
|
+ Device::V3::DoResponse getr;
|
|
|
+ Status status = stub_->Get(&context2, getq, &getr);
|
|
|
+
|
|
|
+ if (status.ok()) {
|
|
|
+ if (getr.retcode() == "2") {
|
|
|
+ cout << "Get " << devResource << " Result " << getr.retcontext() << endl;
|
|
|
+ devRes = getr.retcontext();
|
|
|
+ calResMsg = getr.respresult();
|
|
|
+ } else {
|
|
|
+ cout << "Get " << devResource << " failed: " << getr.retcode() << endl;
|
|
|
+ }
|
|
|
+ return atoi(getr.retcode().c_str());
|
|
|
+ }
|
|
|
+ cout << "get failed " << devResource << endl;
|
|
|
+ cout << "error :" << status.error_message() << " with detail " << status.error_details() << endl;
|
|
|
+ return -status.error_code();
|
|
|
+ }
|
|
|
+
|
|
|
+ int Set(string devResource, string reqParams, string& devRes, string& calResMsg,
|
|
|
+ string devUri, string calSection, string calClientID) override {
|
|
|
+ Device::V3::DoRequest setq;
|
|
|
+ setq.set_deviceuri(devUri.empty() ? m_strDestDeviceUri : devUri);
|
|
|
+ setq.set_reqname(devResource);
|
|
|
+ setq.set_reqparam(reqParams);
|
|
|
+ setq.set_reqtransaction(calSection);
|
|
|
+ setq.set_reqclientid(calClientID);
|
|
|
+
|
|
|
+ ClientContext context2;
|
|
|
+ Device::V3::DoResponse setr;
|
|
|
+ Status status = stub_->Set(&context2, setq, &setr);
|
|
|
+
|
|
|
+ if (status.ok()) {
|
|
|
+ if (setr.retcode() == "2") {
|
|
|
+ cout << "Set " << devResource << " Result" << setr.retcontext() << endl;
|
|
|
+ devRes = setr.retcontext();
|
|
|
+ calResMsg = setr.respresult();
|
|
|
+ } else {
|
|
|
+ cout << "Set " << devResource << " failed" << setr.retcode() << endl;
|
|
|
+ }
|
|
|
+ return atoi(setr.retcode().c_str());
|
|
|
+ }
|
|
|
+ return -100;
|
|
|
+ }
|
|
|
+
|
|
|
+ int Update(string devResource, string reqParams, string& devRes, string& calResMsg,
|
|
|
+ string devUri, string calSection, string calClientID) override {
|
|
|
+ Device::V3::DoRequest setq;
|
|
|
+ setq.set_deviceuri(devUri.empty() ? m_strDestDeviceUri : devUri);
|
|
|
+ setq.set_reqname(devResource);
|
|
|
+ setq.set_reqparam(reqParams);
|
|
|
+ setq.set_reqtransaction(calSection);
|
|
|
+ setq.set_reqclientid(calClientID);
|
|
|
+
|
|
|
+ ClientContext context2;
|
|
|
+ Device::V3::DoResponse setr;
|
|
|
+ Status status = stub_->Update(&context2, setq, &setr);
|
|
|
+
|
|
|
+ if (status.ok()) {
|
|
|
+ if (setr.retcode() == "2") {
|
|
|
+ cout << "Update " << devResource << " Result" << setr.retcontext() << endl;
|
|
|
+ devRes = setr.retcontext();
|
|
|
+ calResMsg = setr.respresult();
|
|
|
+ } else {
|
|
|
+ cout << "Update " << devResource << " failed" << setr.retcode() << endl;
|
|
|
+ }
|
|
|
+ return atoi(setr.retcode().c_str());
|
|
|
+ }
|
|
|
+ return -100;
|
|
|
+ }
|
|
|
+
|
|
|
+ int Add(string devResource, string reqParams, string& devRes, string& calResMsg,
|
|
|
+ string devUri, string calSection, string calClientID) override {
|
|
|
+ Device::V3::DoRequest setq;
|
|
|
+ setq.set_deviceuri(devUri.empty() ? m_strDestDeviceUri : devUri);
|
|
|
+ setq.set_reqname(devResource);
|
|
|
+ setq.set_reqparam(reqParams);
|
|
|
+ setq.set_reqtransaction(calSection);
|
|
|
+ setq.set_reqclientid(calClientID);
|
|
|
+
|
|
|
+ ClientContext context2;
|
|
|
+ Device::V3::DoResponse setr;
|
|
|
+ Status status = stub_->Add(&context2, setq, &setr);
|
|
|
+
|
|
|
+ if (status.ok()) {
|
|
|
+ if (setr.retcode() == "2") {
|
|
|
+ cout << "Add " << devResource << " Result" << setr.retcontext() << endl;
|
|
|
+ devRes = setr.retcontext();
|
|
|
+ calResMsg = setr.respresult();
|
|
|
+ } else {
|
|
|
+ cout << "Add " << devResource << " failed" << setr.retcode() << endl;
|
|
|
+ }
|
|
|
+ return atoi(setr.retcode().c_str());
|
|
|
+ }
|
|
|
+ return -100;
|
|
|
+ }
|
|
|
+
|
|
|
+ int Del(string devResource, string reqParams, string& devRes, string& calResMsg,
|
|
|
+ string devUri, string calSection, string calClientID) override {
|
|
|
+ Device::V3::DoRequest setq;
|
|
|
+ setq.set_deviceuri(devUri.empty() ? m_strDestDeviceUri : devUri);
|
|
|
+ setq.set_reqname(devResource);
|
|
|
+ setq.set_reqparam(reqParams);
|
|
|
+ setq.set_reqtransaction(calSection);
|
|
|
+ setq.set_reqclientid(calClientID);
|
|
|
+
|
|
|
+ ClientContext context2;
|
|
|
+ Device::V3::DoResponse setr;
|
|
|
+ Status status = stub_->Del(&context2, setq, &setr);
|
|
|
+
|
|
|
+ if (status.ok()) {
|
|
|
+ if (setr.retcode() == "2") {
|
|
|
+ cout << "Del " << devResource << " Result" << setr.retcontext() << endl;
|
|
|
+ devRes = setr.retcontext();
|
|
|
+ calResMsg = setr.respresult();
|
|
|
+ } else {
|
|
|
+ cout << "Del " << devResource << " failed" << setr.retcode() << endl;
|
|
|
+ }
|
|
|
+ return atoi(setr.retcode().c_str());
|
|
|
+ }
|
|
|
+ return -100;
|
|
|
+ }
|
|
|
+
|
|
|
+ int Action(string devResource, string reqParams, string& devRes, string& calResMsg,
|
|
|
+ string devUri, string calSection, string calClientID) override {
|
|
|
+ Device::V3::DoRequest setq;
|
|
|
+ setq.set_deviceuri(devUri.empty() ? m_strDestDeviceUri : devUri);
|
|
|
+ setq.set_reqname(devResource);
|
|
|
+ setq.set_reqparam(reqParams);
|
|
|
+ setq.set_reqtransaction(calSection);
|
|
|
+ setq.set_reqclientid(calClientID);
|
|
|
+
|
|
|
+ ClientContext context2;
|
|
|
+ Device::V3::DoResponse setr;
|
|
|
+ Status status = stub_->Action(&context2, setq, &setr);
|
|
|
+
|
|
|
+ if (status.ok()) {
|
|
|
+ if (setr.retcode() == "2") {
|
|
|
+ cout << "Action " << devResource << " Result: " << setr.retcontext() << endl;
|
|
|
+ devRes = setr.retcontext();
|
|
|
+ calResMsg = setr.respresult();
|
|
|
+ } else {
|
|
|
+ cout << "Action " << devResource << " failed: " << setr.retcode() << endl;
|
|
|
+ }
|
|
|
+ return atoi(setr.retcode().c_str());
|
|
|
+ }
|
|
|
+ cout << "action failed " << devResource << endl;
|
|
|
+ cout << "error :" << status.error_message() << " with detail " << status.error_details() << endl;
|
|
|
+ return -status.error_code();
|
|
|
+ }
|
|
|
+
|
|
|
+ int Message(string devResource, string reqParams, string& devRes, string& calResMsg,
|
|
|
+ string devUri, string calSection, string calClientID) override {
|
|
|
+ Device::V3::DoRequest setq;
|
|
|
+ setq.set_deviceuri(devUri.empty() ? m_strDestDeviceUri : devUri);
|
|
|
+ setq.set_reqname(devResource);
|
|
|
+ setq.set_reqparam(reqParams);
|
|
|
+ setq.set_reqtransaction(calSection);
|
|
|
+ setq.set_reqclientid(calClientID);
|
|
|
+
|
|
|
+ ClientContext context2;
|
|
|
+ Device::V3::DoResponse setr;
|
|
|
+ Status status = stub_->Message(&context2, setq, &setr);
|
|
|
+
|
|
|
+ if (status.ok()) {
|
|
|
+ if (setr.retcode() == "2") {
|
|
|
+ cout << "Message " << devResource << " Result" << setr.retcontext() << endl;
|
|
|
+ devRes = setr.retcontext();
|
|
|
+ calResMsg = setr.respresult();
|
|
|
+ } else {
|
|
|
+ cout << "Message " << devResource << " failed" << setr.retcode() << endl;
|
|
|
+ }
|
|
|
+ return atoi(setr.retcode().c_str());
|
|
|
+ }
|
|
|
+ return -100;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 异步接口实现(原始逻辑)
|
|
|
+ int AsyncAction(string devResource, string reqParams, string devUri, string calSection, string calClientID) override {
|
|
|
+ Device::V3::DoRequest setq;
|
|
|
+ setq.set_deviceuri(devUri.empty() ? m_strDestDeviceUri : devUri);
|
|
|
+ setq.set_reqname(devResource);
|
|
|
+ setq.set_reqparam(reqParams);
|
|
|
+ setq.set_reqtransaction(calSection);
|
|
|
+ setq.set_reqclientid(calClientID);
|
|
|
+
|
|
|
+ AsyncClientCall* call = new AsyncClientCall;
|
|
|
+ call->response_reader = stub_->PrepareAsyncAction(&call->context, setq, &cq_);
|
|
|
+ call->response_reader->StartCall();
|
|
|
+ call->response_reader->Finish(&call->reply, &call->status, (void*)call);
|
|
|
+
|
|
|
+ m_reqList.push_back(call);
|
|
|
+ m_nNeedResult = m_reqList.size();
|
|
|
+ return m_nNeedResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ int AsyncMessage(string devResource, string reqParams, string devUri, string calSection, string calClientID) override {
|
|
|
+ Device::V3::DoRequest setq;
|
|
|
+ setq.set_deviceuri(devUri.empty() ? m_strDestDeviceUri : devUri);
|
|
|
+ setq.set_reqname(devResource);
|
|
|
+ setq.set_reqparam(reqParams);
|
|
|
+ setq.set_reqtransaction(calSection);
|
|
|
+ setq.set_reqclientid(calClientID);
|
|
|
+
|
|
|
+ AsyncClientCall* call = new AsyncClientCall;
|
|
|
+ call->response_reader = stub_->PrepareAsyncMessage(&call->context, setq, &cq_);
|
|
|
+ call->response_reader->StartCall();
|
|
|
+ call->response_reader->Finish(&call->reply, &call->status, (void*)call);
|
|
|
+
|
|
|
+ m_reqList.push_back(call);
|
|
|
+ m_nNeedResult = m_reqList.size();
|
|
|
+ return m_nNeedResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ int BeginAyncWait() override {
|
|
|
+ if (!m_reqList.empty()) {
|
|
|
+ for (auto var : m_reqList) delete var;
|
|
|
+ m_reqList.clear();
|
|
|
+ }
|
|
|
+ pthread_ = new std::thread(&GrpcDeviceClientImpl::AsyncCompleteRpc, this);
|
|
|
+ return 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ void WaitAllComplete() override {
|
|
|
+ if (pthread_) {
|
|
|
+ pthread_->join();
|
|
|
+ delete pthread_;
|
|
|
+ pthread_ = nullptr;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ int GetAsyncResult(int idx, string& devResource, string& devRes, string& calResMsg) override {
|
|
|
+ if (idx < m_reqList.size()) {
|
|
|
+ devResource = m_reqList[idx]->reply.reqname();
|
|
|
+ if (m_reqList[idx]->status.ok()) {
|
|
|
+ if (m_reqList[idx]->reply.retcode() == "2") {
|
|
|
+ cout << "Action " << devResource << " Result: " << m_reqList[idx]->reply.retcontext() << endl;
|
|
|
+ devRes = m_reqList[idx]->reply.retcontext();
|
|
|
+ calResMsg = m_reqList[idx]->reply.respresult();
|
|
|
+ } else {
|
|
|
+ cout << "Action " << devResource << " failed: " << m_reqList[idx]->reply.retcode() << endl;
|
|
|
+ }
|
|
|
+ return atoi(m_reqList[idx]->reply.retcode().c_str());
|
|
|
+ }
|
|
|
+ cout << "action failed " << devResource << endl;
|
|
|
+ cout << "error :" << m_reqList[idx]->status.error_message() << " with detail " << m_reqList[idx]->status.error_details() << endl;
|
|
|
+ return -m_reqList[idx]->status.error_code();
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ void EndAync() override {
|
|
|
+ for (auto var : m_reqList) delete var;
|
|
|
+ m_reqList.clear();
|
|
|
+ m_nNeedResult = 0;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 工厂函数实现:创建/释放客户端
|
|
|
+GRPC_DEVICE_API GrpcDeviceClient* CreateClient(const char* pszDeviceServerTarget) {
|
|
|
+ std::string target_str = pszDeviceServerTarget;
|
|
|
+ cout << "try connect " << target_str << endl;
|
|
|
+
|
|
|
+ grpc::SslCredentialsOptions ssl_options;
|
|
|
+ ssl_options.pem_root_certs = LoadStringFromFile("root.crt"); // 注意:证书路径可能需要调整
|
|
|
+ auto channel = grpc::CreateChannel(target_str, grpc::SslCredentials(ssl_options));
|
|
|
+
|
|
|
+ GrpcDeviceClientImpl* pClient = new GrpcDeviceClientImpl(channel);
|
|
|
+ cout << "Connect " << target_str << " status: " << pClient->GetClientStatus() << endl;
|
|
|
+ pClient->SetTarget(pszDeviceServerTarget);
|
|
|
+
|
|
|
+ return pClient;
|
|
|
+}
|
|
|
+
|
|
|
+GRPC_DEVICE_API void FreeClient(GrpcDeviceClient* pClient) {
|
|
|
+ if (pClient != nullptr) delete pClient;
|
|
|
+}
|