Press & Hold Trigger for Generic Device (Device Handling JavaScript)

I've implemented basic press triggers for my 8BitDo Micro controller in the 'Device Handling' JavaScript section. For certain buttons, I want to add a 'hold' state trigger in addition to the simple 'press' trigger. As in, when 'A' is held for less than 500-1000ms or so, the function sends trigger 'A (Press)'; when it's held for more, the function sends trigger 'A (Hold)'.

Only I can't see how this is possible. As the script is run on each event, there's no way to record or retrieve past events. Right? Or am I missing something? Is there another way of achieving what I want to do?

You'd need to maintain button state in static variables outside of the function and make use of bttGetNextEvenWithoutChange() so that your analyzeDeviceInput() function keeps getting called again and again. See e.g. Generic Devices: Report repeated events even if monitored bytes don't change for some discussion.

Ah, for some reason I'd assumed the editable script was isolated or siloed off somehow, or that only the function was called. Thanks, will take another look at it

Here's my quick implementation should it help anyone else. Please do post here if you make any improvements :tada:

firstPress = -1; // Stores first report time
lastPress = -1; // Stores last report time
pressNum = 0; // Number of reports (logged 'presses') in continued report mode
triggerButton = null; // Store which button should trigger
hasTriggered = false; // Store if trigger has already been sent
holdTime = 500; // Defines length to hold button for triggering hold state (in ms)
function analyzeDeviceInput(targetDevice, reportID, reportDataHex) {
	let reportBuffer = buffer.Buffer.from(reportDataHex, 'hex');
    if(reportBuffer.readUInt8(2) === 0x00) {
        if(pressNum > 0) {
            if(lastPress - firstPress < holdTime) {
                log(triggerButton + ' (Press)');
                bttTriggerDeviceTrigger(targetDevice, triggerButton);
            }
        }
        firstPress = -1;
        lastPress = -1;
        pressNum = 0;
        triggerButton = null;
        hasTriggered = false;
    } else if(reportBuffer.readUInt8(2) === 0x20) {
        triggerButton = 'Star';
        pressNum++;
        if(pressNum === 1) {
            firstPress = Date.now();
        } else if(pressNum > 1) {
            lastPress = Date.now();
        }
        if(!hasTriggered && lastPress - firstPress >= holdTime) {
            log('Star (Hold)');
            bttTriggerDeviceTrigger(targetDevice, 'Star (Hold)');
            hasTriggered = true;
        }
        bttGetNextEvenWithoutChange(targetDevice, reportID)
    }
}
2 Likes