Can I use node-red to check the health of my mouse? (Buttons)

I have an OLD mouse. But I kinda love it.

Is there a flow I can make to test the LMB, MMB and RMB working correctly?

Either dashboard is ok.
(Just saying)

dashboard 2

chrome_Lorul1JryK

[{"id":"9c41384520424f71","type":"ui-template","z":"cbf56bf54bdb6748","group":"d4eb8ae820e57069","page":"","ui":"","name":"mouse test","order":1,"width":0,"height":0,"head":"","format":"<template>\n  <v-card class=\"pa-4\" elevation=\"2\" max-width=\"400\">\n    <v-row class=\"mb-4\" justify=\"center\" align=\"center\">\n      <v-btn :color=\"leftClick ? 'primary' : 'grey lighten-1'\" class=\"mx-2\" elevation=\"leftClick ? 12 : 2\" rounded>\n        Left Click\n      </v-btn>\n      <v-btn :color=\"middleClick ? 'primary' : 'grey lighten-1'\" class=\"mx-2\" elevation=\"middleClick ? 12 : 2\" rounded>\n        Middle Click\n      </v-btn>\n      <v-btn :color=\"rightClick ? 'primary' : 'grey lighten-1'\" class=\"mx-2\" elevation=\"rightClick ? 12 : 2\" rounded>\n        Right Click\n      </v-btn>\n    </v-row>\n    <v-row class=\"mb-4\" justify=\"center\" align=\"center\">\n      <v-icon large>\n        mdi-mouse-variant\n      </v-icon>\n      <v-chip class=\"mx-3\" color=\"info\" text-color=\"white\" label>\n        Scroll: {{ scrollDirection }}\n      </v-chip>\n    </v-row>\n    <v-row justify=\"center\" align=\"center\" class=\"mb-2\">\n      <v-chip color=\"primary\" color=\"white\" label>\n        Position: {{ posX }}, {{ posY }}\n      </v-chip>\n    </v-row>\n    <v-row justify=\"center\" align=\"center\" class=\"mb-2\">\n      <v-chip color=\"primary\" color=\"white\" label>\n        Speed: {{ speed.toFixed(2) }} px/s\n      </v-chip>\n    </v-row>\n    <v-row justify=\"center\" align=\"center\" class=\"mb-2\">\n      <v-chip color=\"primary\" color=\"white\" label>\n        Direction: {{ direction }}\n      </v-chip>\n    </v-row>\n  </v-card>\n</template>\n\n<script>\nexport default {\n  data() {\n    return {\n      leftClick: false,\n      middleClick: false,\n      rightClick: false,\n      scrollDirection: 'None',\n      posX: 0,\n      posY: 0,\n      lastX: null,\n      lastY: null,\n      lastTime: null,\n      speed: 0,\n      direction: 'None'\n    };\n  },\n  mounted() {\n    window.addEventListener('mousedown', this.onMouseDown);\n    window.addEventListener('mouseup', this.onMouseUp);\n    window.addEventListener('wheel', this.onWheel);\n    window.addEventListener('mousemove', this.onMouseMove);\n  },\n  unmounted() {\n    window.removeEventListener('mousedown', this.onMouseDown);\n    window.removeEventListener('mouseup', this.onMouseUp);\n    window.removeEventListener('wheel', this.onWheel);\n    window.removeEventListener('mousemove', this.onMouseMove);\n  },\n  methods: {\n    onMouseDown(e) {\n      if (e.button === 0) this.leftClick = true;\n      else if (e.button === 1) this.middleClick = true;\n      else if (e.button === 2) this.rightClick = true;\n    },\n    onMouseUp(e) {\n      if (e.button === 0) this.leftClick = false;\n      else if (e.button === 1) this.middleClick = false;\n      else if (e.button === 2) this.rightClick = false;\n    },\n    onWheel(e) {\n      if (e.deltaY < 0) this.scrollDirection = 'Up';\n      else if (e.deltaY > 0) this.scrollDirection = 'Down';\n      else this.scrollDirection = 'None';\n      // Reset scroll direction after 1 second\n      clearTimeout(this.scrollTimeout);\n      this.scrollTimeout = setTimeout(() => {\n        this.scrollDirection = 'None';\n      }, 1000);\n    },\n    onMouseMove(e) {\n      this.posX = e.clientX;\n      this.posY = e.clientY;\n      const now = performance.now();\n      if (this.lastX !== null && this.lastY !== null && this.lastTime !== null) {\n        const dx = this.posX - this.lastX;\n        const dy = this.posY - this.lastY;\n        const dt = (now - this.lastTime) / 1000; // seconds\n        const dist = Math.sqrt(dx * dx + dy * dy);\n        this.speed = dist / dt;\n        if (Math.abs(dx) > Math.abs(dy)) {\n          this.direction = dx > 0 ? 'Right' : 'Left';\n        } else if (Math.abs(dy) > 0) {\n          this.direction = dy > 0 ? 'Down' : 'Up';\n        } else {\n          this.direction = 'None';\n        }\n      }\n      this.lastX = this.posX;\n      this.lastY = this.posY;\n      this.lastTime = now;\n    }\n  }\n};\n</script>\n\n<style scoped>\n.v-btn {\n  min-width: 100px;\n  transition: box-shadow 0.2s ease, background-color 0.2s ease;\n}\n</style>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":1100,"y":200,"wires":[[]]},{"id":"d4eb8ae820e57069","type":"ui-group","name":"mouse test","page":"6adfff83e693cf57","width":6,"height":1,"order":1,"showTitle":true,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"6adfff83e693cf57","type":"ui-page","name":"mouse-test","ui":"46de808d763294c2","path":"/mouse-test","icon":"home","layout":"grid","theme":"636f3025f138f2ee","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":1,"className":"","visible":"true","disabled":"false"},{"id":"46de808d763294c2","type":"ui-base","name":"My Dashboard","path":"/dashboard","appIcon":"","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"headerContent":"page","navigationStyle":"default","titleBarStyle":"default","showReconnectNotification":true,"notificationDisplayTime":1,"showDisconnectNotification":true,"allowInstall":true},{"id":"636f3025f138f2ee","type":"ui-theme","name":"Default Theme","colors":{"surface":"#062a74","primary":"#062a74","bgPage":"#e9e8e9","groupBg":"#ffffff","groupOutline":"#b18cfe"},"sizes":{"density":"default","pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}},{"id":"03c8ea6a5a52949a","type":"global-config","env":[],"modules":{"@flowfuse/node-red-dashboard":"1.24.2"}}]

NOTE: there may be some oddities that I will let you resolve (I didnt fully check the calcs / x/y directions etc)

4 Likes

That is cool