diff --git a/data/display.html b/data/display.html index 2df521c0..1707aeb4 100644 --- a/data/display.html +++ b/data/display.html @@ -60,7 +60,9 @@

Display

  • Red/Yellow shaded: Slot is sticky and locked.
  • + +

    Currently active fade effect: Linear

    @@ -261,10 +263,27 @@

    Display

    } } + function prevSlot() { + var buttonActionIdPrevSlot = 2; /* See ButtonActionId */ + disableUI(); + + return wsClient.triggerButton({"actionId": buttonActionIdPrevSlot}).then(function(rsp) { + /* Nothing to do */ + }).catch(function(err) { + if ("undefined" !== typeof err) { + console.error(err); + } + return dialog.showError("

    Failed.

    "); + }).finally(function() { + enableUI(); + }); + } + function nextSlot() { + var buttonActionIdNextSlot = 1; /* See ButtonActionId */ disableUI(); - return wsClient.triggerButton().then(function(rsp) { + return wsClient.triggerButton({"actionId": buttonActionIdNextSlot}).then(function(rsp) { /* Nothing to do */ }).catch(function(err) { if ("undefined" !== typeof err) { @@ -276,6 +295,22 @@

    Display

    }); } + function updateDisplay() { + disableUI(); + + /* Currently off? */ + if (0 === timerId) { + timerId = window.setTimeout(getDisplayContent, period); + $("#updateDisplayButton").text("Disable auto. display update"); + } else { + window.clearTimeout(timerId); + timerId = 0; + $("#updateDisplayButton").text("Enable auto. display update"); + } + + enableUI(); + } + function move(uid, slotId) { return wsClient.move({ uid: uid, @@ -566,9 +601,6 @@

    Display

    currentFadeEffect = rsp.fadeEffect; updateFadeEffect(); }).then(function(rsp) { - /* Request display content periodically. */ - timerId = window.setTimeout(getDisplayContent, period); - /* UI is enabled at least. */ enableUI(); }).catch(function(err) { diff --git a/data/js/ws.js b/data/js/ws.js index d175ccdd..0ad93201 100644 --- a/data/js/ws.js +++ b/data/js/ws.js @@ -557,14 +557,21 @@ pixelix.ws.Client.prototype.stopIperf = function(options) { }.bind(this)); }; -pixelix.ws.Client.prototype.triggerButton = function() { +pixelix.ws.Client.prototype.triggerButton = function(options) { return new Promise(function(resolve, reject) { + var par = null; + if (null === this._socket) { reject(); } else { + + if ("number" === typeof options.actionId) { + par = options.actionId.toString(); + } + this._sendCmd({ name: "BUTTON", - par: null, + par: par, resolve: resolve, reject: reject }); diff --git a/src/Common/ButtonActions.h b/src/Common/ButtonActions.h index 71e7efe7..f6857cbe 100644 --- a/src/Common/ButtonActions.h +++ b/src/Common/ButtonActions.h @@ -66,7 +66,9 @@ enum ButtonActionId BUTTON_ACTION_ID_TOGGLE_DISPLAY_OFF_ON, /**< Toggle the display off/on */ BUTTON_ACTION_ID_SWEEP_BRIGHTNESS, /**< Sweep brightness from dark to bright and reverse */ BUTTON_ACTION_ID_INC_BRIGHTNESS, /**< Increase display brightness till maximum. */ - BUTTON_ACTION_ID_DEC_BRIGHTNESS /**< Decrease display brightness till minimum. */ + BUTTON_ACTION_ID_DEC_BRIGHTNESS, /**< Decrease display brightness till minimum. */ + + BUTTON_ACTION_ID_MAX /**< Max. action id (always the last one) */ }; /** diff --git a/src/Web/RestApi.cpp b/src/Web/RestApi.cpp index 56505f04..765483ed 100644 --- a/src/Web/RestApi.cpp +++ b/src/Web/RestApi.cpp @@ -42,6 +42,7 @@ #include "FileSystem.h" #include "RestUtil.h" #include "SlotList.h" +#include "ButtonActions.h" #include #include @@ -71,6 +72,42 @@ typedef struct } ContentTypeElem; +/** + * Virtual button which can be triggered via REST API. + */ +class RestApiButton : public ButtonActions +{ +public: + + /** + * Construct virtual button instance. + */ + RestApiButton() : + ButtonActions() + { + } + + /** + * Destroy virtual button instance. + */ + virtual ~RestApiButton() + { + } + + /** + * Execute action by button action id. + * + * @param[in] id Button action id + */ + void executeAction(ButtonActionId id) + { + ButtonActions::executeAction(id); + } + +private: + +}; + /****************************************************************************** * Prototypes *****************************************************************************/ @@ -201,10 +238,38 @@ static void handleButton(AsyncWebServerRequest* request) } else { - DisplayMgr::getInstance().activateNextSlot(); - - (void)RestUtil::prepareRspSuccess(jsonDoc); - httpStatusCode = HttpStatus::STATUS_CODE_OK; + ButtonActionId actionId = BUTTON_ACTION_ID_ACTIVATE_NEXT_SLOT; /* Default */ + bool isSuccessful = true; + + if (true == request->hasArg("actionId")) + { + int32_t i32ActionId = request->arg("actionId").toInt(); + + if ((0 > i32ActionId) || + (BUTTON_ACTION_ID_MAX <= i32ActionId)) + { + isSuccessful = false; + } + else + { + actionId = static_cast(i32ActionId); + } + } + + if (false == isSuccessful) + { + RestUtil::prepareRspError(jsonDoc, "Invalid action id."); + httpStatusCode = HttpStatus::STATUS_CODE_METHOD_NOT_ALLOWED; + } + else + { + RestApiButton buttonActions; + + buttonActions.executeAction(actionId); + + (void)RestUtil::prepareRspSuccess(jsonDoc); + httpStatusCode = HttpStatus::STATUS_CODE_OK; + } } RestUtil::sendJsonRsp(request, jsonDoc, httpStatusCode); diff --git a/src/Web/WsCommand/WsCmdButton.cpp b/src/Web/WsCommand/WsCmdButton.cpp index 1c63b13a..6e1f82b1 100644 --- a/src/Web/WsCommand/WsCmdButton.cpp +++ b/src/Web/WsCommand/WsCmdButton.cpp @@ -33,7 +33,7 @@ * Includes *****************************************************************************/ #include "WsCmdButton.h" -#include "DisplayMgr.h" +#include "ButtonActions.h" #include @@ -76,7 +76,7 @@ void WsCmdButton::execute(AsyncWebSocket* server, AsyncWebSocketClient* client) } else { - DisplayMgr::getInstance().activateNextSlot(); + executeAction(m_actionId); sendPositiveResponse(server, client); } @@ -86,9 +86,16 @@ void WsCmdButton::execute(AsyncWebSocket* server, AsyncWebSocketClient* client) void WsCmdButton::setPar(const char* par) { - UTIL_NOT_USED(par); + uint8_t actionId; - m_isError = true; + if (false == Util::strToUInt8(par, actionId)) + { + m_isError = true; + } + else + { + m_actionId = static_cast(actionId); + } } /****************************************************************************** diff --git a/src/Web/WsCommand/WsCmdButton.h b/src/Web/WsCommand/WsCmdButton.h index cb9c0d29..cade8191 100644 --- a/src/Web/WsCommand/WsCmdButton.h +++ b/src/Web/WsCommand/WsCmdButton.h @@ -44,6 +44,7 @@ * Includes *****************************************************************************/ #include "WsCmd.h" +#include "ButtonActions.h" /****************************************************************************** * Macros @@ -56,7 +57,7 @@ /** * Websocket command to control the virtual user button. */ -class WsCmdButton: public WsCmd +class WsCmdButton: public WsCmd, public ButtonActions { public: @@ -65,7 +66,9 @@ class WsCmdButton: public WsCmd */ WsCmdButton() : WsCmd("BUTTON"), - m_isError(false) + ButtonActions(), + m_isError(false), + m_actionId(BUTTON_ACTION_ID_ACTIVATE_NEXT_SLOT) /* Default */ { } @@ -93,7 +96,8 @@ class WsCmdButton: public WsCmd private: - bool m_isError; /**< Any error happened during parameter reception? */ + bool m_isError; /**< Any error happened during parameter reception? */ + ButtonActionId m_actionId; /**< Id of the action, which to execute. */ WsCmdButton(const WsCmdButton& cmd); WsCmdButton& operator=(const WsCmdButton& cmd);