From 48b7483c8105f0066719ad898830479e343038b5 Mon Sep 17 00:00:00 2001 From: Jens Rossbach Date: Sun, 7 Jan 2024 11:00:46 +0100 Subject: [PATCH 1/3] Replace synchronous usage of evaluateJSONataExpression by asynchronous --- nodes/common/utils.js | 44 ++++-- nodes/control.js | 303 +++++++++++++++++++++++++----------------- nodes/device.js | 41 ++++-- nodes/notify.js | 11 +- 4 files changed, 247 insertions(+), 152 deletions(-) diff --git a/nodes/common/utils.js b/nodes/common/utils.js index 49b89e0..37dbe29 100644 --- a/nodes/common/utils.js +++ b/nodes/common/utils.js @@ -27,6 +27,8 @@ const Nunjucks = require("nunjucks"); module.exports = { + evaluateJSONataExpression: evaluateJSONataExpression, + validateOutputProperties: function(RED, node, source, target, allowEmpty) { for (let prop of source) @@ -112,8 +114,9 @@ module.exports = } catch (e) { - node.error(RED._("@jens_rossbach/node-red-sony-audio/sonyaudio-device:common.error.invalidExpression", - {error: e.code + ": " + e.message + " [POS: " + e.position + ", TOK: '" + e.token + ", VAL: '" + e.value + "']"})); + node.error( + RED._("@jens_rossbach/node-red-sony-audio/sonyaudio-device:common.error.invalidExpression", + {error: e.code + ": " + e.message + " [POS: " + e.position + ", TOK: '" + e.token + ", VAL: '" + e.value + "']"})); return false; } } @@ -142,7 +145,7 @@ module.exports = return true; }, - prepareOutput: function(RED, node, properties, msg, data, sendIfPayload) + prepareOutput: async function(RED, node, properties, msg, data, sendIfPayload) { let out = msg ? msg : {}; let numMsgProps = 0; @@ -154,7 +157,7 @@ module.exports = { if (prop.type == "msg") { - RED.util.setMessageProperty(out, prop.name, getProperty(prop), true); + RED.util.setMessageProperty(out, prop.name, await getProperty(prop), true); ++numMsgProps; if (prop.name == "payload") @@ -165,7 +168,7 @@ module.exports = else { let ctx = RED.util.parseContextStore(prop.name); - node.context()[prop.type].set(ctx.key, getProperty(prop), ctx.store); + node.context()[prop.type].set(ctx.key, await getProperty(prop), ctx.store); } } catch (e) @@ -192,7 +195,7 @@ module.exports = return out; - function getProperty(prop) + async function getProperty(prop) { let value = null; @@ -226,7 +229,9 @@ module.exports = } catch (e) { - throw new Error(RED._("@jens_rossbach/node-red-sony-audio/sonyaudio-device:common.error.invalidTemplate", {error: e.message})); + throw new Error( + RED._("@jens_rossbach/node-red-sony-audio/sonyaudio-device:common.error.invalidTemplate", + {error: e.message})); } } else @@ -240,12 +245,13 @@ module.exports = { try { - value = RED.util.evaluateJSONataExpression(prop.value.expression, data); + value = await evaluateJSONataExpression(RED, prop.value.expression, data); } catch (e) { - throw new Error(RED._("@jens_rossbach/node-red-sony-audio/sonyaudio-device:common.error.invalidExpression", - {error: e.code + ": " + e.message + " [POS: " + e.position + ", TOK: '" + e.token + "']"})); + throw new Error( + RED._("@jens_rossbach/node-red-sony-audio/sonyaudio-device:common.error.invalidExpression", + {error: e.code + ": " + e.message + " [POS: " + e.position + ", TOK: '" + e.token + "']"})); } if (typeof value == "undefined") @@ -662,3 +668,21 @@ module.exports = } } }; + +function evaluateJSONataExpression(RED, expr, msg) +{ + return new Promise((resolve, reject) => + { + RED.util.evaluateJSONataExpression(expr, msg, (error, result) => + { + if (error) + { + reject(error); + } + else + { + resolve(result); + } + }); + }); +} diff --git a/nodes/control.js b/nodes/control.js index cecd5cc..eb8454a 100644 --- a/nodes/control.js +++ b/nodes/control.js @@ -49,8 +49,13 @@ module.exports = function(RED) node.error(RED._("control.error.unconfigured")); setStatus(STATUS_UNCONFIGURED); } - else if (!validateConfiguration() || - !Utils.validateOutputProperties(RED, node, config.outputProperties, node.output, true)) + else if (!validateConfiguration() + || !Utils.validateOutputProperties( + RED, + node, + config.outputProperties, + node.output, + true)) { setStatus(STATUS_MISCONFIGURED); } @@ -58,7 +63,7 @@ module.exports = function(RED) { setStatus(); - node.on("input", function(msg, send, done) + node.on("input", async function(msg, send, done) { const context = {msg: msg}; @@ -73,7 +78,7 @@ module.exports = function(RED) try { - const request = createAPICall(context); + const request = await createAPICall(context); if (request) { sendRequest(context, @@ -234,10 +239,10 @@ module.exports = function(RED) function validateConfiguration() { - if ((config.actionType == "control") && - (((config.action == "setSoundSettings") && (config.soundSettings.length == 0)) || - ((config.action == "setSpeakerSettings") && (config.speakerSettings.length == 0)) || - ((config.action == "setPlaybackSettings") && (config.modeSettings.length == 0)))) + if ((config.actionType == "control") + && (((config.action == "setSoundSettings") && (config.soundSettings.length == 0)) + || ((config.action == "setSpeakerSettings") && (config.speakerSettings.length == 0)) + || ((config.action == "setPlaybackSettings") && (config.modeSettings.length == 0)))) { node.error(RED._("control.error.invalidSettings")); return false; @@ -286,8 +291,9 @@ module.exports = function(RED) } catch (e) { - node.error(RED._("@jens_rossbach/node-red-sony-audio/sonyaudio-device:common.error.invalidExpression", - {error: e.code + ": " + e.message + " [POS: " + e.position + ", TOK: '" + e.token + ", VAL: '" + e.value + "']"})); + node.error( + RED._("@jens_rossbach/node-red-sony-audio/sonyaudio-device:common.error.invalidExpression", + {error: e.code + ": " + e.message + " [POS: " + e.position + ", TOK: '" + e.token + ", VAL: '" + e.value + "']"})); return false; } } @@ -306,7 +312,7 @@ module.exports = function(RED) return true; } - function createAPICall(context) + async function createAPICall(context) { let apiCall = null; @@ -375,12 +381,13 @@ module.exports = function(RED) try { - value = RED.util.evaluateJSONataExpression(node.callParams, context.msg); + value = await Utils.evaluateJSONataExpression(RED, node.callParams, context.msg); } catch (e) { - throw new Error(RED._("@jens_rossbach/node-red-sony-audio/sonyaudio-device:common.error.invalidExpression", - {error: e.code + ": " + e.message + " [POS: " + e.position + ", TOK: '" + e.token + "']"})); + throw new Error( + RED._("@jens_rossbach/node-red-sony-audio/sonyaudio-device:common.error.invalidExpression", + {error: e.code + ": " + e.message + " [POS: " + e.position + ", TOK: '" + e.token + "']"})); } apiCall.params = getParameters(value); @@ -449,190 +456,235 @@ module.exports = function(RED) function setPowerStatus(context, status) { - sendRequest(context, - "system", - "setPowerStatus", - "1.1", - {status: status}); + sendRequest( + context, + "system", + "setPowerStatus", + "1.1", + {status: status}); } function setAudioVolume(context, volume, relative = false, zone = 0) { - sendRequest(context, - "audio", - "setAudioVolume", - "1.1", - {output: (zone > 0) ? "extOutput:zone?zone=" + zone : "", - volume: (relative && (volume > 0)) ? "+" + volume : volume.toString()}); + sendRequest( + context, + "audio", + "setAudioVolume", + "1.1", { + output: (zone > 0) + ? "extOutput:zone?zone=" + zone + : "", + volume: (relative && (volume > 0)) + ? "+" + volume + : volume.toString()}); } function setAudioMute(context, mute, zone = 0) { - sendRequest(context, - "audio", - "setAudioMute", - "1.1", - {output: (zone > 0) ? "extOutput:zone?zone=" + zone : "", - mute: mute}); + sendRequest( + context, + "audio", + "setAudioMute", + "1.1", { + output: (zone > 0) + ? "extOutput:zone?zone=" + zone + : "", + mute: mute}); } function setSoundSettings(context, params) { - sendRequest(context, - "audio", - "setSoundSettings", - "1.1", - {settings: params}); + sendRequest( + context, + "audio", + "setSoundSettings", + "1.1", + {settings: params}); } function setSpeakerSettings(context, params) { - sendRequest(context, - "audio", - "setSpeakerSettings", - "1.0", - {settings: params}); + sendRequest( + context, + "audio", + "setSpeakerSettings", + "1.0", + {settings: params}); } function setPlaybackModeSettings(context, params) { - sendRequest(context, - "avContent", - "setPlaybackModeSettings", - "1.0", - {settings: params}); + sendRequest( + context, + "avContent", + "setPlaybackModeSettings", + "1.0", + {settings: params}); } function setPlayContent(context, source, port = 0, preset = -1, zone = 0) { let uri = source; - if (((source == "extInput:hdmi") || - (source == "extInput:line")) && - (port > 0)) + if (((source == "extInput:hdmi") + || (source == "extInput:line")) + && (port > 0)) { uri += "?port=" + port; } - else if ((source == "radio:fm") && - (preset >= 0)) + else if ((source == "radio:fm") + && (preset >= 0)) { uri += "?contentId=" + preset; } - sendRequest(context, - "avContent", - "setPlayContent", - "1.2", - {output: (zone > 0) ? "extOutput:zone?zone=" + zone : "", - uri: uri}); + sendRequest( + context, + "avContent", + "setPlayContent", + "1.2", { + output: (zone > 0) + ? "extOutput:zone?zone=" + zone + : "", + uri: uri}); } function stopPlayingContent(context, zone = 0) { - sendRequest(context, - "avContent", - "stopPlayingContent", - "1.1", - {output: (zone > 0) ? "extOutput:zone?zone=" + zone : ""}); + sendRequest( + context, + "avContent", + "stopPlayingContent", + "1.1", { + output: (zone > 0) + ? "extOutput:zone?zone=" + zone + : ""}); } function pausePlayingContent(context, zone = 0) { - sendRequest(context, - "avContent", - "pausePlayingContent", - "1.1", - {output: (zone > 0) ? "extOutput:zone?zone=" + zone : ""}); + sendRequest( + context, + "avContent", + "pausePlayingContent", + "1.1", { + output: (zone > 0) + ? "extOutput:zone?zone=" + zone + : ""}); } function setPlayPreviousContent(context, zone = 0) { - sendRequest(context, - "avContent", - "setPlayPreviousContent", - "1.0", - {output: (zone > 0) ? "extOutput:zone?zone=" + zone : ""}); + sendRequest( + context, + "avContent", + "setPlayPreviousContent", + "1.0", { + output: (zone > 0) + ? "extOutput:zone?zone=" + zone + : ""}); } function setPlayNextContent(context, zone = 0) { - sendRequest(context, - "avContent", - "setPlayNextContent", - "1.0", - {output: (zone > 0) ? "extOutput:zone?zone=" + zone : ""}); + sendRequest( + context, + "avContent", + "setPlayNextContent", + "1.0", { + output: (zone > 0) + ? "extOutput:zone?zone=" + zone + : ""}); } function scanPlayingContent(context, fwd, zone = 0) { - sendRequest(context, - "avContent", - "scanPlayingContent", - "1.0", - {direction: fwd ? "fwd" : "bwd", - output: (zone > 0) ? "extOutput:zone?zone=" + zone : ""}); + sendRequest( + context, + "avContent", + "scanPlayingContent", + "1.0", { + direction: fwd + ? "fwd" + : "bwd", + output: (zone > 0) + ? "extOutput:zone?zone=" + zone + : ""}); } function getPowerStatus(context) { - sendRequest(context, - "system", - "getPowerStatus", - "1.1", - null); + sendRequest( + context, + "system", + "getPowerStatus", + "1.1", + null); } function getSWUpdateInfo(context, network) { - sendRequest(context, - "system", - "getSWUpdateInfo", - "1.0", - {network: network ? "true" : "false"}); + sendRequest( + context, + "system", + "getSWUpdateInfo", + "1.0", { + network: network + ? "true" + : "false"}); } function getPlayingContentInfo(context, zone = 0) { - sendRequest(context, - "avContent", - "getPlayingContentInfo", - "1.2", - {output: (zone > 0) ? "extOutput:zone?zone=" + zone : ""}); + sendRequest( + context, + "avContent", + "getPlayingContentInfo", + "1.2", { + output: (zone > 0) + ? "extOutput:zone?zone=" + zone + : ""}); } function getVolumeInfo(context, zone = 0) { - sendRequest(context, - "audio", - "getVolumeInformation", - "1.1", - {output: (zone > 0) ? "extOutput:zone?zone=" + zone : ""}); + sendRequest( + context, + "audio", + "getVolumeInformation", + "1.1", { + output: (zone > 0) + ? "extOutput:zone?zone=" + zone + : ""}); } function getSoundSettings(context, target) { - sendRequest(context, - "audio", - "getSoundSettings", - "1.1", - {target: target}); + sendRequest( + context, + "audio", + "getSoundSettings", + "1.1", + {target: target}); } function getSpeakerSettings(context, target) { - sendRequest(context, - "audio", - "getSpeakerSettings", - "1.0", - {target: target}); + sendRequest( + context, + "audio", + "getSpeakerSettings", + "1.0", + {target: target}); } function getPlaybackModeSettings(context, target) { - sendRequest(context, - "avContent", - "getPlaybackModeSettings", - "1.0", - {target: target}); + sendRequest( + context, + "avContent", + "getPlaybackModeSettings", + "1.0", + {target: target}); } function setStatus(stat = {}, duration = 0) @@ -662,14 +714,17 @@ module.exports = function(RED) node.device.sendRequest(service, method, version, params) .then(data => { - const out = Utils.prepareOutput(RED, node, node.output, config.msgPassThrough ? context.msg : null, data, config.sendIfPayload); - if (out) + Utils.prepareOutput(RED, node, node.output, config.msgPassThrough ? context.msg : null, data, config.sendIfPayload) + .then(out => { - context.send(out); - } + if (out) + { + context.send(out); + } - setStatus(STATUS_SUCCESS, STATUS_TEMP_DURATION); - context.done(); + setStatus(STATUS_SUCCESS, STATUS_TEMP_DURATION); + context.done(); + }); }) .catch(error => { diff --git a/nodes/device.js b/nodes/device.js index ef58d7c..0c53780 100644 --- a/nodes/device.js +++ b/nodes/device.js @@ -142,12 +142,17 @@ module.exports = function(RED) return new Promise((resolve, reject) => { const uri = "http://" + this.host + ":" + this.port + "/sony/" + service; - const body = {id: 1, - method: method, - version: version, - params: (params == null) ? [] : [params]}; - - this.trace(JSON.stringify(body)); + const body = + { + id: 1, + method: method, + version: version, + params: (params == null) + ? [] + : [params] + }; + + this.trace(uri + " -> " + JSON.stringify(body)); httpRequest(uri, {method: "post", headers: {"Content-Type": "application/json"}, body: JSON.stringify(body)}) .then(response => { @@ -164,11 +169,16 @@ module.exports = function(RED) { if ("result" in data) { - let respMsg = {host: this.host, - service: service, - method: method, - version: version, - payload: (data.result.length == 0) ? null : data.result[0]}; + const respMsg = + { + host: this.host, + service: service, + method: method, + version: version, + payload: (data.result.length == 0) + ? null + : data.result[0] + }; this.trace(JSON.stringify(respMsg)); resolve(respMsg); @@ -192,9 +202,12 @@ module.exports = function(RED) const id = this.nextSubscrId; this.nextSubscrId++; - this.subscribers[id] = {service: service, - filter: filter, - callback: callback}; + this.subscribers[id] = + { + service: service, + filter: filter, + callback: callback + }; if (service in this.receivers) { diff --git a/nodes/notify.js b/nodes/notify.js index 302de3f..831cfdf 100644 --- a/nodes/notify.js +++ b/nodes/notify.js @@ -119,11 +119,14 @@ module.exports = function(RED) node.status(STATUS_CONNECTING); node.subscribeId = node.device.subscribeEvents(config.service, filter, data => { - let out = Utils.prepareOutput(RED, node, node.output, null, data, config.sendIfPayload); - if (out) + Utils.prepareOutput(RED, node, node.output, null, data, config.sendIfPayload) + .then(out => { - node.send(out); - } + if (out) + { + node.send(out); + } + }); }); node.on("close", () => From cdafa6a342d2230f31a43db48aa895823fee19b7 Mon Sep 17 00:00:00 2001 From: Jens Rossbach Date: Sun, 7 Jan 2024 11:56:18 +0100 Subject: [PATCH 2/3] Update copyright year to 2024 --- LICENSE | 2 +- README.md | 4 ++-- nodes/common/event_constants.js | 2 +- nodes/common/event_recv.js | 2 +- nodes/common/utils.js | 2 +- nodes/control.html | 2 +- nodes/control.js | 2 +- nodes/device.html | 2 +- nodes/device.js | 2 +- nodes/locales/de/control.html | 2 +- nodes/locales/de/device.html | 2 +- nodes/locales/de/notify.html | 2 +- nodes/locales/en-US/control.html | 2 +- nodes/locales/en-US/device.html | 2 +- nodes/locales/en-US/notify.html | 2 +- nodes/notify.html | 2 +- nodes/notify.js | 2 +- 17 files changed, 18 insertions(+), 18 deletions(-) diff --git a/LICENSE b/LICENSE index 19252a0..c945f01 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Jens-Uwe Rossbach +Copyright (c) 2024 Jens-Uwe Rossbach Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 84ccde5..6ef9042 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ If you encountered a bug, would like to propose a new feature or simply want to To see what has changed in recent versions of the software, please have a look at the project's [change log](https://github.com/jensrossbach/node-red-sony-audio/blob/master/CHANGELOG.md). ## License -Copyright (c) 2023 Jens-Uwe Rossbach +Copyright (c) 2024 Jens-Uwe Rossbach This code is licensed under the MIT License. @@ -59,7 +59,7 @@ THIS SOFTWARE AND ITS AUTHOR ARE NOT AFFILIATED WITH SONY CORPORATION. The trademark "SONY" and any other product names, service names or logos of SONY used, quoted and/or referenced in this Web Site are trademarks or registered trademarks of Sony Corporation or any of its affiliates. ### License Audio Control API -Copyright (c) 2023 Sony Corporation. All rights reserved. +Copyright (c) 2024 Sony Corporation. All rights reserved. The 'Audio Control API' is licensed to the user by Sony Video & Sound products Inc. under the license terms of the [Creative Commons Attribution-NoDerivatives 4.0 International Public License](https://creativecommons.org/licenses/by-nd/4.0/legalcode). diff --git a/nodes/common/event_constants.js b/nodes/common/event_constants.js index 668bde0..26b9284 100644 --- a/nodes/common/event_constants.js +++ b/nodes/common/event_constants.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Jens-Uwe Rossbach + * Copyright (c) 2024 Jens-Uwe Rossbach * * This code is licensed under the MIT License. * diff --git a/nodes/common/event_recv.js b/nodes/common/event_recv.js index 5903419..da992a4 100644 --- a/nodes/common/event_recv.js +++ b/nodes/common/event_recv.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Jens-Uwe Rossbach + * Copyright (c) 2024 Jens-Uwe Rossbach * * This code is licensed under the MIT License. * diff --git a/nodes/common/utils.js b/nodes/common/utils.js index 37dbe29..a60babc 100644 --- a/nodes/common/utils.js +++ b/nodes/common/utils.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Jens-Uwe Rossbach + * Copyright (c) 2024 Jens-Uwe Rossbach * * This code is licensed under the MIT License. * diff --git a/nodes/control.html b/nodes/control.html index 419f79e..083cc17 100644 --- a/nodes/control.html +++ b/nodes/control.html @@ -1,5 +1,5 @@