From 9b2467392bf1a9e35e36e1aa38ee27de9da45d3f Mon Sep 17 00:00:00 2001 From: Pavel Petroshenko Date: Wed, 19 Apr 2017 11:53:37 -0700 Subject: [PATCH 1/9] MessageManager.class.nut -> MessageManager.lib.nut and the version is updated. --- .imptest | 2 +- MessageManager.class.nut => MessageManager.lib.nut | 2 ++ README.md | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) rename MessageManager.class.nut => MessageManager.lib.nut (99%) diff --git a/.imptest b/.imptest index ba79aea..b60e5d0 100644 --- a/.imptest +++ b/.imptest @@ -4,7 +4,7 @@ "2370797838a609ee" /* E */ ], "agentFile": "tests/agent.nut", - "deviceFile": "MessageManager.class.nut", + "deviceFile": "MessageManager.lib.nut", "stopOnFailure": false, "timeout": 30, "tests": [ diff --git a/MessageManager.class.nut b/MessageManager.lib.nut similarity index 99% rename from MessageManager.class.nut rename to MessageManager.lib.nut index 85bf76d..d38610d 100644 --- a/MessageManager.class.nut +++ b/MessageManager.lib.nut @@ -522,6 +522,7 @@ class MessageManager { // // Returns: Nothing function _onConnect() { + server.log((_isAgent()? "[A]: ": "[D]: ") +"YYY") _processRetryQueue(); _partner.send(MM_MESSAGE_TYPE_CONNECTED, null); } @@ -871,6 +872,7 @@ class MessageManager { // // Returns: Nothing function _onConReceived(payload) { + server.log((_isAgent()? "[A]: ": "[D]: ") +"XXX") // Call the onPartnerConnected handler if (_isFunc(_onPartnerCon)) { _onPartnerCon( diff --git a/README.md b/README.md index 384a131..d63ff05 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ MessageManager is framework for asynchronous bidirectional agent to device commu The library uses [ConnectionManager](https://github.com/electricimp/ConnectionManager) on the device side to receive notifications of connection and disconnection events, and to monitor connection status (ie. so that no attempt it made to send messages when the device is disconnected). -**To add this library to your project, add** `#require "messagemanager.class.nut:1.0.2"` **to the top of your agent and device code.** +**To add this library to your project, add** `#require "MessageManager.lib.nut:2.0.0"` **to the top of your agent and device code.** **Note** MessageManager is designed to run over reliable (ie. TCP/TLS) connections. Retries only occur in the case of dropped connections or lost packets, or if called manually from [beforeSend()](#mmanager_before_send) or [beforeRetry()](#mmanager_before_retry). @@ -291,7 +291,7 @@ Sets a message-local version of the [MessageManager.onReply()](#mmanager_on_repl // Device code #require "ConnectionManager.class.nut:1.0.2" -#require "MessageManager.class.nut:1.0.2" +#require "MessageManager.lib.nut:2.0.0" local cm = ConnectionManager({ "blinkupBehavior": ConnectionManager.BLINK_ALWAYS, @@ -334,7 +334,7 @@ sendData(); ```squirrel // Agent code -#require "MessageManager.class.nut:1.0.2" +#require "MessageManager.lib.nut:2.0.0" local mm = MessageManager(); From 427bc9c28ba92bcdf5301d35bbe508a53bf65874 Mon Sep 17 00:00:00 2001 From: Pavel Petroshenko Date: Wed, 19 Apr 2017 21:46:24 -0700 Subject: [PATCH 2/9] Removed debug logs. --- MessageManager.lib.nut | 2 -- 1 file changed, 2 deletions(-) diff --git a/MessageManager.lib.nut b/MessageManager.lib.nut index d38610d..85bf76d 100644 --- a/MessageManager.lib.nut +++ b/MessageManager.lib.nut @@ -522,7 +522,6 @@ class MessageManager { // // Returns: Nothing function _onConnect() { - server.log((_isAgent()? "[A]: ": "[D]: ") +"YYY") _processRetryQueue(); _partner.send(MM_MESSAGE_TYPE_CONNECTED, null); } @@ -872,7 +871,6 @@ class MessageManager { // // Returns: Nothing function _onConReceived(payload) { - server.log((_isAgent()? "[A]: ": "[D]: ") +"XXX") // Call the onPartnerConnected handler if (_isFunc(_onPartnerCon)) { _onPartnerCon( From d3bc15bafe0cb3e92c09046a7260e6e18d8591d5 Mon Sep 17 00:00:00 2001 From: Pavel Petroshenko Date: Fri, 21 Apr 2017 21:16:50 -0700 Subject: [PATCH 3/9] Legal header updated. Async replies. --- MessageManager.lib.nut | 55 +++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/MessageManager.lib.nut b/MessageManager.lib.nut index 85bf76d..ed1c4ef 100644 --- a/MessageManager.lib.nut +++ b/MessageManager.lib.nut @@ -1,6 +1,27 @@ -// Copyright (c) 2016-2017 Electric Imp -// This file is licensed under the MIT License -// http://opensource.org/licenses/MIT +// MIT License +// +// Copyright 2016-2017 Electric Imp +// +// SPDX-License-Identifier: MIT +// +// 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. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO +// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES +// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + // Default configuration values const MM_DEFAULT_DEBUG = 0; @@ -157,6 +178,9 @@ class MessageManager { // Handler to be called when the message is replied _onReply = null; + // Flag indicating that the message was acknowledged + _acked = null; + // Data message constructor // Constructor is not going to be called from the user code // @@ -177,6 +201,7 @@ class MessageManager { "created": time() }; this.tries = 0; + this._acked = false; this.metadata = metadata; this._timeout = timeout; this._nextRetry = 0; @@ -549,16 +574,16 @@ class MessageManager { // Clean up the timer _queueTimer = null; - local t = time(); + local now = time(); local drop = true; // Process timed out messages from the sent (waiting for ack) queue foreach (id, msg in _sentQueue) { local timeout = msg._timeout ? msg._timeout : _msgTimeout; - if (t - msg._sent > timeout) { + if (now - msg._sent > timeout) { local wait = function(duration = null) { local delay = duration != null ? duration : timeout; - msg._timeout = t - msg._sent + delay; + msg._timeout = now - msg._sent + delay; drop = false; }.bindenv(this); @@ -566,8 +591,10 @@ class MessageManager { _callOnFail(msg, MM_ERR_USER_CALLED_FAIL); }.bindenv(this); - _isFunc(msg._onTimeout) && msg._onTimeout(msg, wait, fail); - _isFunc(_onTimeout) && _onTimeout(msg, wait, fail); + if (!msg._acked) { + _isFunc(msg._onTimeout) && msg._onTimeout(msg, wait, fail); + _isFunc(_onTimeout) && _onTimeout(msg, wait, fail); + } if (drop) { delete _sentQueue[id]; @@ -589,10 +616,10 @@ class MessageManager { // // Returns: Nothing function _processRetryQueue() { - local t = time(); + local now = time(); // Process retry message queue foreach (id, msg in _retryQueue) { - if (t >= msg._nextRetry) { + if (now >= msg._nextRetry) { _retry(msg); } } @@ -790,8 +817,12 @@ class MessageManager { _isFunc(msg._onAck) && msg._onAck(msg); _isFunc(_onAck) && _onAck(msg); - // Delete the acked message from the queue - delete _sentQueue[id]; + // Delete the acked message from the queue if there is no _onReply handler set (either global or message-specific) + if (!_isFunc(msg._onReply) && !_isFunc(_onReply)) { + delete _sentQueue[id] + } else { + msg._acked = true; + } } } From 3e96d7b3681635653ecc8c4fb720ba2187b8ac81 Mon Sep 17 00:00:00 2001 From: Pavel Petroshenko Date: Fri, 21 Apr 2017 21:19:34 -0700 Subject: [PATCH 4/9] LICENSE file updated. --- LICENSE | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/LICENSE b/LICENSE index e49d082..a01b64f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,8 @@ -The MIT License (MIT) +MIT License -Copyright (c) 2016 Electric Imp +Copyright 2016-2017 Electric Imp + +SPDX-License-Identifier: MIT Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -9,13 +11,13 @@ 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. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO +EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES +OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file From 5b8aa7b12bd53a3542b23dad97871832d3ac325b Mon Sep 17 00:00:00 2001 From: Pavel Petroshenko Date: Fri, 21 Apr 2017 22:31:11 -0700 Subject: [PATCH 5/9] Version updated. --- MessageManager.lib.nut | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MessageManager.lib.nut b/MessageManager.lib.nut index ed1c4ef..642438a 100644 --- a/MessageManager.lib.nut +++ b/MessageManager.lib.nut @@ -59,7 +59,7 @@ const MM_HANDLER_NAME_ON_TIMEOUT = "onTimeout"; class MessageManager { - static VERSION = "1.0.2"; + static VERSION = "2.0.0"; // Queue of messages that are pending for acknowledgement _sentQueue = null; From 5d2b14115d994575014f14cc60e62118e9cc2cf8 Mon Sep 17 00:00:00 2001 From: Pavel Petroshenko Date: Sun, 23 Apr 2017 18:35:58 -0700 Subject: [PATCH 6/9] Copyrights. --- tests/Basic.device.test.nut | 27 ++++++++++++++++++++++++--- tests/Connect.device.test.nut | 27 ++++++++++++++++++++++++--- tests/Throttling.device.test.nut | 27 ++++++++++++++++++++++++--- 3 files changed, 72 insertions(+), 9 deletions(-) diff --git a/tests/Basic.device.test.nut b/tests/Basic.device.test.nut index 26c81e8..e54f731 100644 --- a/tests/Basic.device.test.nut +++ b/tests/Basic.device.test.nut @@ -1,6 +1,27 @@ -// Copyright (c) 2017 Electric Imp -// This file is licensed under the MIT License -// http://opensource.org/licenses/MIT +// MIT License +// +// Copyright 2016-2017 Electric Imp +// +// SPDX-License-Identifier: MIT +// +// 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. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO +// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES +// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + class BasicTestCase extends ImpTestCase { diff --git a/tests/Connect.device.test.nut b/tests/Connect.device.test.nut index 974563e..b67f764 100644 --- a/tests/Connect.device.test.nut +++ b/tests/Connect.device.test.nut @@ -1,6 +1,27 @@ -// Copyright (c) 2017 Electric Imp -// This file is licensed under the MIT License -// http://opensource.org/licenses/MIT +// MIT License +// +// Copyright 2016-2017 Electric Imp +// +// SPDX-License-Identifier: MIT +// +// 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. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO +// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES +// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + class ConnectTestCase extends ImpTestCase { diff --git a/tests/Throttling.device.test.nut b/tests/Throttling.device.test.nut index bfbe9ab..8473017 100644 --- a/tests/Throttling.device.test.nut +++ b/tests/Throttling.device.test.nut @@ -1,6 +1,27 @@ -// Copyright (c) 2017 Electric Imp -// This file is licensed under the MIT License -// http://opensource.org/licenses/MIT +// MIT License +// +// Copyright 2016-2017 Electric Imp +// +// SPDX-License-Identifier: MIT +// +// 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. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO +// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES +// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + class ThrottlingDeviceTestCase extends ImpTestCase { From a46e58a2a00dd6b64af46df6b95f3db119f17a4d Mon Sep 17 00:00:00 2001 From: Pavel Petroshenko Date: Mon, 24 Apr 2017 17:17:46 -0700 Subject: [PATCH 7/9] Make sure the tests pass now. --- MessageManager.lib.nut | 7 ++- tests/Connect.device.test.nut | 7 +-- tests/agent.nut | 94 +++++++++++++++++++++++++++-------- 3 files changed, 81 insertions(+), 27 deletions(-) diff --git a/MessageManager.lib.nut b/MessageManager.lib.nut index 642438a..6e2e87e 100644 --- a/MessageManager.lib.nut +++ b/MessageManager.lib.nut @@ -327,8 +327,11 @@ class MessageManager { _cm.onConnect(_onConnect.bindenv(this)); _cm.onDisconnect(_onDisconnect.bindenv(this)); - // Make sure we are connected and the onConnect callback is triggered - _cm.connect(); + // On device side make sure we are connected and the + // onConnect callback is triggered to notify the agent + if (!_isAgent()) { + _cm.connect(); + } } } diff --git a/tests/Connect.device.test.nut b/tests/Connect.device.test.nut index b67f764..60b2246 100644 --- a/tests/Connect.device.test.nut +++ b/tests/Connect.device.test.nut @@ -77,9 +77,6 @@ class ConnectTestCase extends ImpTestCase { } function setUp() { - // agent.on("MM_CONNECT", function(payload) { - // }); - _cm = MyConnectionManager(); local config = { @@ -95,8 +92,8 @@ class ConnectTestCase extends ImpTestCase { function testConnected() { return Promise(function(resolve, reject) { imp.wakeup(1, function() { - assertTrue(_partnerConnected, "Partner connected"); - assertEqual(_onConnectedReply, "No messages", "Connected reply"); + assertTrue(_partnerConnected, "Partner connected: " + _partnerConnected); + assertEqual("No messages", _onConnectedReply, "Connected reply"); resolve(); }.bindenv(this)); }.bindenv(this)); diff --git a/tests/agent.nut b/tests/agent.nut index 4c0bc2c..eddce58 100644 --- a/tests/agent.nut +++ b/tests/agent.nut @@ -1,21 +1,75 @@ -// Copyright (c) 2017 Electric Imp -// This file is licensed under the MIT License -// http://opensource.org/licenses/MIT - -device.on("MM_DATA", function(payload) { - device.send("MM_REPLY", { - "id" : payload["id"], - "data" : payload["data"] - }); -}); - -device.on("MM_CONNECT", function(payload) { - sendConnected(); - device.send("MM_CONNECT_REPLY", { - "data" : "No messages" - }); -}) - -function sendConnected() { - device.send("MM_CONNECT", null); +// MIT License +// +// Copyright 2016-2017 Electric Imp +// +// SPDX-License-Identifier: MIT +// +// 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. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO +// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES +// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +@include "https://raw.githubusercontent.com/electricimp/ConnectionManager/master/ConnectionManager.class.nut" +@include "MessageManager.lib.nut" + +class MyConnectionManager { + _connected = null; + _onConnect = null; + _onDisconnect = null; + + function constructor() { + _connected = true; + } + + function isConnected() { + return _connected; + } + + function disconnect() { + this._connected = false; + _isFunc(_onDisconnect) && _onDisconnect(true); + } + + function connect() { + server.log(" [AGT] connected"); + this._connected = true; + _isFunc(_onConnect) && _onConnect(); + } + + function onDisconnect(handler) { + _onDisconnect = handler; + } + + function onConnect(handler) { + _onConnect = handler; + } + + function _isFunc(f) { + return f && typeof f == "function"; + } +} + +local cm = MyConnectionManager() +function onPartnerConnected(reply) { + cm.connect(); + reply("No messages"); } +local config = { + "onPartnerConnected" : onPartnerConnected.bindenv(this), + "connectionManager" : cm +}; +local mm = MessageManager(config); +mm.on("test", @(data, reply) reply(data)); From a750ee480b4931b5846de7f7c50a6dd84efab823 Mon Sep 17 00:00:00 2001 From: Pavel Petroshenko Date: Mon, 1 May 2017 13:20:37 -0700 Subject: [PATCH 8/9] Updated the .imptest to use another device. --- .imptest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.imptest b/.imptest index b60e5d0..e5e9c5b 100644 --- a/.imptest +++ b/.imptest @@ -1,7 +1,7 @@ { "modelId": "qryDFGlK1tUd" /* B */, "devices": [ - "2370797838a609ee" /* E */ + "233f4aafaf952dee" /* G */ ], "agentFile": "tests/agent.nut", "deviceFile": "MessageManager.lib.nut", From 4c9c169c65313ed247f794dd07b86ed2df30c67c Mon Sep 17 00:00:00 2001 From: Max Mueller Date: Thu, 4 May 2017 14:05:56 -0400 Subject: [PATCH 9/9] Add multiple middleware for user-flexibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added four middleware functions: - beforeOnAck - gets called prior to “onAck” callbacks being fired - beforeOnReply - gets called prior to “onReply” callbacks being fired - beforeOnData - gets called prior to any “on” callbacks being fired - beforeReply - gets called before a reply is sent --- MessageManager.lib.nut | 83 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/MessageManager.lib.nut b/MessageManager.lib.nut index 6e2e87e..3d201df 100644 --- a/MessageManager.lib.nut +++ b/MessageManager.lib.nut @@ -59,7 +59,7 @@ const MM_HANDLER_NAME_ON_TIMEOUT = "onTimeout"; class MessageManager { - static VERSION = "2.0.0"; + static VERSION = "2.1.0"; // Queue of messages that are pending for acknowledgement _sentQueue = null; @@ -130,9 +130,21 @@ class MessageManager { // Global handler to be called when a message is acknowledged _onAck = null; + // Global handler to be called prior to the onAck handler(s) being called + _beforeOnAck = null; + // Global handler to be called when a message is replied _onReply = null; + // Global handler to be called prior to the onReply handler(s) being called + _beforeOnReply = null; + + // Global handler to be called when any data message is received + _beforeOnData = null; + + // Global handler to be called prior to any message being replied + _beforeReply = null; + // User defined callback to generate next message id _nextIdGenerator = null; @@ -470,6 +482,19 @@ class MessageManager { _onAck = handler; } + // Sets the handler to be called before caling the onAck handler(s) + // + // Parameters: + // handler The handler to be called. It has signature: + // handler(message) + // Paremeters: + // message The message that was acked + // + // Returns: Nothing + function beforeOnAck(handler) { + _beforeOnAck = handler; + } + // Sets the handler to be called when the message is replied // // Parameters: @@ -483,6 +508,44 @@ class MessageManager { _onReply = handler; } + // Sets the handler to be called before calling the onReply handler(s) + // + // Parameters: + // handler The handler to be called. It has signature: + // handler(message, response), where + // message The message that received a reply + // response Response received as reply + // + // Returns: Nothing + function beforeOnReply(handler) { + _beforeOnReply = handler; + } + + // Sets the handler to be called before calling "on" handlers + // + // Parameters: + // handler The handler to be called. It has signature: + // handler(name, payload), where + // name The message name + // response The message payload + // + // Returns: Nothing + function beforeOnData(handler) { + _beforeOnData = handler; + } + + // Sets the handler to be called before calling a reply is sent + // + // Parameters: + // handler The handler to be called. It has signature: + // handler(replyPayload), where + // replyPayload The payload of the reply to be sent + // + // Returns: Nothing + function beforeReply(handler) { + _beforeReply = handler; + } + // Returns the overall number of pending messages // (either waiting for acknowledgement or hanging in the retry queue) // @@ -772,17 +835,23 @@ class MessageManager { local handlerFound = false; local error = 0; + _isFunc(_beforeOnData) && _beforeOnData(name, payload); + if (name in _on) { local handler = _on[name]; if (_isFunc(handler)) { handlerFound = true; handler(payload, function/*reply*/(data = null) { replied = true; - error = _partner.send(MM_MESSAGE_TYPE_REPLY, { - "id" : payload["id"], - "data" : data - }); - }); + + local replyPayload = { + "id" : payload["id"], + "data" : data + } + + _isFunc(_beforeReply) && _beforeReply(replyPayload); + error = _partner.send(MM_MESSAGE_TYPE_REPLY, replyPayload); + }.bindenv(this)); } } @@ -817,6 +886,7 @@ class MessageManager { if (id in _sentQueue) { local msg = _sentQueue[id]; + _isFunc(_beforeOnAck) && msg._beforeOnAck(msg); _isFunc(msg._onAck) && msg._onAck(msg); _isFunc(_onAck) && _onAck(msg); @@ -891,6 +961,7 @@ class MessageManager { _isFunc(_onAck) && _onAck(msg); // Then call the global handlers + _isFunc(_beforeOnReply) && _beforeOnReply(msg, payload); _isFunc(msg._onReply) && msg._onReply(msg, payload["data"]); _isFunc(_onReply) && _onReply(msg, payload["data"]);