Skip to content

Commit

Permalink
Virtual buttons controlled via websocket or REST API can now execute …
Browse files Browse the repository at this point in the history
…all defined button actions. The display page was extended to jump to previous/next slot.

Additional the automatic display update is disabled by default. Use the button to enable it.
  • Loading branch information
BlueAndi committed Dec 9, 2023
1 parent 830dceb commit 84634d0
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 18 deletions.
40 changes: 36 additions & 4 deletions data/display.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ <h1 class="mt-5">Display</h1>
<li>Red/Yellow shaded: Slot is sticky and locked.</li>
</ul>
<p>
<button class="btn btn-light" type="button" onclick="prevSlot()" disabled>Previous slot</button>
<button class="btn btn-light" type="button" onclick="nextSlot()" disabled>Next slot</button>
<button id="updateDisplayButton" class="btn btn-light" type="button" onclick="updateDisplay()" disabled>Enable auto. display update</button>
</p>
<p>Currently active fade effect: <span id="lableFadeEffect"> Linear</span></p>
<p><button class="btn btn-light" type="button" onclick="nextEffect()" disabled>Next fade effect</button></p>
Expand Down Expand Up @@ -261,10 +263,27 @@ <h1 class="mt-5">Display</h1>
}
}

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("<p>Failed.</p>");
}).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) {
Expand All @@ -276,6 +295,22 @@ <h1 class="mt-5">Display</h1>
});
}

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,
Expand Down Expand Up @@ -566,9 +601,6 @@ <h1 class="mt-5">Display</h1>
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) {
Expand Down
11 changes: 9 additions & 2 deletions data/js/ws.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
});
Expand Down
4 changes: 3 additions & 1 deletion src/Common/ButtonActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) */
};

/**
Expand Down
73 changes: 69 additions & 4 deletions src/Web/RestApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "FileSystem.h"
#include "RestUtil.h"
#include "SlotList.h"
#include "ButtonActions.h"

#include <Util.h>
#include <WiFi.h>
Expand Down Expand Up @@ -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
*****************************************************************************/
Expand Down Expand Up @@ -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<ButtonActionId>(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);
Expand Down
15 changes: 11 additions & 4 deletions src/Web/WsCommand/WsCmdButton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
* Includes
*****************************************************************************/
#include "WsCmdButton.h"
#include "DisplayMgr.h"
#include "ButtonActions.h"

#include <Util.h>

Expand Down Expand Up @@ -76,7 +76,7 @@ void WsCmdButton::execute(AsyncWebSocket* server, AsyncWebSocketClient* client)
}
else
{
DisplayMgr::getInstance().activateNextSlot();
executeAction(m_actionId);

sendPositiveResponse(server, client);
}
Expand All @@ -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<ButtonActionId>(actionId);
}
}

/******************************************************************************
Expand Down
10 changes: 7 additions & 3 deletions src/Web/WsCommand/WsCmdButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* Includes
*****************************************************************************/
#include "WsCmd.h"
#include "ButtonActions.h"

/******************************************************************************
* Macros
Expand All @@ -56,7 +57,7 @@
/**
* Websocket command to control the virtual user button.
*/
class WsCmdButton: public WsCmd
class WsCmdButton: public WsCmd, public ButtonActions
{
public:

Expand All @@ -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 */
{
}

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 84634d0

Please sign in to comment.