connectcore-demo-example: add play and stop music feature
Signed-off-by: David Escalona <david.escalona@digi.com>
This commit is contained in:
parent
58c06b00e7
commit
a8f6d228e6
|
|
@ -195,6 +195,23 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler):
|
||||||
return
|
return
|
||||||
|
|
||||||
self.wfile.write("{}".encode(encoding="utf_8"))
|
self.wfile.write("{}".encode(encoding="utf_8"))
|
||||||
|
elif re.search("/ajax/play_music", self.path) is not None:
|
||||||
|
# Set the response headers.
|
||||||
|
self._set_headers(200)
|
||||||
|
|
||||||
|
# Get the JSON data.
|
||||||
|
data = self.rfile.read(int(self.headers["Content-Length"]))
|
||||||
|
play = json.loads(data.decode("utf-8")).get("play", None)
|
||||||
|
music_file = json.loads(data.decode("utf-8")).get("music_file", None)
|
||||||
|
|
||||||
|
log.debug("Play music: %s", play)
|
||||||
|
if music_file:
|
||||||
|
log.debug("Music file: %s", music_file)
|
||||||
|
|
||||||
|
play_music(play, music_file)
|
||||||
|
|
||||||
|
# Send the JSON value.
|
||||||
|
self.wfile.write(json.dumps({"play": play}).encode(encoding="utf_8"))
|
||||||
elif re.search("/ajax/set_audio_volume", self.path) is not None:
|
elif re.search("/ajax/set_audio_volume", self.path) is not None:
|
||||||
# Set the response headers.
|
# Set the response headers.
|
||||||
self._set_headers(200)
|
self._set_headers(200)
|
||||||
|
|
@ -950,6 +967,19 @@ def get_led_by_alias(alias):
|
||||||
return led_loc.split(",")
|
return led_loc.split(",")
|
||||||
|
|
||||||
|
|
||||||
|
def play_music(play, music_file):
|
||||||
|
"""
|
||||||
|
Sets the play music value.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
play (Boolean): `True` to play music, `False` to stop it.
|
||||||
|
music_file (String): Path of the music file to play.
|
||||||
|
"""
|
||||||
|
exec_cmd("pkill -KILL -f mpg123")
|
||||||
|
if play:
|
||||||
|
exec_cmd_nowait(f"mpg123 {music_file}")
|
||||||
|
|
||||||
|
|
||||||
def set_audio_volume(value):
|
def set_audio_volume(value):
|
||||||
"""
|
"""
|
||||||
Configures the audio volume.
|
Configures the audio volume.
|
||||||
|
|
@ -1009,6 +1039,21 @@ def exec_cmd(cmd, timeout=None):
|
||||||
return e.returncode, e.stdout
|
return e.returncode, e.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def exec_cmd_nowait(command, *args):
|
||||||
|
"""
|
||||||
|
Executes the provided command without waiting to finish.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
command (String): The command to execute.
|
||||||
|
args (List): The list of arguments.
|
||||||
|
"""
|
||||||
|
arguments = []
|
||||||
|
for arg in args:
|
||||||
|
arguments.extend(arg)
|
||||||
|
subprocess.Popen([command] + arguments, shell=True, stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT, text=True)
|
||||||
|
|
||||||
|
|
||||||
def read_file(path):
|
def read_file(path):
|
||||||
"""
|
"""
|
||||||
Reads the provided file path.
|
Reads the provided file path.
|
||||||
|
|
|
||||||
|
|
@ -620,6 +620,13 @@ Digi Demo - Dashboard
|
||||||
<span>Audio control</span>
|
<span>Audio control</span>
|
||||||
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="setInfoPanelVisible('audio', false)"></div>
|
<div class="fas fa-window-close fa-lg device-card-header-button" onclick="setInfoPanelVisible('audio', false)"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="device-card-content" style="padding-bottom: 0px;">
|
||||||
|
<span class="device-card-content-text" style="margin-right: 15px;">Music:</span>
|
||||||
|
<div id="play_audio_button" class="fas fa-play audio-button" onclick="playMusic(true)">
|
||||||
|
</div>
|
||||||
|
<div id="stop_audio_button" class="fas fa-stop audio-button" onclick="playMusic(false)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="device-card-content">
|
<div class="device-card-content">
|
||||||
<div>
|
<div>
|
||||||
<span class="device-card-content-text">Volume:</span>
|
<span class="device-card-content-text">Volume:</span>
|
||||||
|
|
|
||||||
|
|
@ -1058,11 +1058,24 @@ body {
|
||||||
|
|
||||||
/* AUDIO */
|
/* AUDIO */
|
||||||
.audio-panel {
|
.audio-panel {
|
||||||
width: 350px;
|
width: 280px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#audio_panel .slider-horizontal {
|
#audio_panel .slider-horizontal {
|
||||||
width: 180px;
|
width: 110px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audio-button {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 24px;
|
||||||
|
text-align: center;
|
||||||
|
z-index: 99999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audio-button:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--digi-green);
|
||||||
}
|
}
|
||||||
/* END AUDIO */
|
/* END AUDIO */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* Music by https://www.bensound.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Constants.
|
// Constants.
|
||||||
|
|
@ -55,6 +57,7 @@ const ID_MEMORY_PANEL_AREA = "memory_panel_area";
|
||||||
const ID_MEMORY_PANEL_ARROW = "memory_panel_arrow";
|
const ID_MEMORY_PANEL_ARROW = "memory_panel_arrow";
|
||||||
const ID_MEMORY_PANEL_ICON = "memory_panel_icon";
|
const ID_MEMORY_PANEL_ICON = "memory_panel_icon";
|
||||||
const ID_PLATFORM_NAME = "platform_name";
|
const ID_PLATFORM_NAME = "platform_name";
|
||||||
|
const ID_PLAY = "play";
|
||||||
const ID_VIDEO_BRIGHTNESS_CONTAINER = "video_brightness_container";
|
const ID_VIDEO_BRIGHTNESS_CONTAINER = "video_brightness_container";
|
||||||
const ID_VIDEO_PANEL = "video_panel";
|
const ID_VIDEO_PANEL = "video_panel";
|
||||||
const ID_VIDEO_PANEL_AREA = "video_panel_area";
|
const ID_VIDEO_PANEL_AREA = "video_panel_area";
|
||||||
|
|
@ -103,6 +106,9 @@ const CLASS_PANEL_TOOLTIP = "panel-tooltip";
|
||||||
|
|
||||||
const MESSAGE_CHANGING_VIDEO_BRIGHTNESS = "Changing video brightness...";
|
const MESSAGE_CHANGING_VIDEO_BRIGHTNESS = "Changing video brightness...";
|
||||||
const MESSAGE_CHANGING_AUDIO_VOLUME = "Changing audio volume...";
|
const MESSAGE_CHANGING_AUDIO_VOLUME = "Changing audio volume...";
|
||||||
|
const MESSAGE_MUSIC_PLAYING = "Music playing..."
|
||||||
|
const MESSAGE_MUSIC_STOPPED = "Music stopped."
|
||||||
|
const MESSAGE_PLAY_MUSIC = "Setting play music value..."
|
||||||
const MESSAGE_READING_DEVICE_INFO = "Reading device info...";
|
const MESSAGE_READING_DEVICE_INFO = "Reading device info...";
|
||||||
const MESSAGE_READING_DEVICE_STATUS = "Reading device status...";
|
const MESSAGE_READING_DEVICE_STATUS = "Reading device status...";
|
||||||
const MESSAGE_TOGGLING_LED_VALUE = "Toggling LED value...";
|
const MESSAGE_TOGGLING_LED_VALUE = "Toggling LED value...";
|
||||||
|
|
@ -111,6 +117,8 @@ const ERROR_LED_UNKNOWN = "LED status has not been read yet, please wait.";
|
||||||
const ERROR_NOT_SUPPORTED_DEVICE_MESSAGE = "The selected device type is not supported: {0}";
|
const ERROR_NOT_SUPPORTED_DEVICE_MESSAGE = "The selected device type is not supported: {0}";
|
||||||
const ERROR_NOT_SUPPORTED_DEVICE_TITLE = "Unsupported device";
|
const ERROR_NOT_SUPPORTED_DEVICE_TITLE = "Unsupported device";
|
||||||
|
|
||||||
|
const MUSIC_FILE = "/srv/www/static/sounds/inspire.mp3"
|
||||||
|
|
||||||
// Variables.
|
// Variables.
|
||||||
var deviceInitialized = false;
|
var deviceInitialized = false;
|
||||||
var device = null;
|
var device = null;
|
||||||
|
|
@ -938,6 +946,50 @@ function processSetVideoBrightnessResponse(response) {
|
||||||
videoSlider.enable();
|
videoSlider.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handles what happens when the Play music button is pressed.
|
||||||
|
function playMusic(play) {
|
||||||
|
// Show the loading panel of the device.
|
||||||
|
showLoadingPopup(true, MESSAGE_PLAY_MUSIC);
|
||||||
|
// Send request to play music.
|
||||||
|
$.post(
|
||||||
|
"http://" + getServerAddress() + "/ajax/play_music",
|
||||||
|
JSON.stringify({
|
||||||
|
"play": play,
|
||||||
|
"music_file": MUSIC_FILE
|
||||||
|
}),
|
||||||
|
function(data) {
|
||||||
|
// Process only in the dashboard page.
|
||||||
|
if (!isDashboardShowing())
|
||||||
|
return;
|
||||||
|
// Process answer.
|
||||||
|
processPlayMusicResponse(data);
|
||||||
|
}
|
||||||
|
).fail(function(response) {
|
||||||
|
// Process only in the dashboard page.
|
||||||
|
if (!isDashboardShowing())
|
||||||
|
return;
|
||||||
|
// Process error.
|
||||||
|
processAjaxErrorResponse(response);
|
||||||
|
// Hide the loading panel of the device.
|
||||||
|
showLoadingPopup(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processes the "play music" request answer.
|
||||||
|
function processPlayMusicResponse(response) {
|
||||||
|
// Check if there was any error in the request.
|
||||||
|
if (!checkErrorResponse(response, false)) {
|
||||||
|
play = response[ID_PLAY];
|
||||||
|
// Show confirmation.
|
||||||
|
if (play)
|
||||||
|
toastr.info(MESSAGE_MUSIC_PLAYING);
|
||||||
|
else
|
||||||
|
toastr.info(MESSAGE_MUSIC_STOPPED);
|
||||||
|
}
|
||||||
|
// Hide the loading panel of the device.
|
||||||
|
showLoadingPopup(false);
|
||||||
|
}
|
||||||
|
|
||||||
// Processes an audio volume changed event.
|
// Processes an audio volume changed event.
|
||||||
function volumeChanged(newValue) {
|
function volumeChanged(newValue) {
|
||||||
// Show the loading panel of the device.
|
// Show the loading panel of the device.
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue