fixed: get full json objects from the tcp stream, and parse them

This commit is contained in:
Bob 2021-09-26 23:01:15 +02:00
parent fd151cf7df
commit 0f32809b74
2 changed files with 68 additions and 9 deletions

View file

@ -21,6 +21,7 @@
#include <cstdio> #include <cstdio>
#include <unistd.h> #include <unistd.h>
#include <cstdint>
#include <iostream> #include <iostream>
#include <boost/asio.hpp> #include <boost/asio.hpp>
@ -61,22 +62,63 @@ void CKodiClient::Process()
printf("Connected to Kodi\n"); printf("Connected to Kodi\n");
//Keep reading data from Kodi, when the tcp socket is closed an exception is thrown. //Keep reading data from Kodi, when the tcp socket is closed an exception is thrown.
uint32_t bracketlevel = 0;
bool instring = false;
bool escaped = false;
std::string jsonstr;
for(;;) for(;;)
{ {
boost::asio::streambuf receive_buffer; boost::asio::streambuf receive_buffer;
size_t readbytes = boost::asio::read(socket, receive_buffer, boost::asio::transfer_at_least(1)); size_t bytesread = boost::asio::read(socket, receive_buffer, boost::asio::transfer_at_least(1));
const char* data = boost::asio::buffer_cast<const char*>(receive_buffer.data()); const char* data = boost::asio::buffer_cast<const char*>(receive_buffer.data());
//TODO: because of TCP, one read does not exactly equal one JSON object. //Parse the JSON data into separate JSON objects by finding the text from
json jsondata = json::parse(data); //the starting { to ending }, while ignoring curly brackets in strings.
for (uint32_t i = 0; i < (uint32_t)bytesread; i++)
//If Kodi signals a Player.OnPlay notification, the amplifier should be turned on.
if (jsondata.contains("method"))
{ {
if (jsondata["method"] == "Player.OnPlay") jsonstr.push_back(data[i]);
if (!instring)
{ {
printf("Player started\n"); if (data[i] == '"')
m_ampswitch->SignalPlayStart(); {
instring = true;
}
else if (data[i] == '{')
{
bracketlevel++;
}
else if (data[i] == '}')
{
if (bracketlevel > 0)
{
bracketlevel--;
if (bracketlevel == 0)
{
Parse(jsonstr);
jsonstr.clear();
}
}
else
{
jsonstr.clear(); //Shouldn't happen.
}
}
}
else
{
if (!escaped)
{
if (data[i] == '\\')
escaped = true;
else if (data[i] == '"')
instring = false;
}
else
{
escaped = false;
}
} }
} }
} }
@ -89,3 +131,18 @@ void CKodiClient::Process()
} }
} }
} }
void CKodiClient::Parse(const std::string& jsonstr)
{
json jsondata = json::parse(jsonstr);
//If Kodi signals a Player.OnPlay notification, the amplifier should be turned on.
if (jsondata.contains("method"))
{
if (jsondata["method"] == "Player.OnPlay")
{
printf("Player started\n");
m_ampswitch->SignalPlayStart();
}
}
}

View file

@ -20,6 +20,7 @@
#define KODICLIENT_H #define KODICLIENT_H
#include <thread> #include <thread>
#include <string>
class CAmpSwitch; class CAmpSwitch;
@ -31,6 +32,7 @@ class CKodiClient
private: private:
static void SProcess(CKodiClient* kodiclient); static void SProcess(CKodiClient* kodiclient);
void Process(); void Process();
void Parse(const std::string& jsonstr);
std::thread m_thread; std::thread m_thread;
CAmpSwitch* m_ampswitch; CAmpSwitch* m_ampswitch;