Function writeup for Cyclical Hexadecimal Payloads

Successfully established a webhook that provide a payload every 10 min from 4 distinctly different data sets. Every 10 min the payload represent a different data origin trough a single webhook: first 10 min the payload will represent a temperature value, the following 10 min will produce a payload of relative humidity and so on with two other sensors. At the end of 50 min the temperature sensor will sent its payload again and so on in a cyclical manner.

The data I receive is configured in the following manner:

The data section example in the payload is: “data”: “30312b303030363335333630”
This should translate into:
Chanel Number: 01
Sign: +
Measurement Value: 63536 (I would like to present this as 20.4)
Digital Input value is: 0

30 31 2B 30 30 30 36 33 35 33 36 30
0 1 + 0 0 0 6 3 5 3 6 0
L1 L0 D9 D8 D7 D6 D5 D4 D3 D2 D1 IN

How should I set the Function in the following Workflow:

I am trying to follow the instructions in: https://www.losant.com/blog/collect-monitor-visualize-sigfox-data
Unfortunately is show only a single (non cyclical) function setup.

Thank you for your assistance

Hi @tirosh_gutte,

It sounds like you are hoping to separate your data string into multiple strings to parse, which will have to be done with Javascript. I found a couple of Stack Overflow answers that can help further. The first is on separating strings every n characters, and the second is on getting a key’s value in a map. I would recommend setting up a map with keys and values based on this chart:

If this is not what you were hoping to do, let me know!

Thanks,
Julia

I have tested the below function in javascript and it seem to convert the HEX payload (in an innerHTML test) to ASCII and into respective/defined variables to read from (mapping the string). I have two questions:

  1. How will losant workflow Function recognize the “sign”. Currently we will get 43 for a positive number under the SIgn Var and 42 for a positive sign of the value.
  2. The value that will be returned from the javascrip function I wrote will be 00063536 (will be saved into the ValueTot Var. How will the Losant Function Workflow interpert it? From the example linked in the original question paseInt(str.substring(#,#),16) the converstion will be Hex to Dec. The converstion tested will be Hex to Ascii

function myFunction() {
var str=‘30312B303030363335333630’
var ChaNum1 = parseInt(str.substring(1, 2),16);
var ChaNum2 = parseInt(str.substring(3, 4),16);
var Sign = parseInt(str.substring(4, 6),16)+"
";
var Par1 = parseInt(str.substring(7, 8),16)+"
";
var Par2 = parseInt(str.substring(9, 10),16);+"
";
var Par3 = parseInt(str.substring(11, 12),16);+"
";
var Par4 = parseInt(str.substring(13, 14),16);+"
";
var Par5 = parseInt(str.substring(15, 16),16);+"
";
var Par6 = parseInt(str.substring(17, 18),16);+"
";
var Par7 = parseInt(str.substring(19, 20),16);+"
";
var Par8 = parseInt(str.substring(21, 22),16);+"
";
var DigIn = parseInt(str.substring(23, 24),16);+"
";
var ChaNum = ChaNum1 + ChaNum2;
var ValueTot=Par1+Par2+Par3+Par4+Par5+Par6+Par7+Par8;
}

I am probably missing somthing in the function comprehention. Thank you for your assistance

Hello @tirosh_gutte,

If the workflow sees a positive number value, it will not prepend the number with a “+”, so if you are looking to see a + only, I would recommend putting it in as a string value so you can note “+” or “-”.

The workflow will interpret your values based on the workflow you have written. For example, if you were to want each of those individual values to report as state attributes, you would need to put all of your values on the payload. You would do so with payload.par1=parseInt(str.substring(x,x),x)+"", and then use a Device State Node to report state. The Losant workflow will not change the values for you, you will need to do that with conditionals and a map of the values and their conversions, which is shown in the above Stack Overflow example.

Thanks!
Julia

Thank you for your reply

  1. Regarding the “+” “-” representation I am not clear on how a string will indicate the sign of the number that follow.

  2. I am not clear on how to differentiate the address variations arriving from the device and how to differentiate them as pert of reading the data

  3. Regarding the Function code:
    We reduced the workflow to the following deployment:
    image

In the Function Code we have:

payload.data.body.ChaNum1=parseInt(payload.data.body.data.substring(1, 2),16);
payload.data.body.ChaNum2=parseInt(payload.data.body.data.substring(3, 4),16);
payload.data.body.Sign=parseInt(payload.data.body.data.substring(4, 6),16);
payload.data.body.Par1=parseInt(payload.data.body.data.substring(7, 8),16);
payload.data.body.Par2=parseInt(payload.data.body.data.substring(9, 10),16);
payload.data.body.Par3=parseInt(payload.data.body.data.substring(11, 12),16);
payload.data.body.Par4=parseInt(payload.data.body.data.substring(13, 14),16);
payload.data.body.Par5=parseInt(payload.data.body.data.substring(15, 16),16);
payload.data.body.Par6=parseInt(payload.data.body.data.substring(17, 18),16);
payload.data.body.Par7=parseInt(payload.data.body.data.substring(19, 20),16);
payload.data.body.Par8=parseInt(payload.data.body.data.substring(21, 22),16);
payload.data.body.Digin=parseInt(payload.data.body.data.substring(23, 24),16);
payload.data.body.ChaNum = payload.data.body.ChaNum1 + payload.data.body.ChaNum2;
payload.data.body.ValueTot=payload.data.body.Par1+payload.data.body.Par2+payload.data.body.Par3+payload.data.body.Par4+Par5+payload.data.body.Par6+payload.data.body.Par7+payload.data.body.Par8;

Is there a more elegant way to have these values mapped? and how can payload.data.body.ChaNum1 and payload.data.body.ChaNum2 be used to portray the address from which the data is being read. Reminder: The payload will show a data string that will change every 10 minutes and will portray a different address dedicated for a specific data string.

Address 01: First Data set
10 mIn
Address 02: Second Data set
10 min
Address 03: Third Data set
10 min
Address 04: Forth Data set
10 min
Address 01: First Data set
10 mIn
Address 02: Second Data set
10 min
.
.
.
and so on

Thank you for your help throughout this process

Hi @tirosh_gutte,

My first recommendation would be to use a Switch Node to differentiate the address variations, but this means there will have to be something on your payload to indicate where it is coming from (an ID, some unique variables, etc.). If that exists, you will be able to successfully use a Switch Node and can have different workflow paths based on how the data comes in.

The sign for the number does not need to be a string, but if you are hoping to display values as +42 instead of 42, you will need a way to represent the +, and a string would be your best bet. If you are displaying your numbers as 42 and -42, you will not need the + or - to be strings, they will automatically be parsed by the workflow.

Prepending a number with + throws an invalid JSON error:
06%20PM 28%20PM

When leaving out the +, the workflow knows the value is positive:
14%20PM

As far as the Javascript goes, it is not obvious to me what your end goal is, so I may need a bit more information before assisting. You have a string of numbers coming in that map to a value, per this chart:

Do the variable names of L1, L0, D9, etc. need to be used in your workflow? Is this device state data? What do your new variables in the function node mean (Par5, Par6, ValueTot)? And finally, what is your end goal for the incoming data?

Thanks!
Julia

To clarify, the mapping in Function Block you see above will present the following:
image

We will try using the Switch Node with the payload channel number addressing: L1 and L2 (depicted in the payload javascript as payload.data.body.ChaNum = payload.data.body.ChaNum1 + payload.data.body.ChaNum2;) The mapping of each L# is payload.data.body.ChaNum#.

The sign of the number will be represented by D9 (depicted in the payload javascript as payload.data.body.Sign)

The data (value) will be represented by D1-D8 (These will be added into the payload javascript as payload.data.body.ValueTot=payload.data.body.Par1+payload.data.body.Par2+payload.data.body.Par3+payload.data.body.Par4+payload.data.body.Par5+payload.data.body.Par6+payload.data.body.Par7+payload.data.body.Par8;) The mapping of each D# is payload.data.body.Par#.

We will not be using the digital input value: IN and it is not mapped

So far the Function (javascript) block is introducing the values from the “payload.data” into the above respective keys:
image

The Sign Key will be either 43 or 42.
The javascript in the function block at the workflow is converting the HEX values arriving from the payload “data” key to DEC in the mapped “keys”
In the above body key example you can see that 2B is converted into 43 (see the “Sign” key).
43 represents a positive sign. 2B(HEX)=43(DEC)="+"(ASCII)
45 represents a negative sign. 2D(HEX)=45(DEC)="-"(ASCII)

How should that be written in the Device State in order to be reflected on the “ValueTot” key in the payload?

image

Thank you for all your help

Hi @tirosh_gutte ,

It sounds like you are looking for a way to set your ValueTot to positive or negative based on the reading from D9. I would recommend making some adjustments to your Function Node to do this in the workflow, but if you would like to see your value displayed on a dashboard as “+42,” for example, you will need to use {{format val formatStr}} with D3 formatting (documentation).

I would use an if statement in your Function Node to decipher if the value is + or -. Keep in mind you will see only a - sign in the workflow, the + sign is removed from positive numbers. Instead of setting Sign to 42 or 43, you could set it to 1 or -1:

var fullString=payload.data.body.data;
var x=parseInt(fullString.substring(4, 6),16);

payload.data.body.ChaNum1=parseInt(fullString.substring(1, 2),16);
payload.data.body.ChaNum2=parseInt(fullString.substring(3, 4),16);
if(x==43){
  payload.data.body.Sign=1;
}else if(x=45){
  payload.data.body.Sign=-1;
}
payload.data.body.Par1=parseInt(fullString.substring(7, 8),16);
payload.data.body.Par2=parseInt(fullString.substring(9, 10),16);
payload.data.body.Par3=parseInt(fullString.substring(11, 12),16);
payload.data.body.Par4=parseInt(fullString.substring(13, 14),16);
payload.data.body.Par5=parseInt(fullString.substring(15, 16),16);
payload.data.body.Par6=parseInt(fullString.substring(17, 18),16);
payload.data.body.Par7=parseInt(fullString.substring(19, 20),16);
payload.data.body.Par8=parseInt(fullString.substring(21, 22),16);
payload.data.body.Digin=parseInt(fullString.substring(23, 24),16);
payload.data.body.ChaNum = payload.data.body.ChaNum1 + payload.data.body.ChaNum2;
payload.data.body.ValueTot=payload.data.body.Sign*(payload.data.body.Par1+payload.data.body.Par2+payload.data.body.Par3+payload.data.body.Par4+payload.data.body.Par5+payload.data.body.Par6+payload.data.body.Par7+payload.data.body.Par8);

Your payload will look like this if Sign is negative, and your ValueTot will also be negative:

If Sign is positive, your ValueTot will also be positive:

To set your device state, you will only have to set the path for your values. You can also use Payload Path instead of Individual Fields if your path holds only the values you have just set.
12%20PM

Let me know how else I can help!
Julia

1 Like

Many Thanks for all your help

We are working next on your recommendation for a Switch Node.

The following was set up

The switch was set up with the following case templates:

Under each case template all device states have the same configuration:
image

How should each device state differentiate from one to another? What is your recommendation?