Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
hfedcba committed Apr 13, 2018
2 parents d2d2d18 + acd5b8d commit 83f922a
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 123 deletions.
2 changes: 2 additions & 0 deletions misc/Config Directory/sonos.conf
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ ___________________________________________________________________________

[General]

moduleEnabled = true

# Sonos data path. Here you can place your audio files.
dataPath = /var/lib/homegear/audio

Expand Down
66 changes: 62 additions & 4 deletions src/Sonos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,68 @@ PVariable Sonos::getPairingInfo()
{
try
{
if(!_central) return PVariable(new Variable(VariableType::tArray));
PVariable array(new Variable(VariableType::tArray));
array->arrayValue->push_back(PVariable(new Variable(std::string("searchDevices"))));
return array;
if(!_central) return std::make_shared<BaseLib::Variable>(BaseLib::VariableType::tStruct);
PVariable info = std::make_shared<BaseLib::Variable>(BaseLib::VariableType::tStruct);

//{{{ General
info->structValue->emplace("searchInterfaces", std::make_shared<BaseLib::Variable>(false));
//}}}

//{{{ Family settings
PVariable familySettings = std::make_shared<BaseLib::Variable>(BaseLib::VariableType::tStruct);
info->structValue->emplace("familySettings", familySettings);
//}}}

//{{{ Pairing methods
PVariable pairingMethods = std::make_shared<BaseLib::Variable>(BaseLib::VariableType::tStruct);
pairingMethods->structValue->emplace("searchDevices", std::make_shared<BaseLib::Variable>(BaseLib::VariableType::tStruct));
info->structValue->emplace("pairingMethods", pairingMethods);
//}}}

//{{{ interfaces
auto interfaces = std::make_shared<BaseLib::Variable>(BaseLib::VariableType::tStruct);

//{{{ Event server
auto interface = std::make_shared<BaseLib::Variable>(BaseLib::VariableType::tStruct);
interface->structValue->emplace("name", std::make_shared<BaseLib::Variable>(std::string("Event Server")));
interface->structValue->emplace("ipDevice", std::make_shared<BaseLib::Variable>(false));
interface->structValue->emplace("predefined", std::make_shared<BaseLib::Variable>(true));

auto field = std::make_shared<BaseLib::Variable>(BaseLib::VariableType::tStruct);
field->structValue->emplace("pos", std::make_shared<BaseLib::Variable>(0));
field->structValue->emplace("label", std::make_shared<BaseLib::Variable>(std::string("l10n.common.id")));
field->structValue->emplace("type", std::make_shared<BaseLib::Variable>(std::string("string")));
interface->structValue->emplace("id", field);

field = std::make_shared<BaseLib::Variable>(BaseLib::VariableType::tStruct);
field->structValue->emplace("pos", std::make_shared<BaseLib::Variable>(2));
field->structValue->emplace("label", std::make_shared<BaseLib::Variable>(std::string("l10n.common.listenip")));
field->structValue->emplace("type", std::make_shared<BaseLib::Variable>(std::string("string")));
field->structValue->emplace("required", std::make_shared<BaseLib::Variable>(false));
interface->structValue->emplace("host", field);

field = std::make_shared<BaseLib::Variable>(BaseLib::VariableType::tStruct);
field->structValue->emplace("pos", std::make_shared<BaseLib::Variable>(3));
field->structValue->emplace("label", std::make_shared<BaseLib::Variable>(std::string("l10n.common.listenport")));
field->structValue->emplace("type", std::make_shared<BaseLib::Variable>(std::string("string")));
field->structValue->emplace("default", std::make_shared<BaseLib::Variable>(std::string("7373")));
field->structValue->emplace("required", std::make_shared<BaseLib::Variable>(true));
interface->structValue->emplace("port", field);

field = std::make_shared<BaseLib::Variable>(BaseLib::VariableType::tStruct);
field->structValue->emplace("pos", std::make_shared<BaseLib::Variable>(4));
field->structValue->emplace("label", std::make_shared<BaseLib::Variable>(std::string("l10n.common.ttsprogram")));
field->structValue->emplace("type", std::make_shared<BaseLib::Variable>(std::string("string")));
field->structValue->emplace("required", std::make_shared<BaseLib::Variable>(false));
interface->structValue->emplace("ttsProgram", field);

interfaces->structValue->emplace("eventserver", interface);
//}}}

info->structValue->emplace("interfaces", interfaces);
//}}}

return info;
}
catch(const std::exception& ex)
{
Expand Down
123 changes: 12 additions & 111 deletions src/SonosCentral.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,8 @@ void SonosCentral::deletePeer(uint64_t id)
channels->arrayValue->push_back(PVariable(new Variable(i->first)));
}

raiseRPCDeleteDevices(deviceAddresses, deviceInfo);
std::vector<uint64_t> deletedIds{ id };
raiseRPCDeleteDevices(deletedIds, deviceAddresses, deviceInfo);

{
std::lock_guard<std::mutex> peersGuard(_peersMutex);
Expand Down Expand Up @@ -990,13 +991,14 @@ PVariable SonosCentral::deleteDevice(BaseLib::PRpcClientInfo clientInfo, uint64_
try
{
if(peerID == 0) return Variable::createError(-2, "Unknown device.");
std::shared_ptr<SonosPeer> peer = getPeer(peerID);
if(!peer) return PVariable(new Variable(VariableType::tVoid));
uint64_t id = peer->getID();
{
std::shared_ptr<SonosPeer> peer = getPeer(peerID);
if(!peer) return PVariable(new Variable(VariableType::tVoid));
}

deletePeer(id);
deletePeer(peerID);

if(peerExists(id)) return Variable::createError(-1, "Error deleting peer. See log for more details.");
if(peerExists(peerID)) return Variable::createError(-1, "Error deleting peer. See log for more details.");

return PVariable(new Variable(VariableType::tVoid));
}
Expand All @@ -1015,110 +1017,6 @@ PVariable SonosCentral::deleteDevice(BaseLib::PRpcClientInfo clientInfo, uint64_
return Variable::createError(-32500, "Unknown application error.");
}

PVariable SonosCentral::getDeviceInfo(BaseLib::PRpcClientInfo clientInfo, uint64_t id, std::map<std::string, bool> fields)
{
try
{
if(id > 0)
{
std::shared_ptr<SonosPeer> peer(getPeer(id));
if(!peer) return Variable::createError(-2, "Unknown device.");

return peer->getDeviceInfo(clientInfo, fields);
}
else
{
PVariable array(new Variable(VariableType::tArray));

std::vector<std::shared_ptr<SonosPeer>> peers;
//Copy all peers first, because listDevices takes very long and we don't want to lock _peersMutex too long
_peersMutex.lock();
for(std::map<uint64_t, std::shared_ptr<BaseLib::Systems::Peer>>::iterator i = _peersById.begin(); i != _peersById.end(); ++i)
{
peers.push_back(std::dynamic_pointer_cast<SonosPeer>(i->second));
}
_peersMutex.unlock();

for(std::vector<std::shared_ptr<SonosPeer>>::iterator i = peers.begin(); i != peers.end(); ++i)
{
//listDevices really needs a lot of resources, so wait a little bit after each device
std::this_thread::sleep_for(std::chrono::milliseconds(3));
PVariable info = (*i)->getDeviceInfo(clientInfo, fields);
if(!info) continue;
array->arrayValue->push_back(info);
}

return array;
}
}
catch(const std::exception& ex)
{
GD::out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
}
catch(BaseLib::Exception& ex)
{
GD::out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
}
catch(...)
{
GD::out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
}
return Variable::createError(-32500, "Unknown application error.");
}

PVariable SonosCentral::putParamset(BaseLib::PRpcClientInfo clientInfo, std::string serialNumber, int32_t channel, ParameterGroup::Type::Enum type, std::string remoteSerialNumber, int32_t remoteChannel, PVariable paramset)
{
try
{
std::shared_ptr<SonosPeer> peer(getPeer(serialNumber));
uint64_t remoteID = 0;
if(!remoteSerialNumber.empty())
{
std::shared_ptr<SonosPeer> remotePeer(getPeer(remoteSerialNumber));
if(!remotePeer) return Variable::createError(-3, "Remote peer is unknown.");
remoteID = remotePeer->getID();
}
if(peer) return peer->putParamset(clientInfo, channel, type, remoteID, remoteChannel, paramset);
return Variable::createError(-2, "Unknown device.");
}
catch(const std::exception& ex)
{
GD::out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
}
catch(BaseLib::Exception& ex)
{
GD::out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
}
catch(...)
{
GD::out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
}
return Variable::createError(-32500, "Unknown application error.");
}

PVariable SonosCentral::putParamset(BaseLib::PRpcClientInfo clientInfo, uint64_t peerID, int32_t channel, ParameterGroup::Type::Enum type, uint64_t remoteID, int32_t remoteChannel, PVariable paramset)
{
try
{
std::shared_ptr<SonosPeer> peer(getPeer(peerID));
if(peer) return peer->putParamset(clientInfo, channel, type, remoteID, remoteChannel, paramset);
return Variable::createError(-2, "Unknown device.");
}
catch(const std::exception& ex)
{
GD::out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
}
catch(BaseLib::Exception& ex)
{
GD::out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
}
catch(...)
{
GD::out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
}
return Variable::createError(-32500, "Unknown application error.");
}

PVariable SonosCentral::removeLink(BaseLib::PRpcClientInfo clientInfo, std::string senderSerialNumber, int32_t senderChannelIndex, std::string receiverSerialNumber, int32_t receiverChannelIndex)
{
try
Expand Down Expand Up @@ -1287,17 +1185,20 @@ PVariable SonosCentral::searchDevices(BaseLib::PRpcClientInfo clientInfo, bool u

if(newPeers.size() > 0)
{
std::vector<uint64_t> newIds;
newIds.reserve(newPeers.size());
PVariable deviceDescriptions(new Variable(VariableType::tArray));
for(std::vector<std::shared_ptr<SonosPeer>>::iterator i = newPeers.begin(); i != newPeers.end(); ++i)
{
std::shared_ptr<std::vector<PVariable>> descriptions = (*i)->getDeviceDescriptions(clientInfo, true, std::map<std::string, bool>());
if(!descriptions) continue;
newIds.push_back((*i)->getID());
for(std::vector<PVariable>::iterator j = descriptions->begin(); j != descriptions->end(); ++j)
{
deviceDescriptions->arrayValue->push_back(*j);
}
}
raiseRPCNewDevices(deviceDescriptions);
raiseRPCNewDevices(newIds, deviceDescriptions);
}
return PVariable(new Variable((int32_t)newPeers.size()));
}
Expand Down
3 changes: 0 additions & 3 deletions src/SonosCentral.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ class SonosCentral : public BaseLib::Systems::ICentral
virtual PVariable addLink(BaseLib::PRpcClientInfo clientInfo, uint64_t senderID, int32_t senderChannel, uint64_t receiverID, int32_t receiverChannel, std::string name, std::string description);
virtual PVariable deleteDevice(BaseLib::PRpcClientInfo clientInfo, std::string serialNumber, int32_t flags);
virtual PVariable deleteDevice(BaseLib::PRpcClientInfo clientInfo, uint64_t peerID, int32_t flags);
virtual PVariable getDeviceInfo(BaseLib::PRpcClientInfo clientInfo, uint64_t id, std::map<std::string, bool> fields);
virtual PVariable putParamset(BaseLib::PRpcClientInfo clientInfo, std::string serialNumber, int32_t channel, ParameterGroup::Type::Enum type, std::string remoteSerialNumber, int32_t remoteChannel, PVariable paramset);
virtual PVariable putParamset(BaseLib::PRpcClientInfo clientInfo, uint64_t peerID, int32_t channel, ParameterGroup::Type::Enum type, uint64_t remoteID, int32_t remoteChannel, PVariable paramset);
virtual PVariable removeLink(BaseLib::PRpcClientInfo clientInfo, std::string senderSerialNumber, int32_t senderChannel, std::string receiverSerialNumber, int32_t receiverChannel);
virtual PVariable removeLink(BaseLib::PRpcClientInfo clientInfo, uint64_t senderID, int32_t senderChannel, uint64_t receiverID, int32_t receiverChannel);
virtual PVariable searchDevices(BaseLib::PRpcClientInfo clientInfo);
Expand Down
18 changes: 14 additions & 4 deletions src/SonosPeer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1787,7 +1787,7 @@ PVariable SonosPeer::getValue(BaseLib::PRpcClientInfo clientInfo, uint32_t chann
return Variable::createError(-32500, "Unknown application error.");
}

PVariable SonosPeer::putParamset(BaseLib::PRpcClientInfo clientInfo, int32_t channel, ParameterGroup::Type::Enum type, uint64_t remoteID, int32_t remoteChannel, PVariable variables, bool onlyPushing)
PVariable SonosPeer::putParamset(BaseLib::PRpcClientInfo clientInfo, int32_t channel, ParameterGroup::Type::Enum type, uint64_t remoteID, int32_t remoteChannel, PVariable variables, bool checkAcls, bool onlyPushing)
{
try
{
Expand All @@ -1801,6 +1801,9 @@ PVariable SonosPeer::putParamset(BaseLib::PRpcClientInfo clientInfo, int32_t cha
if(!parameterGroup) return Variable::createError(-3, "Unknown parameter set.");
if(variables->structValue->empty()) return PVariable(new Variable(VariableType::tVoid));

auto central = getCentral();
if(!central) return Variable::createError(-32500, "Could not get central.");

if(type == ParameterGroup::Type::Enum::config)
{
bool configChanged = false;
Expand Down Expand Up @@ -1830,6 +1833,9 @@ PVariable SonosPeer::putParamset(BaseLib::PRpcClientInfo clientInfo, int32_t cha
for(Struct::iterator i = variables->structValue->begin(); i != variables->structValue->end(); ++i)
{
if(i->first.empty() || !i->second) continue;

if(checkAcls && !clientInfo->acls->checkVariableWriteAccess(central->getPeer(_peerID), channel, i->first)) continue;

setValue(clientInfo, channel, i->first, i->second, true);
}
}
Expand Down Expand Up @@ -1875,7 +1881,11 @@ PVariable SonosPeer::setValue(BaseLib::PRpcClientInfo clientInfo, uint32_t chann
valueKey == "PLAY_TTS VOICE" ||
valueKey == "PLAY_TTS_VOLUME" ||
valueKey == "PREVIOUS" ||
valueKey == "STOP"))
valueKey == "STOP" ||
valueKey == "ADD_SPEAKER" ||
valueKey == "REMOVE_SPEAKER" ||
valueKey == "ADD_SPEAKER_BY_SERIAL" ||
valueKey == "REMOVE_SPEAKER_BY_SERIAL"))
{
std::shared_ptr<SonosCentral> central(std::dynamic_pointer_cast<SonosCentral>(getCentral()));
std::unordered_map<int32_t, std::vector<std::shared_ptr<BaseLib::Systems::BasicPeer>>> peerMap = getPeers();
Expand Down Expand Up @@ -2583,7 +2593,7 @@ bool SonosPeer::setHomegearValue(uint32_t channel, std::string valueKey, PVariab
std::vector<uint8_t> parameterData = parameterIterator->second.getBinaryData();
PVariable variable = _binaryDecoder->decodeResponse(parameterData);
if(variable) language = variable->stringValue;
if(!BaseLib::HelperFunctions::isAlphaNumeric(language))
if(!BaseLib::HelperFunctions::isAlphaNumeric(language, std::unordered_set<char>{'-', '_'}))
{
GD::out.printError("Error: Language is not alphanumeric.");
language = "en-US";
Expand All @@ -2596,7 +2606,7 @@ bool SonosPeer::setHomegearValue(uint32_t channel, std::string valueKey, PVariab
std::vector<uint8_t> parameterData = parameterIterator->second.getBinaryData();
PVariable variable = _binaryDecoder->decodeResponse(parameterData);
if(variable) voice = variable->stringValue;
if(!BaseLib::HelperFunctions::isAlphaNumeric(language))
if(!BaseLib::HelperFunctions::isAlphaNumeric(language, std::unordered_set<char>{'-', '_'}))
{
GD::out.printError("Error: Voice is not alphanumeric.");
language = "Justin";
Expand Down
2 changes: 1 addition & 1 deletion src/SonosPeer.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class SonosPeer : public BaseLib::Systems::Peer

//RPC methods
virtual PVariable getValue(BaseLib::PRpcClientInfo clientInfo, uint32_t channel, std::string valueKey, bool requestFromDevice, bool asynchronous);
virtual PVariable putParamset(BaseLib::PRpcClientInfo clientInfo, int32_t channel, ParameterGroup::Type::Enum type, uint64_t remoteID, int32_t remoteChannel, PVariable variables, bool onlyPushing = false);
virtual PVariable putParamset(BaseLib::PRpcClientInfo clientInfo, int32_t channel, ParameterGroup::Type::Enum type, uint64_t remoteID, int32_t remoteChannel, PVariable variables, bool checkAcls, bool onlyPushing = false);
virtual PVariable setValue(BaseLib::PRpcClientInfo clientInfo, uint32_t channel, std::string valueKey, PVariable value, bool wait);
//End RPC methods
protected:
Expand Down

0 comments on commit 83f922a

Please sign in to comment.