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

Hmm, thought so (background sound of scotch being poured, glugging sound and deep sigh of contentment!)

1 Like

I'm thinking this issue may take up a lot of time to get right

So I propose just scrapping option of using multiple outputs for the moment and re-introduce them later

In the meantime, if an advanced users wants multiple outputs, then could simply set a flow context (say called whichOutput) and use a switch node following the Blockly node to do the actual switching dependant on value of flow.whichOutput

image

image

Hi Julian (@TotallyInformation),

I'm back at home, after consuming some lovely Belgian beers. So don't believe everything I'm saying at the moment :roll_eyes:

Will try to explain the issue, like I always explain such things to an audience suffering from melted brains...

  • Below the Blockly editor you can define the number of output ports (similar to a function node):

    image

    This number is available when the Javascript is generated (when the 'Done' button is pushed). So far so good ...

  • In the send-block you can specify to which of those available outputs you want to send the message. In the first version this was a numeric input field:

    image

    This output number was also available when the code was generated (at the 'Done' button). So the generator had both numbers, and could do it like this:

    IF outputnumber > availableOutputCount THEN GENERATE 'node.error(...)'
    ELSE GENERATE 'node.send([ null, null, msg, null ])' --> the code generator composes the array !!

    So everything was working fine. In both cases only a single line of Javascript code was generated. Clean and easy to understand for somebody that wants to learn Javascript from the generated code ...

  • However in a later version I changed the numeric input field by a an input that allows any block that returns a number. For example:

    image

    The outputPort variable is set to 2, so the msg is being send to port 2 (since ouputPort variable contains 2). This allows us more flexibility, since users can now calculate an output number dynamically via other blocks. That sound good, but now I have a PROBLEM: when the code is generated (at 'Done' button), the generator only knows the number of available output ports. But the code generator doesn't know the output port number, since the variable outputPort is only calculated at runtime. So the code generator cannot generate the array [ null, null, msg, null ]. So that array needs to be generated at runtime, which means that the Javascript code to compose that array also needs to be put in the generated Javascript! This means the generated code will become very complex and difficult to understand !!!!

This is not what I want, so I want to get back to the first version (with the numeric input field). That works fine and the user can also do some advanced stuff with it.

Now it is your turn to give an example of what you mean ...

I think that the version (with a numeric input field) is very usable, so we should introduce it already in the first release of the blockly node. In the second release (together with timer support) we could add another EXTRA send-block, e.g. based on your array.

Keep in mind that I have already spend more than 6 weeks al my free evenings to this node. And my holiday ends this weekend, so from next week I will have even less time available. And I have still a lot of other Node-RED related stuff on my todo list, so I cannot postpone to much blockly stuff to the next release. Hope you can understand that.

1 Like

OK

But don't try and do anything else for the moment :slight_smile:

Lets get this ship launched! :slight_smile:

1 Like

Nice. Though the consumption of scotch on this end may not add clarity to my melted brain output!

Right, so why not have an outputNumber block that can only be 1 to the number set? Once the user has set the number of outputs and blurred away from the input, it is available to you (as the node author) via JQuery. Now you've eliminated one of your potential errors. The user of the node cannot select an invalid output node number. Doesn't that help? Certainly would make it easier for novice users I think?

OK, I re-read your code and it seems as though the scotch is actually helping because I can see that you are using template literal features in some cases (e.g. embeded variables that you want evaluated inside the string). But not in other cases. I'm a little anal about such things and I would use simple strings unless I needed something more.

Your code:

    var code = `if(${functionName}(${outputNumber})) {\n`;
    code +=    `  node.send([ ${outputArray} ]);\n`;
    code +=    `}\n`;

My anal code:

    var code = `if(${functionName}(${outputNumber})) {\n`;
    code +=    `  node.send([ ${outputArray} ]);\n`;
    code +=    "}\n";

The other potential problem back-ticks AKA "Template Literals" is that they are very new feature in JavaScript and likely wont work for one of those hangouts using an old version of Node.JS - it was first introduced into the JS spec in 2016 I think. Not sure what version of Node.JS it was implemented. However, people should be using at least Node v8.x which does support them so that shouldn't be an issue.

Just ignore me.

I've just noticed that the set msg block defaults to null value

I think it should default to an empty string (like property field but empty)

It wouldn't affect advanced users but would be better for beginners as the null concept would not be familiar to them

Simon

Hi guys, I have not much time today due to a birthdate party at home. Will get in touch tomorrow! But please keep posting meanwhile

Ok, sounds logical.

That could be a solution, but I can make it even simpler by replacing my numeric input by a dropdown that only shows available port numbers. Problem with both solutions is that the user can decrement the number of available outputs afterwards anyway. But it is better as a nuleric input ...

Indeed since you say that it is not available in older nodejs versions, I need to replace them by strings.
And yes you are completely right that code has become quite messy. It became much bigger as I original planned. Got code from the blockly forum, from Gist, ... All with their own flavours. Have started a large refactoring yesterday evening, but still lot of work. But it is starting to look better already (code wise)...

re set msg to empty - (I'm not fully up to speed on this but) ... is that msg itself ? or msg.payload ? ... setting msg to null is valid (meaning don't send anything) - setting msg to "" will break things as it needs to be an object.

Wrong language used :frowning:

I meant the value field of the property of the set msg block not the msg itself :slight_smile:

(@BartButenaers knew what I meant - he's learnt my version of English very well :slight_smile: )

[FINAL NOTE TO SELF]

I MUST NOT MAKE ANY MORE COMMENTS AT ALL

(unless I feel the universe may end if I don't)

:slight_smile:

Hi guys,

There is now a new version on Github available, to implement the extensive feedback that I received.

Took a bit longer as expected, since my holidays are over ( :sob: ) , and had some major issues with Blockly. The code of my custom blocks has been refactored heavily: hopefully I didn't introduce changes/bugs in the looks of the blocks and the code they generate. Did a lot of testing, but you never know ... @TotallyInformation: now at least the code is more consistent.

An overview of what has changed in the new version:

  • In all the code generators, the template literals have been replaced by simple strings (to support older NodeJs versions).
  • All block definitions are converted from javascript to JSON format. Blockly allows you to write custom blocks as JSON or as Javascript, and since I'm a developer I used Javascript. However that becomes very difficult to understand, when multiple inputs are being used. Moreover the JSON format is 'much' better for multi-language support (see next point).
  • This JSON format allowed me to create a separate en.js file, containing all custom blocks text in the english language:
    Blockly.Msg.NODE_LOG = "log text %1 with %2 level";
    Blockly.Msg.NODE_LOG_TOOLTIP = "Log via the Node-Red function API.";
    Blockly.Msg.NODE_MSG = "msg";
    Blockly.Msg.NODE_MSG_TOOLTIP = "Get the Node-Red input message.";
    Blockly.Msg.NODE_REMOVE_STATUS = "remove node status";
    
    This way users can start creating pull-requests to translate the custom blocks in their preferred language.
    Similar to the basic blocks (from Google), which are already available in 43 languages.
  • The send-message block input now only allows type 'Object', to avoid that users e.g. send a string instead of an object containing a string.
  • Some code generators generated a tab ( \t ) to represent indentations. Now all indentations are two spaces, since all basic blocks (from Google) do it that way. I wanted to avoid a mix of spaces and tabs.
  • To use the semantic versioning, the version has been changed to 1.0.0 (and @cymplecy has become official contributor in my package.json file :ribbon: )
  • I changed color of Blockly node from #F888AC to #FFAAAA to match the standard Node-Red colours. Simon also suggested to use #FDDOA2 (like the function node), but I think the world is already grey enough...
    image
  • The set-property block has now external inputs (see screenshot in next bullet), a request of Simon.
  • The set-property block had by default a null value, which is now replaced by an empty string:
    image
  • The numeric input for output number has been replaced by a dropdown, containing all available output numbers (so a user cannot be mistaken). The dropdown is immediately updated, when the number of outputs will be changed (see animation in next bullet).
  • When changing the number of outputs, a (non-blocking informative) popup message will appear when higher output numbers are still in use:

TODO : Simon asked to move the property-get and property-set blocks (from Object category) to the Node-RED category:
image
Not sure whether to do this or not. Others have an opinion about this request??

All constructive feedback is welcome !!
Bart

P.S. I will pause documenting the node, since the numbers of changes is still rather high at the moment.

2 Likes

... as they are likely to be the most used blocks and they are what NodeRED is all about :slight_smile:

Just updating then I'll see if anything breaks with what I've already coded up

Simon

1 Like

1st comment - at least I can now take my sunglasses off when editing :slight_smile:

1st test passed :slight_smile:
My most complex flow that uses using Blockly works fine - the only block that needed re-editing was the status one - they had all lost whatever was in the text slot - but all good now :slight_smile:

image

Must admit that Simon has - most of the time :roll_eyes: - good reasons to request some stuff, so I should have added the reason-why in my post ...

I tried to keep the field names unchanged, to avoid corrupting your existing test flows. But some might have been changed, if I had no other choice ...

For people that like to know a bit more in detail how Blockly works, here is a quick explanation of what I mean. For example let's have a look at how to layout following custom block:

image

  • The first way to implement this, is using Javascript:
    image
    Not very easy to read, and moreover the text is splitted across 3 appenField method calls. So our sentence is splitted, and not available as a whole...

  • The second way to implement this, is using JSON:
    image
    So we start with the sentence as a whole, containing 3 placeholders (%1, %2, %3). In those placeholders, Blockly will automatically add one of the 3 widgets (text input, color picker, dropdown). It could be in other languages that the sentence will be entirely different, having the placeholders at different locations (e.g. xxx %3 yyy %1 zzz %2). The major advantage of JSON is that Blockly will automatically rearrange the widgets to fit the translated text (dropdown, text input, color picker).

I'm having issues with my NodeRED -> Scratch flow that uses buffers but I'm not sure its actually due to an issue with Blockly - it might be an issue with the TCP node itself (I hadn't tested the flow out since upgrading to 0.19 )

I've been up a long time (airport transfers early this morning so I'll try checking it out in more detail tomorrow as brains is frazzled now

I have to say a big "great work"! This has come a long way in a short time. Looking forward to people getting their hands on it, should be interesting to see how they might use it.

its not a Blockly issue so all OK there

All existing Blocky nodes are working fine - as said before only the status block needed re-editing

I'll try use Blockly to replace some standard node combinations just to make sure its working OK

1 Like