[SOLVED] Temperature and Humidity data problem on STEM dashboard

Dear All!
I have managed to set up my STEM dashboard with widgets of temperature, humidity, SNR, RSSI values of a Seeed Lora temperatue and humidity sensor. Sensor is sending data to helium network, than from helium console integration comes to STEM. All working except the values of temperature and humidity are strange. Temperature shows 2.72 and humidity shows different values more above 100.
I guess it can be maybe the helium plugin decoder section problem, which shows below
Can you help me please the exact code of the decoding function?
Or any fix for this problem? :slight_smile:
Thanks a lot!

"
import base64

def format_payload(args):

# Log received data for debugging purposes:

print(args)



# See Helium's default JSON schema at: https://developer.helium.com/console/integrations/json-schema

# Get RSSI and SNR variables using Helium hotspots data:

hotspots = args.get('hotspots', [])

ubidots_payload = {}

for i in range(len(hotspots)):

    hotspot_name = hotspots[i].get('name', '')

    rssi = hotspots[i].get('rssi', '')

    snr = hotspots[i].get('snr', '')

    # Use reported timestamp of each hotspot

    ts = int(hotspots[i].get('reported_at', ""))

    

    # Delete no longer needed keys from payload, and assign to context

    hotspots[i].pop('rssi', None)

    hotspots[i].pop('snr', None)

    hotspots[i].pop('reported_at', None)

    hotspot_context = hotspots[i]

    # Format payload for RSSI and SNR

    ubidots_payload['rssi-' + hotspot_name] = {'value': rssi, 'timestamp': ts, 'context': hotspot_context}

    ubidots_payload['snr-' + hotspot_name] = {'value': snr, 'timestamp': ts}



# Get Fcnt and Port variables:

ubidots_payload['fcnt'] = args.get('fcnt', None)

ubidots_payload['port'] = args.get('port', None)



# Get main payload's timestamp

ubidots_payload['timestamp'] = int(args.get('reported_at', ""))



# See if there's a decoded payload already

decoded_payload = args.get('decoded', {}).get('payload', {})

# If no decoded payload was found, then decode here:

if not bool(decoded_payload):

    bytes = base64.b64decode(args.get('payload', ''))

    

    # This a sample decoder for RAK1906 WisBlock Environmental Sensor (https://docs.rakwireless.com/Product-Categories/WisBlock/RAK1906/Overview/#)

    if bytes[0] == 1:

        decoded_payload['temperature'] = (bytes[1] << 8 | (bytes[2])) / 100

        decoded_payload['humidity'] = (bytes[3] << 8 | (bytes[4])) / 100

        decoded_payload['pressure'] = (bytes[8] | (bytes[7] << 8) | (bytes[6] << 16) | (bytes[5] << 24)) / 100

        decoded_payload['gas'] = bytes[12] | (bytes[11] << 8) | (bytes[10] << 16) | (bytes[9] << 24)

    else:

        print("ERROR: Didn't find a valid Wisblock payload")

        # Clean up decoded_payload dict to avoid conflict

        decoded_payload = {}

        

# Join dicts into Ubidots payload

ubidots_payload.update(decoded_payload)

return ubidots_payload"

Good day @vespapierre

Thank you for sharing your question with the community!

Firstly, I suggest you check if you are decoding in the correct way. It is possible that, with the sensor you are using, it’s not necessary to divide the data by 100 or something similar.

If with the above you don’t find the error, could you please send us the documentation or the specific reference of the sensor you are using to be able to identify the problem and help you?

All the best,
Ángela

Hi Ángela,

I am almost sure that the problem will be with the decoding. Mostly because the decoding section shows a RAK sensor code.
The sensor is a Seeed wireless air temperature and humidity sensor, below the link of the product and also the documents of it on almost the bottom area.
I do not know how to modify the decoding section to have the correct data shown. Tried to check the sensor doc, but ???

https://sensecap-docs.seeed.cc/pdf/SenseCAP%20LoRaWAN%20Sensor%20User%20Manual-V1.1.pdf

Hello @vespapierre

After analyzing your situation, we identified that the problem was related to the decoder. Below you will find the correct decoder for the sensor you are using. We just modify the segment where the temperature and humidity frames were decoded, so it would take the corresponding bytes and divide them by 1000 as indicated in the documentation you shared with us. Please try this decoder and let us know if it works for you. However, I inform you that we are working on a Plugin for the integration of Seeed + Helium, we will notify you once we release it so that you can use it instead.

import base64

def format_payload(args):

    # Log received data for debugging purposes:
    print(args)
    
    # See Helium's default JSON schema at: https://developer.helium.com/console/integrations/json-schema

    # Get RSSI and SNR variables using Helium hotspots data:
    hotspots = args.get('hotspots', [])
    ubidots_payload = {}

    for i in range(len(hotspots)):
        hotspot_name = hotspots[i].get('name', '')
        rssi = hotspots[i].get('rssi', '')
        snr = hotspots[i].get('snr', '')

        # Use reported timestamp of each hotspot
        ts = int(hotspots[i].get('reported_at', ""))
        
        # Delete no longer needed keys from payload, and assign to context
        hotspots[i].pop('rssi', None)
        hotspots[i].pop('snr', None)
        hotspots[i].pop('reported_at', None)
        hotspot_context = hotspots[i]

        # Format payload for RSSI and SNR
        ubidots_payload['rssi-' + hotspot_name] = {'value': rssi, 'timestamp': ts, 'context': hotspot_context}
        ubidots_payload['snr-' + hotspot_name] = {'value': snr, 'timestamp': ts}
    
    # Get Fcnt and Port variables:
    ubidots_payload['fcnt'] = args.get('fcnt', None)
    ubidots_payload['port'] = args.get('port', None)
    
    # Get main payload's timestamp
    ubidots_payload['timestamp'] = int(args.get('reported_at', ""))
    
    # See if there's a decoded payload already
    decoded_payload = args.get('decoded', {}).get('payload', {})

    # If no decoded payload was found, then decode here:
    if not bool(decoded_payload):
        bytes = base64.b64decode(args.get('payload', ''))
        
        # This a sample decoder for RAK1906 WisBlock Environmental Sensor (https://docs.rakwireless.com/Product-Categories/WisBlock/RAK1906/Overview/#)
        if bytes[0] == 1:
            decoded_payload['temperature'] = int.from_bytes(bytes[3:7], byteorder="little", signed=True) / 1e3
            decoded_payload['humidity'] = int.from_bytes(bytes[10:14], byteorder="little", signed=True) / 1e3
        else:
            print("ERROR: Didn't find a valid Wisblock payload")
            # Clean up decoded_payload dict to avoid conflict
            decoded_payload = {}
            
    # Join dicts into Ubidots payload
    ubidots_payload.update(decoded_payload)

    return ubidots_payload

All the best,
Ángela

Dear Ángela,
thank you for your help! Now received a package and using your decoding code, it shows correct values!
I have tried also to figure out, how to put the battery information to it, which sent in every 10th package but I am not a great coder. :slight_smile:
It would be nice to have information if you have the Seed + Helium plugin! Thanks a lot!
Would you be so kind to put the battery information to the decoded data laso in the plugin?
Thanks Again!
Best regards,
Gabor

1 Like

Hi @vespapierre

I’m glad to hear that the decoder for the temperature and humidity values ​​has worked for you. For the battery information, it is sent, as you said, every 10 packets, and it differs from the TH values because the frame type is 0700, and is decoded in a similar way as it’s done with the temperature and humidity:

battery_content = int.from_bytes (bytes [: 2], byteorder = "little").

Anyways, this is something that we are going to include in the plugin for devices connected through this integration.

-Ángela

Dear Ángela,
Is it enough to extend the code with:
decoded_payload['battery_content'] = int.from_bytes (bytes [: 2], byteorder = "little", signed=True) / 1e3
after humidity or this is something more difficult?
Hardly waiting for the plugin :wink:

update: I have checked, not enough :slight_smile:

Hi @vespapierre

Indeed, using that line is not the only change that you must make in the code, it is necessary, firstly, to validate if the data package that is arriving contains the information of the battery in order to extract it, otherwise, it will not work. On page 32 of the documentation you shared with us, you will find all the information on how the battery information is sent and how to decode it.

Anyways, we are already working on the plugin so that users do not have to modify the decoders to read the data from these devices.

-Ángela

Thank you! Plugin will be the best result :wink:

1 Like

Hi @vespapierre,

I’m happy to announce that the plugin for the SenseCAP sensor is ready now, please check our new post.

Best,
-Isabel