# Payload, Uplink payload formatter & Negative Temperatures

**URL:** <https://www.thethingsnetwork.org/forum/t/payload-uplink-payload-formatter-negative-temperatures/65870>\
**Category:** LMIC\
**Created:** [December 8, 2023, 3:34pm UTC](https://www.thethingsnetwork.org/forum/t/payload-uplink-payload-formatter-negative-temperatures/65870 "2023-12-08T15:34:16Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![paule99](https://www.thethingsnetwork.org/forum/letter_avatar_proxy/v4/letter/p/a4c791/32.png) [@paule99](https://www.thethingsnetwork.org/forum/u/paule99)\
**Post date:** [December 8, 2023, 3:34pm UTC](https://www.thethingsnetwork.org/forum/t/payload-uplink-payload-formatter-negative-temperatures/65870/1 "2023-12-08T15:34:16Z")

</div>

After hours of trial and error modifying LMIC node I’ve managed to get my first temperature sensor (2x DS18B20) node working with TTN albeit postive temperatures work great. However when it comes to negative temperatures I’m stuck… having read several comments here and elsewhere on the net I was actually expecting I might come across this issue but not being a remotely competant coder I’m struggling to get anywhere with it…

I have the LMIC node preparing the uplink payload:

```auto
static volatile uint16_t temp_ = 0;
static volatile uint16_t temp2_ = 0;

uint16_t getTempValue()
{
    
    float temp;
    uint16_t tempInt;

    // Send the command to get temperatures
    ds18b20_sensors.requestTemperatures();
    temp = ds18b20_sensors.getTempCByIndex(0);
    tempInt = temp * 100;

    #ifdef USE_SERIAL
        printSpaces(serial, MESSAGE_INDENT);
        serial.print(F("TEMP value: "));
        Serial.println(temp);
    #endif  

  return tempInt;

}

uint16_t getTemp2Value()
{

    float temp2;
    uint16_t temp2Int;

    // Send the command to get temperatures
    ds18b20_sensors.requestTemperatures();
    temp2 = ds18b20_sensors.getTempCByIndex(1);
    temp2Int = temp2 * 100;

    #ifdef USE_SERIAL
        printSpaces(serial, MESSAGE_INDENT);
        serial.print(F("TEMP 2 value: "));
        Serial.println(temp2);
    #endif  

  return temp2Int;

    
}

void processWork(ostime_t doWorkJobTimeStamp)
{
    // This function is called from the doWorkCallback() 
    // callback function when the doWork job is executed.

    // Uses globals: payloadBuffer and LMIC data structure.

    // This is where the main work is performed like
    // reading sensor and GPS data and schedule uplink
    // messages if anything needs to be transmitted.

    // Skip processWork if using OTAA and still joining.
    if (LMIC.devaddr != 0)
    {
        // Collect input data.

        uint16_t tempValue = getTempValue();
        uint16_t temp2Value = getTemp2Value();
        ostime_t timestamp = os_getTime();

        #ifdef USE_DISPLAY
            // Interval and Counter values are combined on a single row.
            // This allows to keep the 3rd row empty which makes the
            // information better readable on the small display.
            display.clearLine(INTERVAL_ROW);
            display.setCursor(COL_0, INTERVAL_ROW);
            display.print("I:");
            display.print(doWorkIntervalSeconds);
            display.print("s");        
            display.print(" Ctr:");
            display.print(tempValue);
        #endif
        
       /* #ifdef USE_SERIAL
            printEvent(timestamp, "Input data collected", PrintTarget::Serial);
            printSpaces(serial, MESSAGE_INDENT);
            serial.print(F("TEMP value: "));
            serial.println(tempValue);
            printSpaces(serial, MESSAGE_INDENT);
            serial.print(F("TEMP2 value: "));
            serial.println(temp2Value);
        #endif    
        */

        // For simplicity LMIC-node will try to send an uplink
        // message every time processWork() is executed.

        // Schedule uplink message if possible
        if (LMIC.opmode & OP_TXRXPEND)
        {
            // TxRx is currently pending, do not send.
            #ifdef USE_SERIAL
                printEvent(timestamp, "Uplink not scheduled because TxRx pending", PrintTarget::Serial);
            #endif    
            #ifdef USE_DISPLAY
                printEvent(timestamp, "UL not scheduled", PrintTarget::Display);
            #endif
        }
        else
        {
            // Prepare uplink payload.
            uint8_t fPort = 10;
            payloadBuffer[0] = (tempValue >> 8) & 0xff;
            payloadBuffer[1] = tempValue & 0xFF;
            payloadBuffer[2] = (temp2Value >> 8) & 0xff;
            payloadBuffer[3] = temp2Value & 0xFF;
            uint8_t payloadLength = 8;

            scheduleUplink(fPort, payloadBuffer, payloadLength);
        }
    }
}    
 

void processDownlink(ostime_t txCompleteTimestamp, uint8_t fPort, uint8_t* data, uint8_t dataLength)
{
    // This function is called from the onEvent() event handler
    // on EV_TXCOMPLETE when a downlink message was received.

    // Implements a 'reset counter' command that can be sent via a downlink message.
    // To send the reset counter command to the node, send a downlink message
    // (e.g. from the TTN Console) with single byte value resetCmd on port cmdPort.

    const uint8_t cmdPort = 100;
    const uint8_t resetCmd= 0xC0;

    if (fPort == cmdPort && dataLength == 1 && data[0] == resetCmd)
    {
        #ifdef USE_SERIAL
            printSpaces(serial, MESSAGE_INDENT);
            serial.println(F("Reset cmd received"));
        #endif
        ostime_t timestamp = os_getTime();
        //resetCounter();
        printEvent(timestamp, "Counter reset", PrintTarget::All, false);
    }          
}

```

And for the the Uplink Decoder I have:

```auto
function Decoder(bytes, port) {
  
  var temp = ((bytes[0]<<8 | bytes[1]) & 0x3FFF)/ 100;
  var temp2 = ((bytes[2]<<8 | bytes[3]) & 0x3FFF)/ 100;
  
  return {
    Temp: temp,
    Temp2: temp2,
      
  };
}

```

Can anyone suggest how I might go about getting a sensible value for neative temperatures, or at least point me in the right direction…

---

<div class="post-metadata">

**Author:** ![descartes](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/descartes/32/47220_2.png) [@descartes](https://www.thethingsnetwork.org/forum/u/descartes)\
**Post date:** [December 8, 2023, 4:20pm UTC](https://www.thethingsnetwork.org/forum/t/payload-uplink-payload-formatter-negative-temperatures/65870/2 "2023-12-08T16:20:30Z")

</div>

Use an offset, so you add 100 or some such number (so that can go down to -100) to your temp:

> uint16\_t tempInt = (uint16\_t) ((temp + 100.0) \* 100.0);

and at the other end:

> var temp = ( (bytes[0] \<\< 8) + bytes[1]) / 100 ) - 100;

So -10.54C becomes 89.46 becomes 8946 and is reversed to 89.46, the -100 = -10.54.

With an uint16\_t and 2 decimal places (a suspect level of accuracy, 1 dp should be sufficient unless you are NASA), you’ve got 655.35 so you adjust the 100 as appropriate - Alaskan residents may need -150. I have seen a -327.5 before now to split the difference, but there is an ongoing debate at what happens at negative values of Kelvin …

This may help as well: [https://www.thethingsnetwork.org/docs/devices/bytes/](https://www.thethingsnetwork.org/docs/devices/bytes/) - ignore the pink message, this page is still very relevant. This is linked from the v3 docs so worth exploring the payload formatters section there as well.

---

<div class="post-metadata">

**Author:** ![paule99](https://www.thethingsnetwork.org/forum/letter_avatar_proxy/v4/letter/p/a4c791/32.png) [@paule99](https://www.thethingsnetwork.org/forum/u/paule99)\
**Post date:** [December 8, 2023, 4:37pm UTC](https://www.thethingsnetwork.org/forum/t/payload-uplink-payload-formatter-negative-temperatures/65870/3 "2023-12-08T16:37:08Z")

</div>

Thank you Nick, that’s very helpful indeed! I had convinced myself my coding inability was at fault and I was clearly missing some clever coding tricks when the the answer, infact, could be reached with some basic maths 🤦‍♂️

---

<div class="post-metadata">

**Author:** ![Piet\_Pillay](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/piet_pillay/32/35697_2.png) [@Piet\_Pillay](https://www.thethingsnetwork.org/forum/u/Piet_Pillay)\
**Post date:** [December 8, 2023, 4:37pm UTC](https://www.thethingsnetwork.org/forum/t/payload-uplink-payload-formatter-negative-temperatures/65870/4 "2023-12-08T16:37:53Z")

</div>

read this post

but rené post will get you there

> [@Payload Formats \[HowTo\]](https://www.thethingsnetwork.org/forum/t/payload-formats-howto/3441/3):
>
> It’s JavaScript (ECMAScript 5) [indeed](https://github.com/TheThingsNetwork/ttn/blob/master/core/handler/application/application.go). For uplinks: Decoder is a JavaScript function that accepts the payload as byte array and returns an object containing the decoded values. It [gets passed](https://www.thethingsnetwork.org/forum/t/payload-functions/5277/2): First parameter, typically called bytes: the binary payload as an array of numbers. Each number is a byte, 0 to 255 in decimal notation, which is the same as 0x00 to 0xFF in hexadecimal notitation. Second parameter, typically called port: the [port number](https://www.lora-alliance.org/portals/0/specs/LoRaWAN%20Specification%201R0.pdf#page=20) from 1 to 223. Converter is a JavaScript functi…

hope i am quoting the correct one

---

<div class="post-metadata">

**Author:** ![paule99](https://www.thethingsnetwork.org/forum/letter_avatar_proxy/v4/letter/p/a4c791/32.png) [@paule99](https://www.thethingsnetwork.org/forum/u/paule99)\
**Post date:** [December 9, 2023, 12:46pm UTC](https://www.thethingsnetwork.org/forum/t/payload-uplink-payload-formatter-negative-temperatures/65870/5 "2023-12-09T12:46:39Z")

</div>

Thank you both for the replies after a bit more trial and error I’ve got it working as expected. Lesson learnt… don’t get bogged down with the complicated stuff and overlook the simple things 🤦‍♂️

---

<div class="post-metadata">

**Author:** ![descartes](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/descartes/32/47220_2.png) [@descartes](https://www.thethingsnetwork.org/forum/u/descartes)\
**Post date:** [December 9, 2023, 3:44pm UTC](https://www.thethingsnetwork.org/forum/t/payload-uplink-payload-formatter-negative-temperatures/65870/6 "2023-12-09T15:44:50Z")

</div>

> [@paule99](#):
>
> don’t get bogged down with the complicated stuff and overlook the simple things

Or just ask nicely with some evidence of prior effort - **just like you did** - always a pleasure to help people with that next step when they’ve got snow-blind - happens to me all the time!

---

<div class="post-metadata">

**Author:** ![system](https://www.thethingsnetwork.org/forum/uploads/default/original/3X/6/2/6250ea44fd2b0d6259489e1a92748df681e1f970.png) [@system](https://www.thethingsnetwork.org/forum/u/system)\
**Post date:** [December 10, 2023, 3:45pm UTC](https://www.thethingsnetwork.org/forum/t/payload-uplink-payload-formatter-negative-temperatures/65870/7 "2023-12-10T15:45:30Z")

</div>

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.
