#include "FDClient.h"
#include"TempleMsg.pb.h"
#include"CFdbIfPerson.h"
CBaseWorker FDClient::main_worker;
FDClient::FDClient(const char * name, CBaseWorker * worker)
: CBaseClient(name, worker)
{
mTimer = new CInvokeTimer(this);
mTimer->attach(&main_worker, false);
}
/*向服务器发送请求*/
void FDClient::callServer(CMethodLoopTimer<FDClient>* timer)
{
FDB_LOG_I("****this is client : %s\n", __FUNCTION__);
NFdbTemple::SongId song_id;
song_id.set_id(1234);
CFdbProtoMsgBuilder builder(song_id);
CBaseJob::Ptr ref(new CBaseMessage(NFdbTemple::FdbMediaSvcMsgId::REQ_METADATA));
invoke(ref, builder);/*发送至服务器*/
auto msg = castToMessage<CBaseMessage*>(ref);
printMetadata(objId(), msg->metadata());
if (msg->isStatus())
{
int32_t id;
std::string reason;
if (!msg->decodeStatus(id, reason))
{
FDB_LOG_E("onReply:fail to decode status\n");
return;
}
FDB_LOG_I("sync reply: status is received: msg code: %d, id: %d, reason: %s\n",
msg->code(), id, reason.c_str());
return;
}
NFdbTemple::NowPlayingDetails now_playing;
CFdbProtoMsgParser parser(now_playing);
if (msg->deserialize(parser))
{
auto artist = now_playing.artist().c_str();
auto album = now_playing.album().c_str();
auto genre = now_playing.genre().c_str();
auto title = now_playing.title().c_str();
auto file_name = "";
if (now_playing.has_file_name())
{
file_name = now_playing.file_name().c_str();
}
auto folder_name = "";
if (now_playing.has_folder_name())
{
folder_name = now_playing.folder_name().c_str();
}
int32_t elapse_time = now_playing.elapse_time();
std::cout << artist << album << genre << title << file_name << folder_name << elapse_time << std::endl;
}
else
{
FDB_LOG_I("Error! Unable to decode message!!!\n");
}
invoke(NFdbTemple::FdbMediaSvcMsgId::REQ_METADATA);
}
FDClient::~FDClient()
{
}
/*客户端连接服务器时响应*/
void FDClient::onOnline(const CFdbOnlineInfo & info)
{
FDB_LOG_I("client session online: %d, secure: %d\n", info.mSid, info.mQOS);
mTimer->enable();
CFdbMsgSubscribeList subscribe_list;
/*订阅服务器主动推送的广播消息,消息ID与字符串要求和服务器的广播消息保持一致*/
subscribe_list.addNotifyItem(NFdbTemple::FdbMediaSvcMsgId::NTF_ELAPSE_TIME, "my_filter");
subscribe_list.addNotifyItem(NFdbTemple::FdbMediaSvcMsgId::NTF_ELAPSE_TIME, "raw_buffer");
subscribe_list.addNotifyItem(NTF_CJSON_TEST);
subscribe_list.addNotifyGroup(GROUP_1);
subscribe(subscribe_list, 0, info.mQOS);/*注册广播消息,注册完成系统自动回复*/
}
/*客户端断开时响应*/
void FDClient::onOffline(const CFdbOnlineInfo & info)
{
FDB_LOG_I("client session off:%d, secure:%d\n", info.mSid, info.mQOS);
if (info.mFirstOrLast)
{
mTimer->disable();
}
}
/*收到服务器主动推送的广播消息*/
void FDClient::onBroadcast(CBaseJob::Ptr & msg_ref)
{
auto msg = castToMessage<CBaseMessage*>(msg_ref);
FDB_LOG_I("Broadcast is received:%d, filter: %s, qos:%d\n", msg->code(), msg->topic().c_str(), msg->qos());
switch (msg->code())
{
/*广播消息有消息ID和消息字符串作为标识*/
case NFdbTemple::FdbMediaSvcMsgId::NTF_ELAPSE_TIME:
{
std::string filter(msg->topic());
if (!filter.compare("my_filter"))
{
NFdbTemple::ElapseTime eTime;
CFdbProtoMsgParser parser(eTime);
if (msg->deserialize(parser))
{
FDB_LOG_I("elapse time is received: hour: %d, minute: %d, second: %d", eTime.hour(), eTime.minute(), eTime.second());
std::cout << "Broadcast hour: " << eTime.hour() << ", minute: " << eTime.minute() << ", second: " << eTime.second() << std::endl;
}
else
{
FDB_LOG_E("Unable to decode Elapsetime\n");
}
}
else if (!filter.compare("raw_buffer"))
{
int32_t size = msg->getPayloadSize();
std::cout << "Broadcast size: " << size << std::endl;
FDB_LOG_I("Broadcast of raw buffer is received: size: %d\n", size);
}
}
break;
case NTF_CJSON_TEST:
{
CFdbCJsonMsgParser parser;
if (msg->deserialize(parser))
{
cJSON *f = parser.retrieve();
int birthday = 0;
int id = 0;
const char* name = 0;
if (cJSON_IsObject(f))
{
cJSON *item = cJSON_GetObjectItem(f, "birthday");
if (item && cJSON_IsNumber(item))
{
birthday = item->valueint;
}
item = cJSON_GetObjectItem(f, "id");
if (item && cJSON_IsNumber(item))
{
id = item->valueint;
}
item = cJSON_GetObjectItem(f, "name");
if (item && cJSON_IsString(item))
{
name = item->valuestring;
}
std::cout << "Broadcast json: birthday: " << birthday << ", id: " << id << ", name: " << name << std::endl;
FDB_LOG_I("Broadcast of JSON is: birthday: %d, id: %d, name: %s\n", birthday, id, name);
}
}
else
{
FDB_LOG_E("Broadcast of JSON is: with error!\n");
}
break;
}
case NTF_GROUP_TEST1:
case NTF_GROUP_TEST2:
case NTF_GROUP_TEST3:
FDB_LOG_I("Broadcast of group message %d is received, Init:%d\n", fdbMakeEventCode(msg->code()), msg->isInitialResponse());
std::cout << "Broadcast of group message: " << msg->code() << ", init: " << msg->isInitialResponse() << std::endl;
break;
default:
break;
}
}
void FDClient::onKickDog(CBaseJob::Ptr & msg_ref)
{
CFdbMessage::kickDog(msg_ref, worker(), [](CBaseJob::Ptr &msg_ref) {
CFdbMessage::feedDog(msg_ref);
});
}
/*异步请求时,通过该回调函数获得server回复*/
void FDClient::onReply(CBaseJob::Ptr & msg_ref)
{
auto msg = castToMessage<CBaseMessage*>(msg_ref);
FDB_LOG_I("response is received. sn: %d\n", msg->sn());
printMetadata(objId(), msg->metadata());
switch (msg->code())
{
case NFdbTemple::FdbMediaSvcMsgId::REQ_METADATA:
{
if (msg->isStatus())
{
if (msg->isError())
{
int32_t error_code;
std::string reason;
if (!msg->decodeStatus(error_code, reason))
{
FDB_LOG_E("onReply:fail to decode status\n");
return;
}
FDB_LOG_I("onReply: status is received. msg code: %d, error code: %d, reason: %s\n",
msg->code(), error_code, reason.c_str());
}
return;
}
NFdbTemple::NowPlayingDetails now_playing;
CFdbProtoMsgParser parser(now_playing);
if (msg->deserialize(parser))
{
auto artist = now_playing.artist().c_str();
auto album = now_playing.album().c_str();
auto genre = now_playing.genre().c_str();
auto title = now_playing.title().c_str();
auto file_name = "";
if (now_playing.has_file_name())
{
file_name = now_playing.file_name().c_str();
}
auto folder_name = "";
if (now_playing.has_folder_name())
{
folder_name = now_playing.folder_name().c_str();
}
int32_t elapse_time = now_playing.elapse_time();
FDB_LOG_I("async reply: artist: %s, album: %s, genre: %s, title: %s, file name: %s, folder name: %s",
artist, album, genre, title, file_name, folder_name);
std::cout << "async from server: artist: " << artist << ", album: " << album << ", genre: " << genre << ", title:" << title << ", file name: " << file_name
<< ", folder name: " << folder_name << std::endl;
}
else
{
FDB_LOG_I("Error, unable to decode message\n");
}
}
break;
case NFdbTemple::FdbMediaSvcMsgId::REQ_RAWDATA:
{
if (msg->isStatus())
{
int32_t error_code;
std::string reason;
if (!msg->decodeStatus(error_code, reason))
{
FDB_LOG_E("onReply: fail to decode status\n");
return;
}
FDB_LOG_I("onReply: msg code: %d, error code: %d, reason: %s\n", msg->code(), error_code, reason);
return;
}
CFdbParcelableArray<CPerson> persions;
CFdbParcelableParser parser(persions);
if (!msg->deserialize(parser))
{
FDB_LOG_E("onReply: fail to decode from simple parser\n");
return;
}
std::ostringstream stream;
(void)persions.format(stream);
FDB_LOG_I("onReply:%s\n", stream.str().c_str());
std::cout << "reply from server:" << stream.str().c_str() << std::endl;
}
break;
default:
break;
}
}
/*注册服务器广播消息后的回复*/
void FDClient::onStatus(CBaseJob::Ptr & msg_ref, int32_t error_code, const char * description)
{
auto msg = castToMessage<CBaseMessage*>(msg_ref);
if (msg->isSubscribe())
{
if (!msg->isError())
{
FDB_LOG_I("subscribe is ok, sn:%d\n", msg->sn());
}
}
FDB_LOG_I("reason: %s\n", description);
}
void FDClient::printMetadata(FdbObjectId_t obj_id, const CFdbMsgMetadata * metadata)
{
uint64_t time_c2s;
uint64_t time_s2r;
uint64_t time_r2c;
uint64_t time_total;
CFdbMessage::parseTimestamp(metadata, time_c2s, time_s2r, time_r2c, time_total);
FDB_LOG_I("obj:%d, server:%llu, reply:%llu, receive:%llu, total:%llu\n",
obj_id, time_c2s, time_s2r, time_r2c, time_total);
}
/*周期性地向服务器发送请求*/
CInvokeTimer::CInvokeTimer(FDClient *client)
:CMethodLoopTimer<FDClient>(1000, true, client, &FDClient::callServer)
{}