Conversion from Celsius to Fahrenheit

Started by Lensdigital, September 29, 2015, 10:09:47 AM

Lensdigital

I was wondering is there's any way to generate and display temperature in both C and F when sensor only sending Celsius temperature?
I'm not very good at Java/regex so haven't been able to figure it out yet, maybe someone done all the legwork already :)

Felix

#1
Look at this line in metrics.js:

FH : { name:'F', regexp:/F\:(-?\d+)/i, value:'', valuation:function(value) {return value/100;}, unit:'°', pin:1, graph:1, graphValSuffix:'F', graphOptions:{ legendLbl:'Temperature', lines: { lineWidth:1 }}}


This will match an expression like F:12345 (no decimals, negative sign optional). Then note the valuation function which takes the extracted value (12345) and divides it by 100 to get the final decimal value (123.45). You can do a similar thing to go from an expression like F:123.45 and convert to celsius with this formula:
valuation = function(value) { return (value - 32) × 5/9; } and use unit:'°C'
To match a decimal you have to add the dot in the expression:

regexp:/F\:(-?\d+\.\d+)/i
or
regexp:/F\:([-\d\.]+)/i


Edit: after posting this I realize you asked about C to F and I wrote it backwards, it's all the same just change the symbols.
Also at the moment you cannot generate 2 metrics from 1 given value. That may change in the future, but I think all of this is easier if you send 2 separate metrics from the remote node, making it more transparent what's going on, at the expense of a little longer RF packets.

Lensdigital

#2
Thanks a lot Felix! 
If I may ask another question :)
So now I get C converter to F and displayed on webpage, but C metrics stopped updating for some reason. Is there any way to have them both (without touching sensor's code)...
This is what I have in metrics.js

FC : { name:'FC', regexp:/C\:([-\d\.]+)/i, value:'', valuation:function(value) {return (value * 1.8) + 32;}, unit:'F°', pin:1, graph:1, graphValSuffix:'F', graphOptions:{ legendLbl:'Temperature' }},
  C : { name:'C', regexp:/C\:([-\d\.]+)/i, value:'', unit:'C°', pin:1, graph:1, graphValSuffix:'C', graphOptions:{ legendLbl:'Temperature' }},

Felix

#3
Like I said, you cannot natively create 2 UI metrics from 1 single expression in current version (v6 image). That could change by adding a simple function.

To achieve the desired functionality, what you could do now is call the global processSerialData function in your valuation function. That would actually create a recursive call since valuation is called by processSerialData (through determineValue) in the first place. BUT .. if you pass the right data, then that will process the argument as if it were an incoming message from the node. The only catch is that you have to pass in a certain format which includes the node id: '[nodeIdNumeric] message'. In your case it would be like processSerialData('[nodeId] CX:123.45').

For the nodeId you may be able to access the id variable (or perhaps existingNode._id) in the scope of the calling function (processSerialData).
So you may simply be able to do:

valuation:function(value) { processSerialData('['+id or existingNode._id+'] CX:' + value); return (value * 1.8) + 32;}


... where CX needs to be a separate metric to avoid an infinite loop by calling processing on the same expression:

CX : { name:'C', regexp:/CX\:([-\d\.]+)/i, value:'', unit:'°C', pin:1, graph:1, graphValSuffix:'C', graphOptions:{ legendLbl:'Temperature' }},


Lensdigital

Thanks! Trying to get this working as suggested.
Gateway crashes at this point "['+id or existingNode._id+']"
I tried replacing "or" with "||" , but then it says ReferenceError: id is not defined

Oh one more thing I wanted to ask. How would I limit return value to 2 decimal points? Cause I was getting numbers like "72.000008" :)