首页 > 解决方案 > 红色节点:覆盖的全局变量

问题描述

我有控制 WS2812b 条的流程。我正在使用开关,它将布尔变量发送到以下函数,我在其中获取全局变量,我将当前颜色存储在 HSL 中。关闭(假)脚本后,加载当前颜色并将“L”更改为 0(工作),但是当我再次打开它(真)时,即使我没有在任何地方更改它,它也会再次变为 L=0。

if(msg.payload === false)
{
    col = global.get("color");
    col.l = 0;
}

if(msg.payload === true)
{
    col = global.get("color");
}
msg.payload = col;
return msg;

流动:

[{"id":"79df9203.a409ec","type":"tab","label":"Obyvací pokoj","disabled":false,"info":""},{"id":"431fac94.09cba4","type":"mqtt out","z":"79df9203.a409ec","name":"","topic":"/TV_LED/cmd","qos":"","retain":"","broker":"e17662db.a0a03","x":1100,"y":140,"wires":[]},{"id":"a31190b1.8af6c","type":"function","z":"79df9203.a409ec","name":"hsl > neopixel","func":"var hslToRgb = function(hue, saturation, lightness){\n  // based on algorithm from http://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB\n  if( hue == undefined ){\n    return [0, 0, 0];\n  }\n\n  var chroma = (1 - Math.abs((2 * lightness) - 1)) * saturation;\n  var huePrime = hue / 60;\n  var secondComponent = chroma * (1 - Math.abs((huePrime % 2) - 1));\n\n  huePrime = Math.floor(huePrime);\n  var red;\n  var green;\n  var blue;\n\n  if( huePrime === 0 ){\n    red = chroma;\n    green = secondComponent;\n    blue = 0;\n  }else if( huePrime === 1 ){\n    red = secondComponent;\n    green = chroma;\n    blue = 0;\n  }else if( huePrime === 2 ){\n    red = 0;\n    green = chroma;\n    blue = secondComponent;\n  }else if( huePrime === 3 ){\n    red = 0;\n    green = secondComponent;\n    blue = chroma;\n  }else if( huePrime === 4 ){\n    red = secondComponent;\n    green = 0;\n    blue = chroma;    \n  }else if( huePrime === 5 ){\n    red = chroma;\n    green = 0;\n    blue = secondComponent;\n  }\n\n  var lightnessAdjustment = lightness - (chroma / 2);\n  red += lightnessAdjustment;\n  green += lightnessAdjustment;\n  blue += lightnessAdjustment;\n  \n    return {\n        r: Math.round(red * 255),\n        g: Math.round(green * 255),\n        b: Math.round(blue * 255)\n    };\n}\nnode.warn(msg.payload);\nmsg.payload = hslToRgb(msg.payload.h,msg.payload.s,msg.payload.l);\nmsg.payload = \"Neopixelall,\"+msg.payload.r+\",\"+msg.payload.g+\",\"+msg.payload.b;\nreturn msg;\n\n","outputs":1,"noerr":0,"x":920,"y":140,"wires":[["431fac94.09cba4"]]},{"id":"5e030bab.a9e354","type":"mqtt in","z":"79df9203.a409ec","name":"","topic":"/TV_LED/color","qos":"2","broker":"e17662db.a0a03","x":300,"y":340,"wires":[["d5993f0b.74a52"]]},{"id":"d5993f0b.74a52","type":"ui_text","z":"79df9203.a409ec","group":"aec2f80b.a31aa8","order":5,"width":0,"height":0,"name":"","label":"Stored color:","format":"{{msg.payload}}","layout":"row-spread","x":490,"y":340,"wires":[]},{"id":"30c421ea.7900fe","type":"mqtt in","z":"79df9203.a409ec","name":"","topic":"/TV_LED/color","qos":"2","broker":"e17662db.a0a03","x":160,"y":140,"wires":[["90df2140.97555"]]},{"id":"4ac39175.f01b8","type":"mqtt out","z":"79df9203.a409ec","name":"","topic":"/TV_LED/color","qos":"","retain":"true","broker":"e17662db.a0a03","x":1100,"y":100,"wires":[]},{"id":"c2735b8.0f402a8","type":"link out","z":"79df9203.a409ec","name":"LED_TV","links":["5db90cc7.188e14"],"x":735,"y":120,"wires":[]},{"id":"5db90cc7.188e14","type":"link in","z":"79df9203.a409ec","name":"","links":["c2735b8.0f402a8"],"x":775,"y":120,"wires":[["a31190b1.8af6c","e53fc48c.f09088"]]},{"id":"90df2140.97555","type":"function","z":"79df9203.a409ec","name":"string>light","func":"msg.payload= JSON.parse(msg.payload);\nglobal.set(\"color\",msg.payload);\n\nmsg.payload = msg.payload.l;\nreturn msg;\n","outputs":1,"noerr":0,"x":330,"y":140,"wires":[["5dec6394.05474c"]]},{"id":"5dec6394.05474c","type":"ui_slider","z":"79df9203.a409ec","name":"","label":"Lightness","tooltip":"","group":"aec2f80b.a31aa8","order":5,"width":0,"height":0,"passthru":false,"outs":"end","topic":"","min":0,"max":"1","step":"0.1","x":480,"y":140,"wires":[["47416ab5.d30f44"]]},{"id":"f0d4dbfb.267d68","type":"ui_colour_picker","z":"79df9203.a409ec","name":"","label":"","group":"aec2f80b.a31aa8","format":"hsl","outformat":"object","showSwatch":true,"showPicker":false,"showValue":false,"showHue":false,"showAlpha":false,"showLightness":false,"dynOutput":"false","order":8,"width":0,"height":0,"passthru":true,"topic":"","x":470,"y":80,"wires":[["c2735b8.0f402a8"]]},{"id":"e53fc48c.f09088","type":"function","z":"79df9203.a409ec","name":"not black","func":"if(msg.payload.l !== 0)\n    return msg; \n","outputs":1,"noerr":0,"x":900,"y":100,"wires":[["4ac39175.f01b8"]]},{"id":"94fe53c2.444ea","type":"ui_switch","z":"79df9203.a409ec","name":"","label":"On / Off","tooltip":"","group":"aec2f80b.a31aa8","order":8,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","x":480,"y":240,"wires":[["1a00a4b.e0dbe5b"]]},{"id":"47416ab5.d30f44","type":"function","z":"79df9203.a409ec","name":"light>hsl","func":"var col = global.get(\"color\");\ncol.l = msg.payload;\nmsg.payload = col;\nreturn msg;\n","outputs":1,"noerr":0,"x":620,"y":140,"wires":[["c2735b8.0f402a8"]]},{"id":"1a00a4b.e0dbe5b","type":"function","z":"79df9203.a409ec","name":"light off","func":"if(msg.payload === false)\n{\n    col = global.get(\"color\");\n    col.l = 0;\n}\n    \nif(msg.payload === true)\n{\n    col = global.get(\"color\");\n}\nmsg.payload = col;\nreturn msg;","outputs":1,"noerr":0,"x":620,"y":240,"wires":[["c2735b8.0f402a8"]]},{"id":"e17662db.a0a03","type":"mqtt-broker","z":"","name":"Broker","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"aec2f80b.a31aa8","type":"ui_group","z":"","name":"LED - TV","tab":"5b27353d.d34fbc","order":3,"disp":true,"width":"4","collapse":false},{"id":"5b27353d.d34fbc","type":"ui_tab","z":"","name":"Obývací pokoj","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

编辑:我不知道这是否是 JS 的正确行为,但这是一个小调试:

    col = global.get("color");
    global.set("ori_color",col);
    node.warn(global.get("ori_color")); //1
    col.l = 0;
    node.warn(global.get("ori_color")); //2
    msg.payload = col;

调试:1)H:300,S:1,L:0.5 2)H:300,S:1,L:0

所以它基本上追溯地改变了全局变量槽col变量.. wierd

标签: javascriptnode-red

解决方案


在 JavaScript 中,对象是通过引用传递和分配的。这意味着您必须将新对象分配给col变量(制作副本)。

if(msg.payload === false)
{
    var col = Object.assign({}, global.get("color"));
    col.l = 0;
    msg.payload = col;
}
else
    col = global.get("color");

msg.payload = col;
return msg;

推荐阅读