[ANNOUNCE] Visual programming a function node with Blockly - Feedback request

Simon,

There is a new version on Github with following fixes:

  • Status block: it now generates yellow instead of orange (see animation below).
  • Status block: if the status text is empty, it now generates a status object {} to remove the status from the node (see animation below). This way this weird error is not displayed anymore:
    image
  • Both the javascript files (for Blockly and all blocks) and the xml files (for toolboxes) are now loaded from a relative server path. You shouldn't notice this, but there was an issue reported that the Blockly editor wasn't visible when httpAdminRoot was used.
  • Extra logging is added for the toolbox XML document creation. This seems to fail (see also issue) for that user, but I don't have clue at the moment why that happens. But again you shouldn't notice a difference ...

This animation shows the yellow status displaying, and how to remove the node status:

P.S. instead of adding a text-block without text, it now also works when no text-block is added:
image

2 Likes

Works lovely now :slight_smile:
GIF

I MUST STOP SUGGESTING THINGS

but ......

maybe the status block should have a default empty text block instead of an empty space and there should be an explicit clear node status block?

Simon (running away fast......................................................... )

[BUG]
image

Simon,

A new version is available on Github to fit your needs:

  • Your pull request has been merged, so the orange color (in the color picker) is changed to yellow:
    image

  • The status node has now a default empty text field (instead of no text field):
    image

  • I have added a new 'remove node status' block:

  • The bug about the non-existing output number is fixed. Problem was that I choosed at generation time which code I had to generate: the code with msg.send ... OR the code with node.error ... But that was incorrect in your case: you used a variable (which can change at runtime), so at generation time I cannot always determine which port number will be used.

    So in the new version I had to generate code with BOTH msg.send ... AND the code with node.error ... At runtime one of both code snippets will be executed, depending of the output number being passed at that moment. So I tried to generate something like this:
    image
    However the code at line 1 is not readable for users that want to learn Javascript this way, due to the magic numbers (first '1' is the outputNumber and second '1' is total available number of outputs). Tried to solve this by generating automatically variables:

    const OUTPUT_NUMBER = 1;
    const AVAILABLE_OUTPUTS = 1;
    if ( OUTPUT_NUMBER > AVAILABLE_OUTPUTS) {
       ...
    

    However this doesn't work if you use multiple send blocks in your editor, since you will end up with duplicate variables. That can be solved by generating unique variable names, but then it becomes messy ...

    To get around this, I now generate a function at the top (which is used further on) :
    image

    I THINK THIS WAY THE MAGIC NUMBERS ARE EXPLAINED ENOUGH. IS THIS A GOOD SOLUTION OR SHOULD I SOLVE IT ANOTHER WAY ???

    P.S. if multiple send blocks are available in the editor, only 1 function will be generated and used by all those blocks...

re Bug above
That's been fixed :slight_smile:
But still not quite right

image

var outputPort;

function isValidOutput(outputNumber) {
  const AVAILABLE_OUTPUTS = 2;
  if (outputNumber > AVAILABLE_OUTPUTS) {
    node.error("Cannot send to output outputPort, since only 2 outputs available");
    return false;
  }
  else {
    return true;
  }
}


outputPort = 1;
if ((msg['payload']) == true) {
  outputPort = 2;
}
if(isValidOutput(outputPort)) {
  node.send([ null, null ]);
} 

I think it should end up issuing something like
node.send([null,msg]);

I must have pressed button at same time as you

Let me read yours 1st :slight_smile:

mm...I see its complicated :frowning:

If you can't see how to make it work at the moment then maybe remove ability to have more than 1 output at the moment.

Add it back in a later release?

1 Like

I'm currently using this as a workaround for the moment

image

var outputPort;

function isValidOutput(outputNumber) {
  const AVAILABLE_OUTPUTS = 2;
  if (outputNumber > AVAILABLE_OUTPUTS) {
    node.error("Cannot send to output 1, since only 2 outputs available");
    return false;
  }
  else {
    return true;
  }
}


outputPort = 1;
if ((msg['payload']) == true) {
  outputPort = 2;
}
if (outputPort == 1) {
  if(isValidOutput(1)) {
    node.send([ msg, null ]);
  }
} else {
  if(isValidOutput(2)) {
    node.send([ null, msg ]);
  }
}

which is good enough for me at moment :slight_smile:
Simon

Damn again... I have currently a loop inside the code generator, to build the node.send statement:

    // Send the message only to the specified output number, and null to all other outputs.
    var outputArray = '';
    for (var i = 1; i <= Blockly.nodeOutputs; i++) {
        if (i > 1) {
            outputArray += `, `;
        }
        
        if (i == outputNumber) {
            outputArray += `${inputValue}`;
        }
        else {
            outputArray += `null`;
        }
    }
    
    var code = `if(${functionName}(${outputNumber})) {\n`;
    code +=    `  node.send([ ${outputArray} ]);\n`;
    code +=    `}\n`;

But since I don't know anymore at code-generation-time which output number will be used (since that is only determined at run-time), this means I have to put the above loop also in the generated Javascript. This will result in unreadable code. Don't like that. It should stay in the code generator, and be invisible to the users.

Isn't it better that we don't allow the output number to be generated at runtime. I.e. only allow a fixed number to be entered. The logic to determine which output needs to be used shouldn't be INSIDE the output_number input field, but instead AROUND our send-block. For example by using an if-block:

image

Otherwise nobody will understand the generated code anymore. Does this makes sense?
@TotallyInformation: Julian, would be nice to get your opinion. And also other users ...

1 Like

Now I saw your latest post too late. Seems my last proposal is the same as your workaround ...

I reworked the send block to work again with fixed output numbers.

In the following example I have a blockly node with 3 outputs.

  • Messages with payload '1' will be send to output 1
  • Messages with payload '2' will be send to output 2
  • Messages with payload '3' will be send to output 3
  • Messages with payload '4' will result in an error

blockly_send_fixed

I think this enough for most users. It generates very compact understandable Javascript code, and the users are still able to do some more advanced stuff (like the message routing in the above animation).

P.S. If no counter proposal, I will put this version on Github tomorrow evening.

1 Like

My counter proposal is to allow arrays to be sent instead of just msg

so have a block
send xxx to output
where xxx defaults to msg

but let people set xxx to [msg,null]
or whatever they want

This would align it perfectly with JS

Since there are e.g. multiple LOOP blocks available, we might offer two separate SEND blocks:

  • one with an msg and an output number
  • one with a msg array

Not sure what you mean by "Since there are e.g. multiple LOOP blocks available,"

I'm off out now till 16:00 GMT - see you later :slight_smile:

I just wanted to say that Google also provides sometimes multiple blocks to achieve the same result. For example when you want to repeat something 10 times, they offer two blocks to do this:
image

So we can also offer two separate blocks for sending messages: one that accepts a list and another that accepts an output number. That's all ...

understood

Sorry been busy catching up work.

In regard to having multiple output channels, the Node-RED way is to define the number in the configuration of the node instance. This makes it fixed and therefore known in advance doesn't it? Or have I missed something? Maybe someone could drop in an example flow to illustrate the issue?

In regard to having multiple blocks to do something similar, I think this is absolutely in line with the expected audiences. Having a simplified block and one that is more complex but flexible. As long as it doesn't get out of hand so that you end up with thousands :smirk:

One small thing about code style - you seem to have a lot of back-ticks rather than the single quotes (or double if including escaped control characters) I would generally use - is there a reason for that? I'm not sure if there is a performance or other impact from only using back-ticks?

The "problem" is that , at present moment, the Blockly node lets me use a variable for the ouput.
But since the value of the variable is not known at "compile time" (when the JS is generated) then trying to cope with that situation leads to a lot of complex JS (that Bart is trying to avoid)

(Follow the links to previous posts - forum doesn't format them properly when I pasted the link in!)

But can't you simply fix the number of outputs in advance like you would have to in a function node?

Sorry if I'm being thick, it's been a long week and I spent the whole afternoon in a remote workshop designing a data model - brain melt!

Yes AND No - think Schrodinger's Cat Problem :slight_smile:

The issue is not for those suffering from withered brain cells :slight_smile: