duncan3dc / sonos

A PHP library for interacting with Sonos speakers
Apache License 2.0
107 stars 33 forks source link

Add custom track, documentation wrong? #93

Closed phoniclynx closed 6 years ago

phoniclynx commented 6 years ago

I'm trying to make a simple doorbell that responds when a flic button is pressed and calls a URL. I thought this should be simple, but I have a feeling your documentation is either wrong or out of date?

This is what I have at the moment:

function sonosDoorBell (){
    $sonos = new Network;

    $doorbell = $sonos->getControllerByRoom("Living Room");

    $track =  "x-file-cifs://HOMEAUTOMATION/announce/doorbell/Dream-sound-effect.mp3";

    $return = $doorbell->interrupt($track);
}

class Smb implements \duncan3dc\Sonos\Interfaces\UriInterface
{
    public $file;
    public function __construct($file)
    {
        $this->file = $file;
    }
    public function getUri()
    {
        return "x-file-cifs://LEMIEUX/music/{$this->file}";
    }
}

I get the error:

Fatal error: Declaration of Smb::getUri() must be compatible with duncan3dc\Sonos\Interfaces\UriInterface::getUri(): string in /var/www/html/sonoscontroller.php on line 11

Being the first line that is taken directly out of your documentation? (I had to correct the " public funcion __construct($file)" as it was missing a "T".. could there be other errors causing this not to work here? I'm not too sure what I am looking at.

duncan3dc commented 6 years ago

HI @phoniclynx sorry the documentation is not up to date, I'll take a look at updating it this week for you.

In the mean time, the error you're seeing above (Declaration of Smb::getUri()) is because of your declaration of getUri(), it should be:

public function getUri(): string
{
}

However, if you're just passing the $track in as a string, do you need the Smb class?

phoniclynx commented 6 years ago

I'm not 100% sure which part it "should" be. However if I just pass it as a string I get the error: Fatal error: Uncaught TypeError: Argument 1 passed to duncan3dc\Sonos\Controller::interrupt() must be an instance of duncan3dc\Sonos\Interfaces\UriInterface, string given, called in /var/www/html/sonoscontroller.php on line 88 and defined in /var/www/html/vendor/duncan3dc/sonos/src/Controller.php:668 Stack trace: #0 /var/www/html/sonoscontroller.php(88): duncan3dc\Sonos\Controller->interrupt('x-file-cifs://H...') #1 /var/www/html/index.php(1207): sonosDoorBell() #2 /var/www/html/index.php(87): sonos::doorbell() #3 {main} thrown in /var/www/html/vendor/duncan3dc/sonos/src/Controller.php on line 668

duncan3dc commented 6 years ago

Ah ok yeh, so maybe something like this:

class HomeAutomation implements \duncan3dc\Sonos\Interfaces\UriInterface
{
    private $file;
    public function __construct(string $file)
    {
        $this->file = $file;
    }
    public function getUri(): string
    {
        return "x-file-cifs://HOMEAUTOMATION/{$this->file}";
    }
}

function sonosDoorBell ()
{
    $sonos = new Network;
    $doorbell = $sonos->getControllerByRoom("Living Room");
    $track = new HomeAutomation("announce/doorbell/Dream-sound-effect.mp3");
    $doorbell->interrupt($track);
}
phoniclynx commented 6 years ago

I copied and pasted that as you suggested, but now I'm getting a different error: Fatal error: Class HomeAutomation contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (duncan3dc\Sonos\Interfaces\UriInterface::getMetaData) in /var/www/html/sonoscontroller.php on line 105

duncan3dc commented 6 years ago

Sorry about that, I'll take a look at the docs this week and let you know when they're updated

phoniclynx commented 6 years ago

ok cool.. thx

duncan3dc commented 6 years ago

I've corrected the docs now, something like this should work (tested on my network):

class HomeAutomation implements \duncan3dc\Sonos\Interfaces\UriInterface
{
    private $file;
    public function __construct(string $file)
    {
        $this->file = $file;
    }

    public function getUri(): string
    {
        $parts = explode("/", $this->file);
        $parts = array_map("rawurlencode", $parts);
        return "x-file-cifs://HOMEAUTOMATION/" . implode("/", $parts);
    }

    public function getMetaData(): string
    {
        return \duncan3dc\Sonos\Helper::createMetaDataXml("-1", "-1", [
            "res"               =>  $this->getUri(),
            "upnp:albumArtURI"  =>  "",
            "dc:title"          =>  "Title",
            "upnp:class"        =>  "object.item.audioItem.musicTrack",
            "dc:creator"        =>  "Artist",
            "upnp:album"        =>  "Album",
        ]);
    }
}
phoniclynx commented 6 years ago

I tried that code. Now I seem to get another error:

Fatal error: Uncaught duncan3dc\Sonos\Exceptions\SoapException: UPnPError: 701 in /var/www/html/vendor/duncan3dc/sonos/src/Devices/Device.php:152 Stack trace: #0 /var/www/html/vendor/duncan3dc/sonos/src/Speaker.php(86): duncan3dc\Sonos\Devices\Device->soap('AVTransport', 'Pause', Array) #1 /var/www/html/vendor/duncan3dc/sonos/src/Controller.php(719): duncan3dc\Sonos\Speaker->soap('AVTransport', 'Pause', Array) #2 /var/www/html/vendor/duncan3dc/sonos/src/Controller.php(188): duncan3dc\Sonos\Controller->soap('AVTransport', 'Pause') #3 /var/www/html/vendor/duncan3dc/sonos/src/Controller.php(589): duncan3dc\Sonos\Controller->pause() #4 /var/www/html/vendor/duncan3dc/sonos/src/Controller.php(677): duncan3dc\Sonos\Controller->exportState() #5 /var/www/html/sonoscontroller.php(112): duncan3dc\Sonos\Controller->interrupt(Object(HomeAutomation)) #6 /var/www/html/index.php(1207): sonosDoorBell() #7 /var/www/html/index.php(87): sonos::doorbell() #8 {main} thrown in /var/www/html/vendor/duncan3dc/sonos/src/Devices/Device.php on line 152

phoniclynx commented 6 years ago

I think that is because it is Grouped in Party Mode (3 different rooms) that I get that error. When I ungroup everything I get no error, and I also get no sound being played :\

phoniclynx commented 6 years ago

I tried to simply add it by track and I get errors with that too:

$track = new Track("x-file-cifs://HOMEAUTOMATION/announce/doorbell/dramatic.mp3");
$queue->addTrack($track);

returns Fatal error: Uncaught Error: Class 'Track' not found in /var/www/html/sonoscontroller.php:114 Stack trace: #0 /var/www/html/index.php(1207): sonosDoorBell() #1 /var/www/html/index.php(87): sonos::doorbell() #2 {main} thrown in /var/www/html/sonoscontroller.php on line 114

phoniclynx commented 6 years ago

You are going to hate me by the end of this, haha sorry. But I think I've found another bug. I have 3(three) rooms in my Sonos setup: Living Room. Kitchen, Bedroom.

If I use the code above to send the interrupt doorbell alert and it is sent to "Living Room using: $doorbell = $sonos->getControllerByRoom("Living Room");"; it plays in the room "Kitchen". I have a bizarre feeling the SONOS controller is there.

If I change the request to play by room "Kitchen", I get an error: Fatal error: Uncaught duncan3dc\Sonos\Exceptions\NotFoundException: Unable to find the controller for the room 'Kitchen' in /var/www/html/vendor/duncan3dc/sonos/src/Network.php:221 Stack trace: #0 /var/www/html/sonoscontroller.php(110): duncan3dc\Sonos\Network->getControllerByRoom('Kitchen') #1 /var/www/html/index.php(1207): sonosDoorBell() #2 /var/www/html/index.php(87): sonos::doorbell() #3 {main} thrown in /var/www/html/vendor/duncan3dc/sonos/src/Network.php on line 221

If I change to request to play by room "Bedroom", I get the error: Fatal error: Uncaught duncan3dc\Sonos\Exceptions\NotFoundException: Unable to find the controller for the room 'Bedroom' in /var/www/html/vendor/duncan3dc/sonos/src/Network.php:221 Stack trace: #0 /var/www/html/sonoscontroller.php(110): duncan3dc\Sonos\Network->getControllerByRoom('Bedroom') #1 /var/www/html/index.php(1207): sonosDoorBell() #2 /var/www/html/index.php(87): sonos::doorbell() #3 {main} thrown in /var/www/html/vendor/duncan3dc/sonos/src/Network.php on line 221

Not too sure what is going on there?