Generic Devices -> Button combinations possible?

I love this new feature! Very cool idea to implement it this way :clap:t2:

I got my PS4 Controller to work. I just had to uncheck 'Report' in the 'parse device' window the first time I used it. Now it works with 'Report' being checked.

When I press two buttons while holding the first one, I can see that the numbers are shown correctly. The first pressed button stays on the value for being pressed and the second one also changes.

What do I have to write in the code, to connect these to buttons two set up a combined Trigger?

Thanks for the great work!

Can you post the "change log"? First you need to click on the bytes that change, afterwards BTT will generate the log when you trigger the functions.

Sure, I hope this are the parts you're interested in:

1675168434.498322|lic|newest date 2021-10-30 12:33:05 +0000|
1675168434.498378|lic|lict 115328943-chre5345849c659-3410887d8e|
1675168434.785582|ASL|deallocating root Window controller|
1675168434.809141|ASL|deallocating BTTPrefsMenuContentContainerVC|
1675168434.809425|ASL|dealloc main ui structure vc|
1675168434.809467|ASL|deallocating BTTMainUIStructureVC|
1675168434.809552|ASL|deallocating BTTMainSplitViewController|
1675168434.810166|ASL|deallocating BTTAppListVC|
1675168434.810495|ASL|deallocating BTTTopMenuVC|
1675168434.811478|ASL|deallocating BTTOutlineModeVC|
1675168434.811747|ASL|deallocating BTTConfigurationVC|
1675168434.818788|ASL|dealloc level1|
1675168434.818829|ASL|deallocating BTTLevel1VC|
1675168434.819242|ASL|deallocating BTTLevel3VC|
1675168434.819579|ASL|deallocating BTTConfigurationVC|
1675168434.839116|NEWUI|DEALLOC Settings Container VC|
1675168438.019928|ASL|result {
    BTTGenericDeviceActiveReports =     {
        1 = 1;
    };
    BTTGenericDeviceScript = "// Enter your input analyzer script here. \n// Do not change the function signatures\nfunction analyzeDeviceInput(targetDevice, reportID, reportDataHex) {\n      \n\tlet reportBuffer = buffer.Buffer.from(reportDataHex, 'hex');\n        // the values you see above are in hex format. To read such a byte\n        // use readUInt8(index).\n        if(reportBuffer.readUInt8(7) === 0x01) {\n            log('Ps');\n            bttTriggerDeviceTrigger(targetDevice, 'PsButton');\n        }else if(reportBuffer.readUInt8(5) === 0x28) {\n            log('X');\n            bttTriggerDeviceTrigger(targetDevice, 'Cross');\n        }else if(reportBuffer.readUInt8(6) === 0x20) {\n            log('Start');\n            bttTriggerDeviceTrigger(targetDevice, 'Start');\n        }\n}\n\n// Advanced, optional. Use if you want to trigger commands that send data to\n// the device, from a BTT predefined action.\n// See https://docs.folivora.ai/1500_generic_devices.html\nasync function executeBTTCommand(targetDevice, commandName, commandInput) {\n    log(\"execute command: \" + commandName)\n    switch(commandName) {\n        case \"exampleCommand\": {\n            // send any hex string to the device\n            let deviceResponse = await bttSendDataToDevice({\n              BTTActionSendDataTargetDevice: targetDevice,\n              BTTActionSendDataData: 'FEEDC0DE',\n              BTTActionSendDataReportType: 1,\n              BTTActionSendDataResponseType: -1,\n              BTTActionSendDataResponsePrefix: ''\n            }); \n            break;\n        }\n    }\n    return 'done executing ' + commandName\n}";
    BTTGenericDeviceWatchedBytes =     {
        1 =         (
            7,
            6,
            5
        );
    };
}|
1675168439.953512|NAMED|Close That App|
1675168440.167057|ASL|delay planned: 0.200000 real 0.204275|
1675168440.168142|NAMED|Close That Window|
1675168440.186253|ASL|result {
    BTTGenericDeviceActiveReports =     {
        1 = 1;
    };
    BTTGenericDeviceScript = "// Enter your input analyzer script here. \n// Do not change the function signatures\nfunction analyzeDeviceInput(targetDevice, reportID, reportDataHex) {\n      \n\tlet reportBuffer = buffer.Buffer.from(reportDataHex, 'hex');\n        // the values you see above are in hex format. To read such a byte\n        // use readUInt8(index).\n        if(reportBuffer.readUInt8(7) === 0x01) {\n            log('Ps');\n            bttTriggerDeviceTrigger(targetDevice, 'PsButton');\n        }else if(reportBuffer.readUInt8(5) === 0x28) {\n            log('X');\n            bttTriggerDeviceTrigger(targetDevice, 'Cross');\n        }else if(reportBuffer.readUInt8(6) === 0x20) {\n            log('Start');\n            bttTriggerDeviceTrigger(targetDevice, 'Start');\n        }\n}\n\n// Advanced, optional. Use if you want to trigger commands that send data to\n// the device, from a BTT predefined action.\n// See https://docs.folivora.ai/1500_generic_devices.html\nasync function executeBTTCommand(targetDevice, commandName, commandInput) {\n    log(\"execute command: \" + commandName)\n    switch(commandName) {\n        case \"exampleCommand\": {\n            // send any hex string to the device\n            let deviceResponse = await bttSendDataToDevice({\n              BTTActionSendDataTargetDevice: targetDevice,\n              BTTActionSendDataData: 'FEEDC0DE',\n              BTTActionSendDataReportType: 1,\n              BTTActionSendDataResponseType: -1,\n              BTTActionSendDataResponsePrefix: ''\n            }); \n            break;\n        }\n    }\n    return 'done executing ' + commandName\n}";
    BTTGenericDeviceWatchedBytes =     {
        1 =         (
            7,
            6,
            5
        );
    };
}|
1675168440.186471|ASL|result {
    BTTGenericDeviceActiveReports =     {
        1 = 1;
    };
    BTTGenericDeviceScript = "// Enter your input analyzer script here. \n// Do not change the function signatures\nfunction analyzeDeviceInput(targetDevice, reportID, reportDataHex) {\n      \n\tlet reportBuffer = buffer.Buffer.from(reportDataHex, 'hex');\n        // the values you see above are in hex format. To read such a byte\n        // use readUInt8(index).\n        if(reportBuffer.readUInt8(7) === 0x01) {\n            log('Ps');\n            bttTriggerDeviceTrigger(targetDevice, 'PsButton');\n        }else if(reportBuffer.readUInt8(5) === 0x28) {\n            log('X');\n            bttTriggerDeviceTrigger(targetDevice, 'Cross');\n        }else if(reportBuffer.readUInt8(6) === 0x20) {\n            log('Start');\n            bttTriggerDeviceTrigger(targetDevice, 'Start');\n        }\n}\n\n// Advanced, optional. Use if you want to trigger commands that send data to\n// the device, from a BTT predefined action.\n// See https://docs.folivora.ai/1500_generic_devices.html\nasync function executeBTTCommand(targetDevice, commandName, commandInput) {\n    log(\"execute command: \" + commandName)\n    switch(commandName) {\n        case \"exampleCommand\": {\n            // send any hex string to the device\n            let deviceResponse = await bttSendDataToDevice({\n              BTTActionSendDataTargetDevice: targetDevice,\n              BTTActionSendDataData: 'FEEDC0DE',\n              BTTActionSendDataReportType: 1,\n              BTTActionSendDataResponseType: -1,\n              BTTActionSendDataResponsePrefix: ''\n            }); \n            break;\n        }\n    }\n    return 'done executing ' + commandName\n}";
    BTTGenericDeviceWatchedBytes =     {
        1 =         (
            7,
            6,
            5
        );
    };
}|
1675168441.836276|NAMED|Close That App|
1675168442.054860|ASL|delay planned: 0.200000 real 0.209458|
1675168442.056121|NAMED|Close That Window|
1675168442.071095|ASL|dealloc bridge|
1675168448.629125|lic|newest date 2021-10-30 12:33:05 +0000|
1675168448.629140|lic|lict 115328943-chre5345849c659-3410887d8e|
1675168454.745948|TERMINATE|SHOULDTERMINATE|

Ah sorry I meant what is listed here under "History of Monitored Changes"

1 Like

Also here is a screenshot. The history shows 4 events. The Log only three.
The 4 events are obviously

  1. Press Ps
  2. Press Cross
  3. Release Cross
  4. Release Ps

In that case to trigger when both are pressed at the same time you can do this:

function analyzeDeviceInput(targetDevice, reportID, reportDataHex) {
      
	let reportBuffer = buffer.Buffer.from(reportDataHex, 'hex');
        // the values you see above are in hex format. To read such a byte
        // use readUInt8(index).
        if(reportBuffer.readUInt8(5) === 0x28 && reportBuffer.readUInt8(7) === 0x01 ) {
            log('trigger!');
            bttTriggerDeviceTrigger(targetDevice, 'psAndCrossAtTheSameTime');
        }
}

It should be the first condition in your if

1 Like

That worked!
Thank you :fire:

Can I ask for one more thing?!
As soon as I open an app which utilizes the Gamepad, it stops working.
If I check 'Try to get exclusive access to device' it keeps working.
But then I can't control the games. They don't get any input.

I guess I have to set up every button in BTT and loop them trough.
Like 'Press X' lets BTT send the original command for this button.
How do i do that? What do I have to choose as an Action?

I don't think that's possible. However I could make it possible to activate the Generic Device only for specific apps (or disable for specific ones). That's currently not possible but should be easy to add for the next version

Good to know. Thanks, I will play around with the amazing features you gave us so far!
Would be great though, if this could be a Feature in the future. This is a must have for every gamer :smile:

In v4.004 you can now create a conditional activation group and add the generic device analyzer to that.

For the activation group you can then specify where it should work/not work

Nice! Thanks for posting the update!!
This means I can say that in App X,Y,Z the gamepad works as regular without triggering BTT, right?

Just to be sure, you understood why I asked this:

I guess I have to set up every button in BTT and loop them trough.
Like 'Press X' lets BTT send the original command for this button.
How do i do that? What do I have to choose as an Action?

I want to control the games with the gamepad, but make hotkeys with BTT.
F.e. I play some old games with the Dolphin Emulator. I control the game as is, but as soon as I hit a combination of two specific button, I want BTT to make an action. Could be quit the App with CMD+Q or anything else, what is not game-related.

This would be great for other apps like Steam or Battle.net. Cause we could extend the functionality of the gamepad a lot. Without waiting for the companies to implement something like that by their own :smile:
or switching to a keyboard/mouse

I see! That probably will not work for games that take full control of the controllers. As far as I know there is no way to get events from a device that has been captured by another app.

Oh ok, that‘s a bummer :sweat_smile:

As a workaround i was trying to map keyboard keys to the gamepad and use it that way. It works as long as i am not in an app, that tries to use the gamepad.

In the settings of that app(s) i did switch to keyboard controls, but nothing gets through with the gamepad.

Only in apps for playing games. In every other app, f.e. TextEdit, it works. Any idea what could be the reason?

If you're using steam, you can use their Game Controller mapper to dedicate some keys to send basic keyboard shortcuts (that BTT picks up) while still using the defaults for the other buttons.

That's what I'm using for now, because they have more options for how to customize the joystick inputs. But BTT is really powerful because I can use it to press one button and get mouse drags or timed combos.

1 Like

Thanks @buckbuck for that tipp!
For the use with Steam this works great

If you leave steam running in the background, it still gives an outside-of-steam "Desktop Configuration". This can work even if you're running an app outside of Steam. It's a special profile that's not connected to a specific game. It's in the main Settings; Controller; Desktop Configuration.

I use it to map the joystick controls, assign all the buttons to higher function keys so I can customize them in BTT for different app profiles... and then I use it for desktop use and games outside of steam. I turn off the controller in the other apps.

The only drawback is that Steam has to be open in the background. I'll be happy if I can sort out joystick logic natively to BTT, but hybrid is fine for me for now.