Function node & var definition

I must anticipate that I am not a programmer and most comes from cut & paste from others work.
I cannot understand the behavior of a function node I am using (NodeRed 3.0.2 and Monaco editor).
The function uses a Case statement:

var data = msg.payload.split("\t");
switch (data[0]) {
    case 'SOC':
        stateoc = parseFloat(data[1] / 10);
        break;
    case 'V':
        voltag = parseFloat(data[1] / 1000);
        break;
    case 'I':
        curren = parseFloat(data[1] / 1000);
        break;
}
return [
    {
        payload: {
            SOC: stateoc,
            Voltage: voltag,
            Current: curren
        }
    }
]

but written like this I get: "ReferenceError: 'name' is not defined (line 16, col 18)" for the three variables used. If I run the flow, after the error messages, the function works fine.
If I resolve the error message defining the variables with var or let (same result for both), I get no error but the function doesn't work anymore and all the variables results are undefined.
Any clue on this behavior?

For the variables inside the switch statement, if you use let or const to define them, the JavaScript standard ensures that they exist only within the current context. In your case, the context is within the individual case statement.

If you use the older var to define them, they are "hoisted" to the top of the function internally so that will work. Using them without a definition will make them global. In the case of a node-red function node, that doesn't mean much because each function node operates in a node.js virtual environment. However, both of these approaches are very much discouraged since in other contexts, they can cause various issues.

The thing to do here would be to define the variables at the top of the function:

const data = msg.payload.split("\t");
let stateoc, voltag, curren  // defines the vars but does not give them a value
switch (data[0]) {
    case 'SOC': {
        stateoc = parseFloat(data[1] / 10);
        break;
    }
    case 'V': {
        voltag = parseFloat(data[1] / 1000);
        break;
    }
    case 'I': {
        curren = parseFloat(data[1] / 1000);
        break;
   }
   default: { // always good practice to define this even if you don't use it
       // nothing to do? or do you want an error shown?
   }
}
return [
    {
        payload: {
            SOC: stateoc,
            Voltage: voltag,
            Current: curren
        }
    }
]

Note that I've also wrapped the case code blocks in { ... } which makes things a lot clearer (to me anyway) and there are a couple of rare edge-cases that are avoided.

Just guessing (as not near a computer) but I suspect you need to change the definition of 'msg' to an object.

var data = msg.payload.split("\t");
switch (data[0]) {
    case 'SOC':
        stateoc = parseFloat(data[1] / 10);
        break;
    case 'V':
        voltag = parseFloat(data[1] / 1000);
        break;
    case 'I':
        curren = parseFloat(data[1] / 1000);
        break;
}

msg.payload = {};  // <<<<<<<<<<<< Try adding this line and see if it works ??
return [
    {
        payload: {
            SOC: stateoc,
            Voltage: voltag,
            Current: curren
        }
    }
]

You have another problem, in that each time through only one of stateoc, voltag and curren will be calculated. So in the return statement, where you setup the payload, the other two will be set to undefined.

It doesn't cause an error, but you don't need the square brackets around the return message, since there is only one. Finally it is generally better practice to modify the original message and send that back, rather than create a new message. So the last part would read

msg.payload = {
            SOC: stateoc,
            Voltage: voltag,
            Current: curren
}
return msg

Thank you so much, I tried your suggestion, but as with my previous attempts, if I declare the variables with "let" the functions return undefined values; if I remove the variables declaration, i get the initial error but then the function works with the expected results

Tried even this one, but it changes nothing. Thanks anyway

Thanks Colin, you are right but in this way every now and then I get a payload at "0" that I don't get in the other way.

The change I suggested would not cause zeros. To check, have two functions, your original and the modified one, and connect them both to the same source. Check the outputs of both to see if they are different.

Can you please share your updated code.

Yes they are, mine has no zeros. :thinking:

I just copied and pasted your code

Please post the function you are now using. How can you have copied @TotallyInformation's code if you have my changes in too?

I have tried every single suggestion by itself and checked the result, then answered to each of you regarding his suggested change.

Anyway this is the code with both suggestions:

const data = msg.payload.split("\t");
let stateoc, voltag, curren;
switch (data[0]) {
    case 'SOC':
        stateoc = parseFloat(data[1] / 10);
        break;
    case 'V':
        voltag = parseFloat(data[1] / 1000);
        break;
    case 'I':
        curren = parseFloat(data[1] / 1000);
        break;
}
msg.payload = {
    SOC: stateoc,
    Voltage: voltag,
    Current: curren
}
return msg;

and this is the debug output running this code:
image

And a debug of the message going in?

**[Edit]**Also add a line after the split

node.warn(`data[0]: ${data[0]}`)

Not quite what I posted. At the least, you need to add a test to make sure that you handle the case where data is not an array (because there was nothing to split - e.g. no tab in the text), you should also use try/catch around the first line in case the split fails completely. You also need to include my suggestion of handling the case where data[0] is not one of your specified values. That's what the default case does.

The incoming message is always the same, already checked with a debug node.
In any case the point is that, leaving the input untouched, the function has the reference error but gives the right outcome if I do not declare the variables and gives the undefined values if I declare the variables. All the other staying the same.

You are right, but even using your code exactly as you have written, the results are the ones I have already put in my answer.
All the cosmetics of good programming have not changed the results as just replied to Colin.

Just for the sake of completeness the incoming messages are from a serial port node of a Victron BMV 712, the format is factory defined with tabs separating labels from values. I checked for hours and the incoming messages are always formatted in the same way.

Please do as we ask. Add the warn and the debug node before and after and show us what you see. Perhaps you are just missing something. Why do you resist doing what we ask?

and at least share an input msg that fails and one that works so that we can help. Without that info, we can't help, especially if you don't put the other checks into your code.