node-red-contrib-musiccast
Version:
A Node-RED collection for monitoring and controlling a Yamaha Musiccast network.
386 lines (334 loc) • 15.8 kB
HTML
<!--
Apache-2.0
Copyright (c) 2023 Vahdettin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
-->
<script type="module" src="resources/node-red-contrib-musiccast/musiccast-ui.js"></script>
<script type="text/javascript">
(function () {
const BASE = 'link';
RED.nodes.registerType('musiccast-link', {
category: 'Musiccast',
defaults: {
mc: {type: "musiccast-config", required: true},
name: {value: "", required: false},
device: {value: "", required: false},
type_device: {value: "", required: false},
command: {value: "getDistributionInfo", required: false},
type_command: {value: "", required: false},
payload: {value: "{}", required: false},
type_payload: {value: "json", required: false},
f_show_status: {value: false, required: false}
},
inputs: 1,
outputs: 1,
color: "#9c86bc",
label: function () {
return this.name || this.command;
},
icon: "font-awesome/fa-arrows-alt",
align: 'right',
paletteLabel: "link",
oneditprepare: function () {
let mc = RED.nodes.node($("#node-input-mc").val()) || null;
let ui = new MCUI(BASE,mc,RED);
const Fields = ui.cFields;
let popGroupID = function (opts, callback) {
let ui = this;
const el = ui.Fields.g;
let groupTypes = [{
value: "num",
label: "Specify",
hasValue: true
},
{
value: "global",
label: "global.musiccast_group_id",
icon: "fa fa-globe",
hasValue: false
},
{
value: "global",
label: "global.musiccast_group_id",
icon: "fa fa-globe",
hasValue: false
},
{
value: "msg",
label: "msg.group_id",
icon: "fa fa-envelope",
hasValue: false
}];
try {
el.typedInput('types', groupTypes);
} catch (err) {
el.typedInput({
default: "num",
typeField: ui.TypeFields.g,
types: groupTypes
});
}
callback(null, {
g: el.typedInput("value"),
t: el.typedInput("type")
});
};
let mcLinkDraw = function (done) {
ui.popDevices(null, function (err, curDev) {
ui.popCommands(curDev, function (err, curCommand) {
ui.loadCommand(curCommand,function(err,curCommand){
})
ui.popAttributes();
done(true);
});
});
}
mcLinkDraw(function (drawn) {
if (drawn) {
Fields.c.on('change', function (event, type, value) {
ui.loadCommand({
v: value,
t: Fields.c.typedInput("type")
},function(err,curCommand){})
});
Fields.p.on('change', function (event, type, value) {
if (type && type === 'json') {
if (!value) {
Fields.p.typedInput('value', '{}')
}
}
});
$("#lookup-command").on("click", function () {
ui.showSidebarHelpPanel({
v: Fields.c.typedInput("value"),
t: Fields.c.typedInput("type")
});
});
$("#set-attribute-default").on("click", function () {
ui.popExampleAttributes({
v: Fields.c.typedInput("value"),
t: Fields.c.typedInput("type")
}, function (err, data) {
})
});
RED.events.on("nodes:change", function (theNode) {
if (theNode && theNode.type === 'musiccast-config') {
if (theNode.dirty && theNode.dirty !== false && theNode.valid && theNode.valid !== false) {
ui.refresh(theNode,function(err,done){
ui.popDevices(null, function (err, curZone) {
})
})
}
}
});
ui.finish();
}
});
},
oneditsave: function () {
let mc = RED.nodes.node($("#node-input-mc").val()) || null;
let ui = new MCUI(BASE,mc,RED);
const Fields = ui.cFields;
$("#lookup-command").off();
$("#set-attribute-default").off();
this.device = Fields.d.typedInput("value");
this.command = Fields.c.typedInput("value");
this.payload = Fields.p.typedInput("value");
},
oneditcancel: function () {
$("#lookup-command").off();
$("#set-attribute-default").off();
}
});
})();
</script>
<script type="text/html" data-template-name="musiccast-link">
<link rel="stylesheet" href="resources/node-red-contrib-musiccast/style.css"/>
<div>
<span id="notification_message"></span>
</div>
<div class="form-row">
<label for="node-input-mc"> Musiccast</label>
<input type="text" id="node-input-mc">
</div>
<div class="form-row ">
<label for="node-input-device"><i class="fa fa-crosshairs"></i> Device</label>
<div style="display: inline-block; position: relative; width: 70%; height: 20px;">
<div style="position: absolute; left: 0px; right: 40px;">
<input type="text" id="node-input-device" style="width:80%">
</div>
</div>
</div>
<div class="form-row ">
<label for="node-input-command"><i class="fa fa-cogs"></i> Command</label>
<div style="display: inline-block; position: relative; width: 70%; height: 20px;">
<div style="position: absolute; left: 0px; right: 40px;">
<input type="text" id="node-input-command" style="width:100%">
</div>
<a id="lookup-command" class="red-ui-button" style="position: absolute; right: 0px; top: 0px;"><i
class="fa fa-book"></i></a>
</div>
</div>
<div class="form-row musiccast-form-row-cmd-addt ">
<label> </label>
<input type="checkbox" id="node-input-f_show_status"
style="display:inline-block; width:15px; vertical-align:baseline;" autocomplete="off">
<label style="width: 60% !important;" for="node-input-f_show_status"
title="Show power status for the designated zone on the palette when command runs.">Show on
palette</label>
</div>
<div class="form-row musiccast-form-row-payload">
<label for="node-input-payload"><i class="fa fa-puzzle-piece"></i> Attributes</label>
<div style="display: inline-block; position: relative; width: 70%; height: 20px;">
<div style="position: absolute; left: 0px; right: 40px;">
<input type="text" id="node-input-payload" style="width:100%">
</div>
<a id="set-attribute-default" class="red-ui-button"
style="position: absolute; right: 0px; top: 0px;"><i class="fa fa-paste"></i></a>
</div>
</div>
<div class="form-row ">
<label for="node-input-name"><i class="fa fa-tag"></i> Label</label>
<div style="display: inline-block; position: relative; width: 70%; height: 20px;">
<div style="position: absolute; left: 0px; right: 40px;">
<input type="text" id="node-input-name" placeholder="optional" style="width:100%">
</div>
</div>
</div>
<div class="form-row musiccast-form-row-ah">
<input type="text" id="node-input-type_command">
</div>
<div class="form-row musiccast-form-row-ah">
<input type="text" id="node-input-type_payload">
</div>
<div class="form-row musiccast-form-row-ah">
<input type="text" id="node-input-type_device">
</div>
</script>
<script type="text/html" data-help-name="musiccast-link">
<link rel="stylesheet" href="resources/node-red-contrib-musiccast/style.css"/>
<p>Configure distribution groups for synchronized playback across multiple Musiccast devices.</p>
<h4>Yamaha API Relationship</h4>
<p>The Yamaha API command types included in this node are:</p>
<dl>
<dd>
<ul>
<li>Distribution </li>
</ul>
</dd>
</dl>
<h4>Basic Configuration</h4>
<p>The following items can only be set via the palette editor. All other configuration items can be set in the
editor or via inbound message or context variable. Details for these items are in the Input section below. </p>
<dl>
<dt>Musiccast</dt>
<dd>Select the Musiccast configuration to use.</dd>
<dt>Label</dt>
<dd>Optional. Enter a name for the node or the default will be assigned.</dd>
<dt>Show on palette</dt>
<dd>Optional. If this option appears under the Command dropdown and is checked, basic information from a
response will be displayed on the palette under the node when a command is sent.
</dl>
<h4>Helpful Features</h4>
<p>There are several buttons that when clicked, provide helpful functionality to assist with configuration.</p>
<dl>
<dd>
<ul>
<li><a class="red-ui-button"><i class="fa fa-question"></i></a> Shows inline help for the
selected command.
</li>
<li><a class="red-ui-button"><i class="fa fa-paste"></i></a> Populates the Attributes field with example
values to start with.
</li>
</ul>
</dd>
</dl>
<h3>Input</h3>
<dl class="message-properties">
<dt>device
<span class="property-type">string</span>
</dt>
<dd> The target device name or label.
</dd>
<dt>command
<span class="property-type">string</span>
</dt>
<dd> The command to send.
</dd>
<dt>attributes
<span class="property-type">object</span>
</dt>
<dd> Additional attributes if needed by the command. This can also be sent as <code>payload</code>.
</dd>
</dl>
<h3>Output</h3>
<dl class="message-properties">
<dt>device
<span class="property-type">string</span>
</dt>
<dd> The device the command was sent to.
</dd>
<dt>command <span class="property-type">string</span></dt>
<dd> The command that was sent.</dd>
<dt>payload <span class="property-type">object</span></dt>
<dd> The response received from the device. This will always include <i>response_code</i> and <i>response_message</i>.
</dd>
</dl>
<h3>Command Reference</h3>
<!-- BEGIN COMMAND HELP -->
<dl class="message-properties">
<dt id="musiccast-command-info-getdistributioninfo">getDistributionInfo</dt>
<dd>Get current distribution information.</dd><p></p>
<dt id="musiccast-command-info-setgroupname">setGroupName</dt>
<dd>Set the friendly name for a group on a device. Leave name empty to set to default. The default is assigned when setting up a group so this command is typically not required.</dd><p></p>
<dd>Attribute structure:
<pre class="musiccast-attributes-example">{
<span class="key">"name":</span> <span class="string">"xxxxxxxxx"</span>
}</pre><p></p>
</dd>
<dt id="musiccast-command-info-setclientinfo">setClientInfo</dt>
<dd>Set a device as a distribution client. Set group_id to an empty string to remove a device from a group.</dd><p></p>
<dd>Attribute structure:
<pre class="musiccast-attributes-example">{
<span class="key">"group_id":</span> <span class="string">"00000000000000000000000000000000"</span>,
<span class="key">"zone":</span> <span class="string">"main|zone1|..."</span>,
<span class="key">"server_ip_address":</span> <span class="string">"x.x.x.x"</span>
}</pre><p></p>
</dd>
<dt id="musiccast-command-info-setserverinfo">setServerInfo</dt>
<dd>Configure a device's role as a distribution server. Set group_id to a value of an empty string to stop the device from being a server.</dd><p></p>
<dd>Attribute structure:
<pre class="musiccast-attributes-example">{
<span class="key">"group_id":</span> <span class="string">"00000000000000000000000000000000"</span>,
<span class="key">"type":</span> <span class="string">"add|remove"</span>,
<span class="key">"zone":</span> <span class="string">"main|zone1|..."</span>,
<span class="key">"client_list":</span> [
<span class="string">"x.x.x.x"</span>
]
}</pre><p></p>
</dd>
<dt id="musiccast-command-info-startdistribution">startDistribution</dt>
<dd>Send command to start distribution for a device that is configured as a server.</dd><p></p>
<dd>Attribute structure:
<pre class="musiccast-attributes-example">{
<span class="key">"num":</span> <span class="string">"0|1|..."</span>
}</pre><p></p>
</dd>
<dt id="musiccast-command-info-stopdistribution">stopDistribution</dt>
<dd>Command a device to stop distribution.</dd><p></p>
</dl>
<!-- END COMMAND HELP -->
<h4>Collection Information</h4>
<ul>
<li>Version: 4.5.2</li>
</ul>
<div style="height: 700px;"></div>
<span>This space intentionally left blank</span>
</script>