Page 1 of 1

Enabling Snapclient

PostPosted: 01 Nov 2018, 10:48
by ReefSmacker
Hi,

I've been playing around with using snapclient on my Pi's (version 3) with snapserver running on either Ubuntu via MPD or on our main Kodi libreelec system. I'm using RuneAudio version 0.5 (build: janui-20180903)

As far as compiling snapclient and listening to synced music/tv this has been very successful.
This was achieved by connecting to the Pi via SSH and manually starting the service using systemctl start snapclient

My issue is in trying to make it usable for the Mrs :)
Trying to keep it as simple as possible, I have added an on/off button to the features section of the settings display.
In settings_ctl.php, it either tries to start or stop the service but it is failing.
The runeui log shows me the following output:
PHP message: ### sysCmd($str) ### systemctl start snapclient
PHP message: ### sysCmd() output: ### $data type = array
PHP message: ### sysCmd() output: ### ['0'] => Failed to start snapclient.service: Interactive authentication required.
PHP message: ### sysCmd() output: ### ['1'] => See system logs and 'systemctl status snapclient.service' for details.


By running systemctl status snapclient.service I get:
Apr 14 07:14:47 pergola-pi systemd[1]: Starting Snapcast client...
Apr 14 07:14:47 pergola-pi snapclient[20698]: daemon started
Apr 14 07:14:47 pergola-pi systemd[1]: Started Snapcast client.
Apr 14 07:15:22 pergola-pi snapclient[20698]: Received SIGTERM signal.
Apr 14 07:15:22 pergola-pi systemd[1]: Stopping Snapcast client...
Apr 14 07:15:27 pergola-pi snapclient[20698]: daemon terminated.
Apr 14 07:15:27 pergola-pi systemd[1]: Stopped Snapcast client.


This is not hugely helpful.
It would appear the PHP is not running as root and thus is being denied access to starting the service.

Can anybody point out how I should be starting the service ?
I have tried changing /etc/default/snapclient to run as a different user (snapclient) but that is not allowing the service to start either.
When configured to use the user snapclient, it doesn't throw an error in the log...

Cheers
Matt

PS: Not sure if this is related but i needed to update the version of glibc to 2.28 to allow snapclient to run. This does not appear to affect RuneAudio. At least not in the way i have been using it.

Re: Enabling Snapclient

PostPosted: 01 Nov 2018, 11:43
by janui
Hi ReefSmacker,

Here is an example of how Rune does this. This example if for starting/stopping the local browser. You can almost copy and paste this for starting/stopping snapclient.

Words/text which would need to be changed from the local browser example: ‘local-browser’, ‘Local browser’, ‘local_browser’, ‘Start a local browser on HDMI or TFT’, ‘xorgserverstart’, ‘xorgserverstop’, ‘systemctl start local-browser’ and ‘systemctl stop local-browser’.

For the ON/OFF switch in the Settings UI, modify: /srv/http/app/templates/settings.php
Example code:
Code: Select all
<div class="form-group">
  <label for="local-browser" class="control-label col-sm-2">Local browser</label>
  <div class="col-sm-10">
    <label class="switch-light well" onclick="">
      <input name="features[local_browser]" type="checkbox" value="1"<?php if($this->local_browser == 1): ?> checked="checked" <?php endif ?>>
      <span><span>OFF</span><span>ON</span></span><a class="btn btn-primary"></a>
    </label>
    <span class="help-block">Start a local browser on HDMI or TFT</span>
  </div>
</div>

For the logic to make the switch work, modify: /srv/http/app/settings_ctl.php
Example code:
Code: Select all
if ($_POST['features']['local_browser'] == 1) {
  $redis->get('local_browser') == 1 || $jobID[] = wrk_control($redis, 'newjob', $data = array('wrkcmd' => 'xorgserverstart'));
} else {
  $redis->get('local_browser') == 0 || $jobID[] = wrk_control($redis, 'newjob', $data = array('wrkcmd' => 'xorgserverstop'));
}
And:
Code: Select all
$template->local_browser = $redis->get('local_browser');

To actually start and stop the systemd service with the correct privileges, modify: /srv/http/command/rune_SY_wrk
Example code:
Code: Select all
case 'xorgserverstart':
  runelog('wrk_SY: ', $job->wrkcmd);
  $redis->sAdd('w_lock', $jobID);
  $redis->set('local_browser', 1);
  sysCmd('systemctl start local-browser');
  $redis->sRem('w_lock', $jobID);
  break;
case 'xorgserverstop':
  runelog('wrk_SY: ', $job->wrkcmd);
  $redis->sAdd('w_lock', $jobID);
  $redis->set('local_browser', 0);
  sysCmd('systemctl stop local-browser');
  $redis->sRem('w_lock', $jobID);
  break;

From SSH you need to initialise the redis variable which is used to remember the switch value, example:
Code: Select all
redis-cli local_browser 0


You probably have most of this coded. If you carry out updates (git pull) you will probably lose your modifications. You will need to find a way of reimplementing them.

janui

Re: Enabling Snapclient

PostPosted: 02 Nov 2018, 04:15
by ReefSmacker
Janui,

Thanks for the info.
I have implemented pretty much everything you've suggested with the exception of initialising the redis variable.
I guessed that would get written with the first attempt at set.
I'll have another play tonight and see if it'll start.

I'm a bit confused about the statement
start and stop the systemd service with the correct privileges, modify: /srv/http/command/rune_SY_wrk

How does this use the "right" privileges? There is nothing explicitly stating a user or level.

Cheers

Re: Enabling Snapclient

PostPosted: 02 Nov 2018, 06:32
by ReefSmacker
Hi Janui,

I have rechecked the code and believe I have everything as it should be but it still refuses to actually start the service. Note, I am checking the status of the service using: systemctl status

Here are my modifications:
int app/templates/settings.php
Code: Select all
            <legend>Features management</legend>
            <p>Enable/disable optional modules that best suit your needs. Disabling unused features will free system resources and might improve the overall performance</p>
            <div class="form-group">
                <label for="snapclient" class="control-label col-sm-2">Snapclient</label>
                <div class="col-sm-10">
                    <label class="switch-light well" onclick="">
                        <input id="snapclient" name="features[snapclient]" type="checkbox" value="1"<?php if($this->snapclient == 1): ?> checked="checked" <?php endif ?>>
                        <span><span>OFF</span><span>ON</span></span><a class="btn btn-primary"></a>
                    </label>
                    <span class="help-block">Toggle the capability of receiving snapcast streaming of audio</span>
                </div>
            </div>


in app/settings_ctl.php
Code: Select all
    if (isset($_POST['features'])) {
        if ($_POST['features']['snapclient'] == 1) {
            $redis->hGet('snapclient') == 1 || $jobID[] = wrk_control($redis, 'newjob', $data = array('wrkcmd' => 'snapclientstart'));
        } else {
            $redis->hGet('snapclient') == 0 || $jobID[] = wrk_control($redis, 'newjob', $data = array('wrkcmd' => 'snapclientstop'));
        }
        if ($_POST['features']['airplay']['enable'] == 1) {

and
Code: Select all
$template->orionprofile = $redis->get('orionprofile');
$template->snapclient = $redis->get('snapclient');
$template->airplay = $redis->hGetAll('airplay');


in ./command/rune_SY_wrk
Code: Select all
        // start snapclient
        if ($redis->get('snapclient')) {
                sysCmdAsync('systemctl start snapclient');
        }


and

Code: Select all
                case 'snapclientstart':
                    runelog('wrk_SY: ', $job->wrkcmd);
                    $redis->sAdd('w_lock', $jobID);
                    $redis->hSet('snapclient', 1);
                    sysCmd('systemctl start snapclient');
                    $redis->sRem('w_lock', $jobID);
                    break;
                case 'snapclientstop':
                    runelog('wrk_SY: ', $job->wrkcmd);
                    $redis->sAdd('w_lock', $jobID);
                    $redis->hSet('snapclient', 0);
                    sysCmd('systemctl stop snapclient');
                    $redis->sRem('w_lock', $jobID);
                    break;
                case 'xorgserverstart':
                    runelog('wrk_SY: ', $job->wrkcmd);



Have also manually added an entry to redis using redis-cli set snapclient 0
Testing this shows:
Code: Select all
root@pergola-pi(rw):/var/www# redis-cli get snapclient
"0"
root@pergola-pi(rw):/var/www#


When set for 0, changing the settings page to enabled and then applying provides the following logs:

from tail -f runeui.log
PHP message: ### wrk_control data: ### {"wrkcmd":"snapclientstart","action":null,"args":null}
PHP message: [wrk_control] ### [wrk] wrk_control($redis,newjob,$data) jobID=12b326da083f13ae9c7f91e562782771 ### $data type = array
PHP message: [wrk_control] ### [wrk] wrk_control($redis,newjob,$data) jobID=12b326da083f13ae9c7f91e562782771 ### ['wrkcmd'] => snapclientstart



from tail -f rune_SY_wrk.log
[02-Nov-2018 05:22:05 UTC] ### sysCmd($str) ### systemctl start upmpdcli
[02-Nov-2018 05:22:05 UTC] ### sysCmd() output: ### $data type = array
[02-Nov-2018 05:22:05 UTC] ### notify (async) JSON string: ### {"title":"UPnP \/ DLNA","text":"UPnP \/ DLNA feature enabled"}
[02-Nov-2018 05:22:06 UTC] [sysCmdAsync] ### sysCmdAsync($cmdstr) decoded ### /var/www/command/ui_notify.php '{"title":"UPnP \/ DLNA","text":"UPnP \/ DLNA feature enabled" }
[02-Nov-2018 05:22:06 UTC] [sysCmdAsync] ### sysCmdAsync($cmdstr) encoded ### /var/www/command/cmd_async L3Zhci93d3cvY29tbWFuZC91aV9ub3RpZnkucGhwICd7InRpdGxlIjoiVVBuUCBcLy BETE5BIiwidGV4dCI6IlVQblAgXC8gRExOQSBmZWF0dXJlIGVuYWJsZWQifQ==
[02-Nov-2018 05:22:06 UTC] [sysCmdAsync] ### sysCmdAsync() output: ### $data type = array
[02-Nov-2018 05:22:06 UTC] ### (loop) delete job_queue ### 1f769e3ffedae0e08f0e15d0cf79e60c
[02-Nov-2018 05:22:06 UTC] ### (loop) start job ### 12b326da083f13ae9c7f91e562782771
[02-Nov-2018 05:22:06 UTC] ### wrk_SY: ### snapclientstart
[02-Nov-2018 05:22:06 UTC] ### sysCmd($str) ### systemctl start snapclient
[02-Nov-2018 05:22:06 UTC] ### sysCmd() output: ### $data type = array
[02-Nov-2018 05:22:06 UTC] ### (loop) delete job_queue ### 12b326da083f13ae9c7f91e562782771
[02-Nov-2018 05:22:08 UTC] ### sysCmd($str) ### systemctl is-active ashuffle
[02-Nov-2018 05:22:08 UTC] ### sysCmd() output: ### $data type = array
[02-Nov-2018 05:22:08 UTC] ### sysCmd() output: ### ['0'] => inactive
[02-Nov-2018 05:22:17 UTC] ### sysCmd($str) ### systemctl is-active ashuffle
[02-Nov-2018 05:22:17 UTC] ### sysCmd() output: ### $data type = array
[02-Nov-2018 05:22:17 UTC] ### sysCmd() output: ### ['0'] => inactive
[02-Nov-2018 05:22:25 UTC] ### sysCmd($str) ### systemctl is-active ashuffle
[02-Nov-2018 05:22:25 UTC] ### sysCmd() output: ### $data type = array
[02-Nov-2018 05:22:25 UTC] ### sysCmd() output: ### ['0'] => inactive


If I manually enable redis for snapclient using redis-cli set snapclient 1
The settings page correctly loads with the button showing enabled.
If I try to disable it and apply, there is no output for snapclient in either log. This indicates to me that
Code: Select all
$redis->hGet('snapclient') == 0
in settings_ctl is true, thus
Code: Select all
wrk_control
is not executed.

From the terminal, redis-cli shows it is actually enabled:
root@pergola-pi(rw):/var/www# redis-cli get snapclient
"1"
root@pergola-pi(rw):/var/www#


Really not sure what I'm missing.

thanks.

Re: Enabling Snapclient

PostPosted: 02 Nov 2018, 08:27
by ReefSmacker
Persistence has paid off :)

I changed a couple of small things

I was using redis->hSet and redis-hGet when it should be redis->set and redis-get.
My code was originally copied from the airplay section.

I am also now using sysCmdAsync rather than sysCmd.

the service is controlling and the redis is being updated. Nice.

thanks for your help. If anybody would like a package of snapclient for the Pi 3, let me know.

Re: Enabling Snapclient

PostPosted: 02 Nov 2018, 10:16
by janui
Hi ReefSmacker,
Nice one. You could think about adding two extra lines to /srv/http/command/rune_SY_wrk which will make your modification persistent after reboot. This means that snapclient will start automatically on reboot when it is swiched on.
Change this:
Code: Select all
                    sysCmd('systemctl start snapclient');
To this:
Code: Select all
                    sysCmd('systemctl start snapclient');
                    sysCmd('systemctl enable snapclient');
And change this:
Code: Select all
                   sysCmd('systemctl stop snapclient');
To this:
Code: Select all
                   sysCmd('systemctl stop snapclient');
                   sysCmd('systemctl disable snapclient');
janui

Re: Enabling Snapclient

PostPosted: 02 Nov 2018, 21:52
by ReefSmacker
Thanks Janui,

That will certainly help.