Ubidots Community

Hexadeciaml variable input from AWS core

Hi, I am looking at using Ubidots instead of our current AWS Timestream/Grafana setup. We currently have multiple Siemens LOGO! PLCs that all send data back to the AWS IoT core. I have successfully started sending data to Ubidots, the problem is that the analogue data that AWS receives is in hexadecimal string format which Ubidots doesn’t seem to be able to process. In the current system I used a Lambda function to convert the analogues to decimal and the digitals to bool before writing to Timestream which is read by Grafana. Is it possible to do this for Ubidots or is there a native way to do it in Ubidots? I couldn’t see a function for it in the synthetic variable code reference.

Here is an example of the current device shadow that AWS recievs

{
  "state": {
    "reported": {
      "AI..4:1-1": "021C",
      "AI..4:2-1": "0000",
      "AI..4:3-1": "0000",
      "AI..4:4-1": "0000",
      "I..1:1-1": "01",
      "I..1:2-1": "00",
      "Q..1:1-1": "00",
      "Q..1:2-1": "00",
      "AM..4:1-1": "0000",
      "AM..4:2-1": "0000"
    }
  }
}

Hello @ICAinternetofthings
Thank you for reaching out to Ubidots.

I’m glad that you now have data coming into Ubidots. The last step would be to use your Decoder in order to, well, decode the Hexadecimal string into an Ubidots usable format. This decoder can be found by goint to the AWS IoT Core Plugin in the Plugins section of your account.

There you could decode the data so that it follows an Ubidots supported JSON, for example:

{
  "temperature": 30,
  "humidity": 40
}

Or in your case:

{
      "AI..4:1-1": 540,
      "AI..4:2-1": 0,
      "AI..4:3-1": 0,
      "AI..4:4-1": 0,
      "I..1:1-1": 1,
      "I..1:2-1": 0,
      "Q..1:1-1": 0,
      "Q..1:2-1": 0,
      "AM..4:1-1": 0,
      "AM..4:2-1": 0
}

Does this make sense?

I’ll be attentive to your response.

Best regards,
Sebastián

Thanks for the reply, I have been looking at the decoder for a little while now and am struggling to see how it works. As I look at it and understand it the payload variable is the data value of each individual data point? If so how come something like just using int() on it doesn’t work? eg:

# This sample code receives a standard Ubidots payload (i.e. {"temperature": 23, "humidity":55}) 
# sent to the AWS IoT topic "$aws/things/<device-label>/shadow/update", assuming your AWS IoT SQL 
# Statement is configured as: 'SELECT topic(3) as device, * as payload FROM "$aws/things/+/shadow/update"'
# You may change the AWS IoT SQL Statement and the decoding function at will.

def decode(args):
    print("Arguments received in decode function", args)
    payload = args.get("payload")
    device_label = args.get("device")

    # Please format your data and make sure this function returns a dictionary like this:
    # {
    #   "device_label":"your_device_label",
    #   "payload": <An Ubidots API v1.6 compatible payload (See https://ubidots.com/docs/hw/#send-data)> 
    # }

    return {"device_label": device_label, "payload": int(payload)}

Output

{
  "error": "int() argument must be a string, a bytes-like object or a number, not 'NoneType'"
}

So from looking at the console output from passing the decoder just one data point it appears that the args dictionary object is

{'device': 'LOGO1', 'payload': {'AI..4:1-1': '021C'}}

I’m sorry but I don’t know python well enough to work out how to extract the value of the payload and convert it to decimal

EDIT:
A large ammount of goolgling later I believe I have cracked it. Using a for loop which saves a converted version into a new python dictionary for each piece of data recieved. Here is the code for anyone who is looking to do it in the future:

# This sample code receives a standard Ubidots payload (i.e. {"temperature": 23, "humidity":55}) 
# sent to the AWS IoT topic "$aws/things/<device-label>/shadow/update", assuming your AWS IoT SQL 
# Statement is configured as: 'SELECT topic(3) as device, * as payload FROM "$aws/things/+/shadow/update"'
# You may change the AWS IoT SQL Statement and the decoding function at will.

def decode(args):
    print("Arguments received in decode function", args)
    payload = args.get("payload")
    device_label = args.get("device")

    intPayload = {}

    for key in payload:
        intPayload[key] = int(payload[key], 16)

    else:

    # Please format your data and make sure this function returns a dictionary like this:
    # {
    #   "device_label":"your_device_label",
    #   "payload": <An Ubidots API v1.6 compatible payload (See https://ubidots.com/docs/hw/#send-data)> 
    # }
        print("final payload is: ", intPayload)

        return {"device_label": device_label, "payload": intPayload}