Automated "motorized" fader slider

This flow allows to automate the fading of a vertical slider. You can specify the target value via the payload and the time to get it there via the topic.

This is an improvement over the "Slick vertical slider" available here: https://flows.nodered.org/flow/4b2ebe373bcac34e6b18be998bb47f93

\n\n","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":614.5,"y":211,"wires":[["d1a17c2f.b549b","cca5c785.de9bb8"]]},{"id":"36f4e79f.503238","type":"inject","z":"37969d68.c02a22","name":"","topic":"1","payload":"255","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":281,"y":117,"wires":[["1b8b9c39.cd5d94"]]},{"id":"2653f503.1b0d3a","type":"inject","z":"37969d68.c02a22","name":"","topic":"2","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":285,"y":158,"wires":[["1b8b9c39.cd5d94"]]},{"id":"a3cb9449.c1d878","type":"inject","z":"37969d68.c02a22","name":"","topic":"3","payload":"200","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":285,"y":199,"wires":[["1b8b9c39.cd5d94"]]},{"id":"40182633.c90508","type":"inject","z":"37969d68.c02a22","name":"","topic":"4","payload":"127","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":285,"y":235,"wires":[["1b8b9c39.cd5d94"]]},{"id":"ce43c985.bed7b8","type":"inject","z":"37969d68.c02a22","name":"","topic":"0","payload":"40","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":287,"y":359,"wires":[["1b8b9c39.cd5d94"]]},{"id":"1dad0ba3.d96794","type":"inject","z":"37969d68.c02a22","name":"","topic":"10","payload":"255","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":284,"y":276,"wires":[["1b8b9c39.cd5d94"]]},{"id":"b6e16766.9fd428","type":"comment","z":"37969d68.c02a22","name":"payload is slider target value, topic is fading time in seconds","info":"","x":427,"y":73,"wires":[]},{"id":"c6b3f12a.1b00a","type":"comment","z":"37969d68.c02a22","name":"no topic or topic of \"0\" trigers instant change of slider","info":"","x":397,"y":320,"wires":[]},{"id":"eeef8bce.a93cf8","type":"inject","z":"37969d68.c02a22","name":"","topic":"","payload":"230","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":282,"y":399,"wires":[["1b8b9c39.cd5d94"]]}] /** * Parse the flow.json to get the details on the tabs/subflows present */ const processFlow = function (flow) { const tabids = [] const tabs = [] flow.forEach((d) => { if (d.type === 'subflow') { tabids.push(d.id) tabs.push({ id: d.id, label: d.name, type: 'subslow' }) } else if (d.z) { if (tabids.indexOf(d.z) === -1) { tabids.push(d.z) tabs.push({ id: d.z, label: d.z, type: 'tab', }) } } }) return tabs } function addPanZoom () { var svgs = d3.selectAll('.flowviewer svg'); svgs.each(function() { var svg = d3.select(this); svg.html('' + svg.html() + ''); var inner = svg.select('g'); var zoom = d3.zoom() .translateExtent([[0, 0], [3000, 3000]]) .scaleExtent([0.5, 1]) .on("start", function () { svg.classed("dragging", true); }) .on('zoom', function(event) { inner.attr('transform', event.transform); }) .on("end", function () { svg.classed("dragging", false); }); svg.call(zoom); }); } const clearFlow = function () { $('.flowviewer svg .flowGridlines').empty() $('.flowviewer svg .containerGroup').empty() $('.flowviewer svg .flowGroups').empty() $('.flowviewer svg .flowWires').empty() $('.flowviewer svg .flowNodes').empty() } // get the tabs/subflows for our provided flow const tabs = processFlow(flow) // sort them such that tabs render first tabs.sort((a, b) => { return a.type > b.type ? -1 : (a.type < b.type) ? 1 : 0 }) function openTab (id) { // clear any existing flow clearFlow() // draw the new flow - uses function from `public/js/flowviewer.js` renderFlow(id, flow, $('.flowviewer svg')); addPanZoom() } function addTab (tab, index) { const classes = 'flowviewer-tab flowviewer-' + tab.type const name = tab.type === 'tab' ? 'Flow ' + (index + 1) : tab.label const tabDOM = $('.flowviewer-tabs') .append(`
${name}
`) .on('click', `#flowviewer-tab-${index}`, function () { // add on click to each new tab $('.flowviewer-tab').removeClass('active') $(this).addClass('active') openTab(tab.id) }) } tabs.forEach((tab, index) => { addTab(tab, index) }) clearFlow(); renderFlow(tabs[0].id, flow, $('.flowviewer svg')); addPanZoom(); $('#flowviewer-tab-0').addClass('active') $('#copy-flow').on('click', function() { navigator.clipboard.writeText(JSON.stringify(flow)); }) })()
[{"id":"1b8b9c39.cd5d94","type":"function","z":"37969d68.c02a22","name":"autofade","func":"let fadestep = context.get(\"fadestep\")\nlet level = context.get(\"level\") || 0\nlet step = 1\nlet target = msg.payload || 0\nlet timing = msg.topic*1000/(Math.abs(target - level)) || 0\n\nfunction fade(step,target) {\n    if (level != target){\n        level = level + step\n        context.set(\"level\",level)\n        //node.warn(\"target: \" + target + \" level: \" + level)\n    }\n    msg.payload = level\n    node.send(msg)\n    \n    if (level === target){\n        clearTimeout(fadestep);\n        return;\n    }\n}\n\nif (msg.hasOwnProperty(\"feedback\")){ // if message comes from front-end\n    context.set(\"level\",msg.feedback)\n    if (msg.hasOwnProperty(\"socketid\")){ // if message is a manual input from dashboard\n        clearTimeout(fadestep); //stop fading\n    }\n}else{\n    clearTimeout(fadestep);\n    target = msg.payload\n    if (level < target){\n        step = 1\n    }else{\n        step = -1\n    }\n    if (!msg.topic || msg.topic === \"0\"){\n        level = msg.payload\n        context.set(\"level\",level)\n        return msg;\n    }else{\n        fadestep = setInterval(function(){ fade(step,target)}, timing);\n        context.set(\"fadestep\",fadestep)\n    }\n    \n}\n\n","outputs":1,"noerr":0,"x":487,"y":211,"wires":[["49736d54.086f64"]]},{"id":"d1a17c2f.b549b","type":"change","z":"37969d68.c02a22","name":"feedback","rules":[{"t":"set","p":"feedback","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":542,"y":262,"wires":[["1b8b9c39.cd5d94"]]},{"id":"cca5c785.de9bb8","type":"debug","z":"37969d68.c02a22","name":"","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","x":781,"y":214,"wires":[]},{"id":"49736d54.086f64","type":"ui_template","z":"37969d68.c02a22","group":"","name":"fader","order":4,"width":"2","height":"6","format":"<div style=\"text-align: center;font-weight: bold;\">Light Master</div>\n<input class=\"sliderV size2x6\" type=\"range\" min=0 max=255 step=1 ng-model=\"msg.payload\" aria-label=\"volume\" ng-change=\"output(msg)\">\n\n<script>\n(function($scope) {\n    $scope.output = function(key) {\n        if ($scope.hasOwnProperty(\"msg\")){\n            if ($scope.msg.hasOwnProperty(\"socketid\") || $scope.msg.payload !== 128){ //this prevents output at 50% from initialization on ng-change\n\t\t        $scope.send({payload:$scope.msg.payload, socketid:$scope.msg.socketid});\n            }\n        }\n        \n    };\n})(scope);\n</script>\n\n<style>\ninput[type='range'].sliderH {\n  margin-top: 60px;\n  width: 80px;\n  height: 240px;\n  padding: 0;\n  overflow: unset;\n  cursor: grab;\n}\ninput[type='range'].sliderV {\n  transform: rotateZ(-90deg);\n  margin-top: 60px;\n  writing-mode: bt-lr;\n  width: 80%;\n  padding: 0;\n  overflow: unset;\n  cursor: grab;\n  height: 8px;\n  margin-left: -100px;\n}\n.size1x6 {\n    height: 8px !important;\n    margin-left: -100px !important;\n}\n.size2x6 {\n    height: 13px !important;\n    margin-left: -80px !important;\n}\n.size1x6::-webkit-slider-thumb {\n    height: 23px !important;\n    width: 42px !important;\n}\n.size2x6::-webkit-slider-thumb{\n    height: 43px !important;\n    width: 72px !important;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n  input[type='range'].sliderH {\n    -webkit-appearance: none;\n    width: 240px;\n    height: 10px;\n    margin-top: 30px;\n    margin-left: 30px;\n    outline: 0;\n    border-radius: 5px;\n    background-color: #0b0b0b;\n    box-shadow: inset 1px 1px 0 1px #6d6d6d;\n  }\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n  input[type='range'].sliderV {\n    -webkit-appearance: none;\n    -webkit-transform: rotate(270deg);\n    width: 240px;\n    height: 10px;\n    margin-top: 140px;\n    outline: 0;\n    border-radius: 5px;\n    background-color: #0b0b0b;\n    box-shadow: inset 1px 1px 0 1px #6d6d6d;\n  }\n}\ninput[type='range']::-ms-track {\n  width: 10px;\n  height: 240px;\n  border-radius: 5px;\n  background-color: #0b0b0b;\n  box-shadow: inset 1px 1px 0 1px #6d6d6d;\n  border: 0;\n}\ninput[type='range']::-moz-range-track {\n    transform: rotateZ(-90deg);\n  width: 10px;\n  height: 240px;\n  border-radius: 5px;\n  background-color: #0b0b0b;\n  box-shadow: inset 1px 1px 0 1px #6d6d6d;\n  border: 0;\n}\ninput[type='range']::-webkit-slider-thumb {\n  width: 72px;\n  height: 32px;\n  -webkit-appearance: none;\n  background-image: -webkit-linear-gradient(left, #0f0f0f, #2e2e2e 4%, #0f0f0f 8%, #000 47%, #808080 48%, #808080 52%, #000 53%, #1a1a1a 96%, #2e2e2e);\n  box-shadow: 5px -1px 10px 0 #1a1a1a;\n}\ninput[type='range']::-ms-thumb {\n  width: 32px;\n  height: 72px;\n  border: 0;\n  box-shadow: 5px -1px 10px 0 #1a1a1a;\n  background-image: -ms-linear-gradient(bottom, #0f0f0f, #2e2e2e 4%, #0f0f0f 8%, #000 47%, #808080 48%, #808080 52%, #000 53%, #1a1a1a 96%, #2e2e2e);\n}\ninput[type='range']::-ms-tooltip {\n  display: none;\n}\ninput[type='range']::-moz-range-thumb {\n  width: 32px;\n  height: 72px;\n  border: 0;\n  box-shadow: 5px -1px 10px 0 #1a1a1a;\n  background-image: -moz-linear-gradient(bottom, #0f0f0f, #2e2e2e 4%, #0f0f0f 8%, #000 47%, #808080 48%, #808080 52%, #000 53%, #1a1a1a 96%, #2e2e2e);\n  border-radius: 0;\n  transform: rotateZ(-90deg);\n}\n</style>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":614.5,"y":211,"wires":[["d1a17c2f.b549b","cca5c785.de9bb8"]]},{"id":"36f4e79f.503238","type":"inject","z":"37969d68.c02a22","name":"","topic":"1","payload":"255","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":281,"y":117,"wires":[["1b8b9c39.cd5d94"]]},{"id":"2653f503.1b0d3a","type":"inject","z":"37969d68.c02a22","name":"","topic":"2","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":285,"y":158,"wires":[["1b8b9c39.cd5d94"]]},{"id":"a3cb9449.c1d878","type":"inject","z":"37969d68.c02a22","name":"","topic":"3","payload":"200","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":285,"y":199,"wires":[["1b8b9c39.cd5d94"]]},{"id":"40182633.c90508","type":"inject","z":"37969d68.c02a22","name":"","topic":"4","payload":"127","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":285,"y":235,"wires":[["1b8b9c39.cd5d94"]]},{"id":"ce43c985.bed7b8","type":"inject","z":"37969d68.c02a22","name":"","topic":"0","payload":"40","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":287,"y":359,"wires":[["1b8b9c39.cd5d94"]]},{"id":"1dad0ba3.d96794","type":"inject","z":"37969d68.c02a22","name":"","topic":"10","payload":"255","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":284,"y":276,"wires":[["1b8b9c39.cd5d94"]]},{"id":"b6e16766.9fd428","type":"comment","z":"37969d68.c02a22","name":"payload is slider target value, topic is fading time in seconds","info":"","x":427,"y":73,"wires":[]},{"id":"c6b3f12a.1b00a","type":"comment","z":"37969d68.c02a22","name":"no topic or topic of \"0\" trigers instant change of slider","info":"","x":397,"y":320,"wires":[]},{"id":"eeef8bce.a93cf8","type":"inject","z":"37969d68.c02a22","name":"","topic":"","payload":"230","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":282,"y":399,"wires":[["1b8b9c39.cd5d94"]]}]

Flow Info

Created 4 years, 3 months ago
Rating: 5 3

Owner

Actions

Rate:

Node Types

Core
  • change (x1)
  • comment (x2)
  • debug (x1)
  • function (x1)
  • inject (x7)
Other
  • ui_template (x1)

Tags

  • vertical
  • slider
  • fader
  • volume
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option