Node-red-contrib-blockly 1.0.0 available

Urm, I don't think you should be trying to access global directly. That's why there are get/set functions. So I'm not sure that is a valid example. None-the-less, as I said, I didn't think it would be necessarily right for this use.

New 1.1.0 test version available on Github with following changes:

  • The nested properties described in the previous post
  • The 'has' property dropdown option described in the previous post
  • A single line comment block as requested by @cymplecy. The multiline comment is much more complex, so I will implement that probably in a next life. Seems that Blockly also allows to add a comment to a block, but via the right-click contextmenu. So now you have two ways to implement it:
    blockly_comment
  • A javascript block that allows you to manually enter a Javascript command. I didn't make it multiline, because it should only be used to add short code snippets. If you want to add long code snippets, then you should use the function node instead ...
    blockly_javascript
    I think such a block is required since I'm not going to implement the entire Javascript language as blocks. And it would be a pitty that you cannot use Blockly, if a single you need a small code snippet, but the corresponding block doesn't exist (yet). When you have inserted the same code snippet all over the place, this might be a good indication to request a new block that can be reused by other users...
1 Like

Eeek!

I've always thought that this was needed - but only for emergiencies

I wouldn't have told everyone and I would have hidden it at the end of of the longest category :slight_smile:

And then only told people about it when they had tried to use all the blocks to execute their algorithm

Hi @mikeS7 ,
Nice to hear that you are in the mood for extending the blockly node.
Have moved your question to this Blockly discussion, because I don't want to go to much off-topic in Andrew's discussion. And I want to have also 'at least' the opinion from @cymplecy and @TotallyInformation , who are at the moment the two most important men in my life... :sunglasses:

At the moment I'm not quite sure how we need to proceed with this. In the 0.19 release the node.id and node.name have been added to the function node API. And now in the 0.20 release the function node API is again updated to support environment variables.

We can easily add an environment-block to support environment variables (next to msg / flow / global / node), and add the functionality to the server-side code: the server-side code is 100% identical to the function node! But - in contradiction to the function node - our blockly node can be installed e.g. on an old Node-RED version 0.17 release (which doesn't support environment variables). What should we do in that case, to avoid things will explode?

  • We could hide the environment-block in the toolbox, but then users will start looking like crazy (since they meanwhile have seen a tutorial on the web demonstrating that block).
  • We could let the user drop it in its workspace, and show a warning icon (like in the node-send block) for older versions. And during code generation we could simply generate a node.error('Node-RED version ... does not support environment variables via API).
  • Others ...

Moreover I don't like having to copy the function node code for every Node-RED release. Would prefer that I could somehow just call the function node's code under the hood. Then Blockly is always in sync with the function node. I think this would even be better: then we always use the function node code of the Node-RED version we are running on! If we are running on an older version, then the function node API would be automatically more limited. But not sure at the moment how I could do that, i.e. something like this I suppose:

function BlocklyNode(n) {
  // Delegate the request to the function node code ...
  FunctionNode(n);
}
RED.nodes.registerType("Blockly",BlocklyNode);

Any thoughts from anybody on this one ?

KISS
Just don't support any previous version of Node-RED

If Blockly was an old node with zillions of users using it - then there might be a need to maintain it working with an older release

Maybe just keep old versions available as github branch archives in case someone for some strange reason, can't upgrade to latest Node-RED but needs to have Blockly node

Simon

Steady on old chap! I am British after all :blush:

One of two things I think, of which I prefer the 2nd:

  1. Don't support older versions (as Simon suggests) - actually, I'm not convinced by this simply because of the speed at which NR is developing. There will be lots of people who, for various valid reasons, won't be able to upgrade in a hurry.
  2. "Grey out" the node if the NR version is not high enough. This would be my preference. The block still shows up so people don't wonder where it is, but you can't actually use it. Not sure if this is possible though. Otherwise, generate an error if someone tries to use it with an older version of NR.

As to being able to use the function node's code. I think you may need to contact Nick/Dave on that one.

My gut feel is that it probably isn't sensible simply because you will have created a tight coupling between your code and theirs. This is VERY likely to break something each time the function node is updated.

One possibility might be a PR with a refactoring of the code in the function node so that all of the utility is in an includable module file. If it isn't already. However, this would need careful thought and some planning because that sub-module would need to have a well defined and stable interface defined and documented.

I think that a better approach would be to look at what code could sensibly be refactored such that it could either become part of the RED object with corresponding standardised API or part of some other common library that might be useful to node builders.

In any such case, I doubt this is a 5-minute job and would need discussion with Nick and Dave.

Yes, that is why I posted this question. I have not enough knowledge to solve this at the moment

Yes I also want to do it in the KISS way, but think there are a lot of different Node-RED versions currently running all over this planet. So would like to solve this decently, in some way or another ...

Yes. And by hiding or disabling the block in the toolbar, you get another problem: suppose you are running on an older Node-RED where the block is invisible/disabled. But you import an example flow which contains that block. Then we would run into troubles again. If I generate a 'node.error(...)' there would be no problem in this case.

Good point. So you would still need to error check it, that is true.

The idea was just to add ability to use require-from-string. I want to add checkbox to allow choice what "VM" to use. In version 1.1.0 you added javascript block and we can use new function API without adding a new block (block can be added later). Hope will have the code next week and you can look to continue the discussion.

I want to ask about new feature:

  • Has property in a get block is the nice feature. Could you please add default value to the get method to support javascript style such as msg.property || <value> or for a context context.get('property') || <value>

Hi Mike :slight_smile:

I pushed for this (and the set) block to have the simplest syntax possible and to be the 1st blocks in Blockly node as they would be the most familiar things compared to using standard change node.

I would like Blockly to be a stepping stone from standard change nodes to writing JS function nodes directly

I feel it would be better overall if Blockly users just had to put a few more basic blocks together rather than having an overly complicated block that does everything JS can.

the || <value> JS construct is a very neat and useful part of JS but not very common in simple languages

But maybe there could be a separate || <value> block so all that would be needed would be

set myVar to [get msg property payload]
set myVar to myVar || something

What do you think?

Simon

don't forget that that syntax doesn't always work as 0, "0", false, etc are all "falsey" in javascript, so while it's a neat shorthand in many cases... it's not 100%. I'd argue it's safer to leave out of the blocks for now.

1 Like

@cymplecy Simon, it can be done such way:


but I've got:
var1 = 'default';
var1 = (msg['payload']) || var1;

2 lines ... I want only one. OR block allows to connect only logical value or a variable at the second input

Yes - OR in Blockly is designed to just use boolean true/falses values.

Unfortunately, the basic Blockly blocks such as this cannot be altered in what types they will accept.

So to do what you want, I think @BartButenaers would have to add a get xxx || yyy block that accepts any values for xxx and yyy

But going down this route could mean having a Blockly block for every JS syntax possiblity and this is impracticable in the long term

If all it takes is to use two blocks instead of one, then that might be a price worth paying to prevent lots of extra blocks being created

And if you had a need to use a lot of them then I'd just create a simple function to do the job

image

Hi Mike, thanks for joining our discussion!

Never used that before. Do you want it to add extra libraries, without having to specify them in the settings.js file? If so, can the generated code be copied to a function node (or will the code not run anymore in a function node)?

I have also proposed already a few checkboxes recently, but none of them survived the discussions on this forum :face_with_raised_eyebrow: Indeed we want to happen it all behind the scenes, so our users won't have to bother about the technical stuff. So we prefer not to add extra widgets...

Simon has never been a huge fan of my Javascript block, and I'm starting to understand why. I added it as a last resort, if no other block can be of any help. However I didn't create it to call e.g. Node-RED API functions for which I already have created blocks. So perhaps it is not a good idea to publish the Javascript block anyway.
P.S. It is not much work to add a new environment block, however I just need to have a better mechanism to determine which blocks are available in the Node-RED vesion blockly is running on top ...

That seems indeed to be a reasonal question to me. But I also understand that Simon wants to keep its blocks simpel. And as Dave indicates, it is not fully waterproof...

A summarize of the possible solutions:

  1. Don't add the new feature. But would be a pitty if you have to add 300 extra blocks to achieve such an easy task ...
  2. Add a default value somehow to the current get-block.
  3. Create a new default-get-block which is identical to the get-block, but which allows to specify a default value. But that will result in too much blocks
  4. Create a new OR-block that accepts any value.
  5. Add a dropdown to the current set-block, which contains 'set' and 'set existing' options. When you select 'set existing', the value will only be set if existing. So when you set the default value first, it wouldn't be overwritten afterwards. However then you again need multiple lines ...

I would go for 2 or 4. And my favorite is 2, to keep the number of blocks under control.

Besides to the 'default values' discussion, I have another dilemma...
I'm developing Date/Time blocks, but seems that Javascript standard support for Date/Time lacks some of the functionalities that I need. For example I want to format a date like this:

yyyy-mm-dd hh:MM:ss

Could accomplish this in two different ways, each with their own (dis)advantages:

  1. Currently I wanted to use only standard Javascript, so I generate my own formatDate function:
    image
    The advantage is that it is plain Javascript code, so you can easily copy it to e.g. a function node. But the disadvantage is that the generated code becomes complex, and that my function offers not all functionalities (otherwise it would become too long) ...

  2. I could use the 'moment' node, which is build on top of moment.js. This way I can generate only a single line of code:

    moment().format('MMMM Do YYYY, h:mm:ss a');
    

    This code is very short and easy to read, but you cannot simply copy the generated code to a function node. Indeed, the user will have to specify the moment node in his Node-RED settings.js file.

Personally I would prefer to switch to option 2, but don't want to confuse users by the syntax errors that occur when pasting the code in the function node...

Any advise on this one ??

Copying code to a plain function node, I think, is a must have feature so that people can "tweak" the Blockly code if needed or want to.

Therefore I don't think moment can be used if it requires editing the settings.js file

I did some googling and came up with this as possible solution

image

var timestamp, myDate;


timestamp = (msg['payload']);
myDate = '';
myDate = (new Date(timestamp)).toISOString().replace(/[^0-9]/g, "");;
node.status({fill:"blue", shape:"ring", text:myDate});

2 is the last option on earth I would hope you to implement

For all the reasons stated in previous post e.g.1st block simplicity / beginners moving from change node to Blockly node and going "what is this this default thing????"

Simon

Ok that was the answer I was hoping for. Just wanted to make sure that I had developed it correctly ...

The toISOString is indeed something that works, and I used that in the beginning. But I wanted to allow other formats like e.g. dd.mm.yyyy, and that is not possible with the standard Date class.

So I will use the toISOString, and only generate a formatDate function for custom formats. And I will never generate code that uses third party libraries, like e.g. moment.js.

EDIT: The toISOString() method converts a Date object into a string, using the ISO-8601 standard (format is: YYYY-MM-DDTHH:mm:ss.sssZ like e.g. 2011-10-05T14:48:00.000Z). Which label should this option needs to get in the dropdow list: ISO, ISO-8601, YYYY-MM-DDTHH:mm:ss.sssZ, ... ????

When you only say what you don't want, you sound like my wife :wink:
My male neural network has now concluded that Simon only wants option 4. Is this result correct?

Bart

I would vote for not having option 4 either but it not the show stopper that option 2 is :slight_smile:
I'd just like to quote an earlier comment

Simon