Nintendo Switch Joycon as "Generic Device"

I just set up a Nintendo Switch right Joy-Con as a "generic device". Three points I'd like to make:

  • @Andreas_Hegenberg, to set up a generic device it must be a trigger (called e.g. "Joy-Con (R)"), which is confusing because it sits alongside the "triggers" that the device triggers (e.g. "Joy-Con (R): X"). This device pattern needs some UI that reflects how it works. Device setup should be separate from triggers. I'm sure you know this and its in the roadmap.
  • I also encountered a bug - if actions are attached to the device configuration "trigger" and then the actions are deleted, they still occur. Until this is fixed: set up the device as a trigger, and then set up trigger/action pairs separately.
  • I'd like to share the script I used to map my JoyCon events to BTT events. @Andreas_Hegenberg, the bufferMaps abstraction I set up captures the entire complexity of what these Javascript functions should do. Rather than asking users to write Javascript, maybe you can just let them configure "bufferMaps" by mapping registers-value pairs to event names. It took me some time to see that this was what the Javascript function should do, but UI to reflect this concept shouldn't be too complicated.

Here is the Javascript function that captures all events from a right Joy-Con.

function analyzeDeviceInput(targetDevice, reportID, reportDataHex) {
  let reportBuffer = buffer.Buffer.from(reportDataHex, "hex");
  let event;

  let bufferMaps = [
      buffer: 1,
      events: {
        0x01: "A",
        0x02: "X",
        0x04: "B",
        0x08: "Y",
        0x20: "SR",
        0x10: "SL",
      buffer: 3,
      events: {
        0x00: "jW",
        0x01: "jNW",
        0x02: "jN",
        0x03: "jNE",
        0x04: "jE",
        0x05: "jSE",
        0x06: "jS",
        0x07: "jSW",
      buffer: 2,
      events: {
        0x40: "R",
        0x80: "ZR",
        0x02: "Plus",
        0x08: "jDown",
        0x10: "Home",

  for (let bufferMap of bufferMaps) {
    event =[reportBuffer.readUInt8(bufferMap.buffer)];
    if (event) {
      //   log(event)
      bttTriggerDeviceTrigger(targetDevice, event);

  // If you want to get the next report even though,
  // the data has not changed, call this function:
  // bttGetNextEvenWithoutChange(targetDevice, reportID)

It returns the following "events" that become triggers:

  • A -> "Joy-Con (R): A" # A button
  • B -> "Joy-Con (R): B" # B button
  • X -> "Joy-Con (R): X" # X button
  • Y -> "Joy-Con (R): Y" # Y button
  • SR -> "Joy-Con (R): SR" # SR button
  • SL -> "Joy-Con (R): SL" # SL button
  • R -> "Joy-Con (R): R" # R button
  • ZR -> "Joy-Con (R): ZR" # ZR button
  • Plus -> "Joy-Con (R): Plus" # Plus button
  • Home -> "Joy-Con (R): Home" # Home button
  • jDown -> "Joy-Con (R): jDown" # joystick down button
  • jW -> "Joy-Con (R): jW" # W joystick direction
  • jNW -> "Joy-Con (R): jNW" # NW joystick direction
  • jN -> "Joy-Con (R): jN" # N joystick direction
  • jNE -> "Joy-Con (R): jNE" # NE joystick direction
  • jE -> "Joy-Con (R): jE" # E joystick direction
  • jSE -> "Joy-Con (R): jSE" # SE joystick direction
  • jS -> "Joy-Con (R): jS" # S joystick direction
  • jSW -> "Joy-Con (R): jSW" # SW joystick direction

@Andreas_Hegenberg if you nail the UI for configuring devices (not as triggers, which, again, does not reflect what these are), folks could share these "bufferMaps" as "BTT generic device drivers", and as json they'd be very portable, and safely shareable. So safely portable that you could have a community device lookup built into BTT...

I'm not sure I understand. There are two things for the generic devices:
• The device "Input Analyzer" that has your script and defines the triggers it can execute

• The triggers itself that are called by the Input Analyzer via the bttTriggerDeviceTrigger function
If you want you could put them into separate folders:

2.) Could you maybe share your preset or some screenshots of the setup? I think I don't fully get it right now :slight_smile: In general actions assigned to the "Input Analyzer" are triggered when the device is loaded/connects.

3.) Maybe I don't understand, but such bufferMaps are just one of many possibly ways how a device works. In many cases they are more dynamic or interconnected.

@Andreas_Hegenberg thank you for these responses!

What I experienced was the following bug. If you create an "input analyzer" trigger, then you can create other triggers that respond to the configured device states. Instead of creating a new trigger, I stupidly replaced the input analyzer trigger ("Joy-Con (R)") with one of these device state triggers ("Joy-Con (R): X"), at which point there was no actual input analyzer action. It was confusing because, at least for some time, the triggers I had configured continued to exist in the trigger option menu ("Joy-Con (R): X" and "Joy-Con (R): Y", etc.) and still worked in BTT (even though I had overwritten the input analyzer trigger).

I misunderstood the way that the input analyzer trigger and the device action triggers both need to exist alongside each other.

I think I was correct that setting this up is confusing, but I was also still confused when I reported this issue. Thanks for bearing with me and responding so thoughtfully!

3.) Maybe I don't understand, but such bufferMaps are just one of many possibly ways how a device works. In many cases they are more dynamic or interconnected.

@Andreas_Hegenberg I understand this but I hope that over time BTT is able to abstract out some device patterns to make this (very cool) "generic device" feature usable and still generic. I don't know how representative the Nintendo Switch Joy-Con is among all devices, but at least in this case I can imagine a productive, if simplified, device interface that doesn't require users writing Javascript.