用户App 使用websocket 访问BaseService ,因此,编写baseService App 时要选择一个websocket 库。我这里选择了websocketpp库。 应用程序client 定时向baseservice 发送 jsonrpc 格式的digitalWrite。
依赖库
该库要使用到 boost 的一些库:
sudo apt-get install libboost-system-dev libboost-thread-dev
编译中增加的boost_system库引用
sudo clang++ client.cpp -I ./include -L ./lib -lpthread -lboost_system -o client -std=c++11
代码
#include <streambuf>
#include <sstream>
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include <websocketpp/config/asio_no_tls_client.hpp>
//#include <websocketpp/config/core.hpp>
#include <websocketpp/client.hpp>
#include "mqtt/mqtt.h"
#include <iostream>
#include <pthread.h>
#include <semaphore.h>
using namespace std;
using namespace rapidjson;
typedef websocketpp::client<websocketpp::config::asio_client> client;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
// pull out the type of messages sent by our config
typedef websocketpp::config::asio_client::message_type::ptr message_ptr;
websocketpp::connection_hdl base_hd;
bool connected=false;
client c;
void * sender_thread(void *arg)
{ int id=0;
int val=0;
websocketpp::lib::error_code ec;
while(true)
{
if (connected)
{
Document message;
message.SetObject();
Document::AllocatorType& allocator = message.GetAllocator();
message.AddMember("jsonrpc","2.0",allocator);
message.AddMember("method","digitalOut.write",allocator);
Value params(kObjectType);
params.AddMember("mode",1,allocator);
params.AddMember("pin",257,allocator);
Value data(kArrayType);
data.PushBack(val, allocator);
if (val==0) {val=1;} else {val=0;}
params.AddMember("value",data,allocator);
message.AddMember("params",params,allocator);
message.AddMember("id",id,allocator);
id=id+1;
if (id>5000) id=0;
StringBuffer buffer;
buffer.Clear();
Writer<StringBuffer> writer(buffer);
message.Accept(writer);
string msg_payload=buffer.GetString();
cout<<"msg payload: "<<msg_payload<<"\n"<<endl;
c.send(base_hd, msg_payload,websocketpp::frame::opcode::TEXT, ec);
if (ec) {
std::cout << "Echo failed because: " << ec.message() << std::endl;
}
}
sleep(1);
}
}
void on_message(client* c, websocketpp::connection_hdl hdl, message_ptr msg) {
string methodName;
base_hd=hdl;
connected=true;
Document req;
req.Parse(msg->get_payload().c_str());
if (req.HasMember("method"))
{
methodName=req["method"].GetString();
cout <<"method: "<< methodName<<endl;
}
}
int main(int argc, char* argv[]) {
cout<<"BaseService C++ App (demo)"<<endl;
pthread_t a_thread;
pthread_create(&a_thread, NULL, sender_thread, NULL);
std::string uri = "ws://localhost:2019/iosocket";
if (argc == 2) {
uri = argv[1];
}
try {
// Set logging to be pretty verbose (everything except message payloads)
// c.set_access_channels(websocketpp::log::alevel::all);
// c.clear_access_channels(websocketpp::log::alevel::frame_payload);
// c.set_access_channels(websocketpp::log::alevel::all);
c.clear_access_channels(websocketpp::log::alevel::all);
// Initialize ASIO
c.init_asio();
// Register our message handler
c.set_message_handler(bind(&on_message,&c,::_1,::_2));
websocketpp::lib::error_code ec;
client::connection_ptr con = c.get_connection(uri, ec);
if (ec) {
std::cout << "could not create connection because: " << ec.message() << std::endl;
return 0;
}
// Note that connect here only requests a connection. No network messages are
// exchanged until the event loop starts running in the next line.
c.connect(con);
// Start the ASIO io_service run loop
// this will cause a single connection to be made to the server. c.run()
// will exit when this connection is closed.
c.run();
} catch (websocketpp::exception const & e) {
std::cout << e.what() << std::endl;
}
}
几点说明
c.set_access_channels(websocketpp::log::alevel::all);
c.clear_access_channels(websocketpp::log::alevel::frame_payload);
这两条语句会显示帧的内容
如果设置为
c.clear_access_channels(websocketpp::log::alevel::all);
将不显示帧的内容