Thingsboard CE shared Attribute send to lora device

I want to send from thingsboard CE shared attribute to lora device. does anyone know how to do that? I tried thingsboard using rules and mqtt. But did not work. Can anyone help me further?

This is not implemented / supported.

Thanks for the quick information.

I setup an http integration both in Loraserver and in TB and I send the downlink commands to the nodes using REST API in TB.
I’m using Thingsboard PE, so I don’t know if this way is also supported by TB-CE.
Gianluigi

Have you made a guide to this somewhere? Or would you like to explain/show how it was done?

I try to describe the main steps:

  • In TB create the payload that you want to send to the LoraServer downlink queue;
    For this I used a transformation node;
    The resulting payload is something like this:
    CreateDownPayload
    Note that it contains the downlink msg payload to be send to the endnode converted to base64 (“data” in the below picture)
  • In order to send it to LoraServer, connect the output of this transformation node to the input of a rest api call rule node configured like this:

    Of course use your LoraServer IP address and your JWT token.
    I don’t know if this is the best way, but till now it works …

[gigi130358] Thank you for your support. But i can not try it so, in CE Version external connection not possible.
I try it with your information to connect over Rule chain.
Georg

I also tried the same. It shows “internal server error”. Could you please tell me by which method you generated the JWT Token for accessing LoRa server from Thingsboard?

Thank you in advance.

The last post in https://github.com/brocaar/loraserver/issues/197 could help you to generate the JWT Token.
Gianluigi

Hello @gigi130358,

I am trying to follow your approach. I’ve updated External-rest API call node. How did you add downlink msg payload in Transformation-script? I tried to put it in the RPC method params of the control widget of the dashboard. I get the following error at external-rest API node (debug events).

org.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request: [{“error”:“f_port must be \u003e 0”,“code”:3,“message”:“f_port must be \u003e 0”,“details”:}]

Did you use any control widget in your implementation? Can you share the transformation script? Did you do anything at the function Encode(fPort, obj, variables) of Device-Profile CODEC in the Chirpstack?

Thank you.

I’m sorry but I have been retired for a couple of years so I am unable to retrieve the information you requested

I did exactly you showed in the screenshot. I’m getting org.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request: [{"error":"devEUI: encoding/hex: invalid byte: U+0052 'R'","code":3,"message":"devEUI: encoding/hex: invalid byte: U+0052 'R'","details":[]}] at the rest API call node. Did you experienced such problems?

Here are some info
rule chain

create cmd payload:
var cmd = hexToBase64//(“81FFFFFFFF00184523000003844524000003844533000003844534000003848C”);
(“81FFFFFFFF001845230000012C45240000012C45330000012C45340000012CF4”); // 5 min

var deviceQueueItem = {
confirmed: true,
data:cmd ,
devEUI: metadata.deviceName,
fCnt: 0,
fPort: 223,
jsonObject:""
}
msg = {
deviceQueueItem: deviceQueueItem
}
return {msg: msg, metadata: metadata, msgType: msgType};

function hexToBase64(hexstring) {
return btoa(hexstring.match(/\w{2}/g).map(function(a) {
return String.fromCharCode(parseInt(a, 16));
}).join(""));
}

hello,

I already solved the problem and I can send downlink from thingsboard CE.

I will share with you how I did it for those who need to use this integration.

I can’t upload the file, so I leave the code, save it in .json and then import it as a new rule chain

{
  "ruleChain": {
    "additionalInfo": {
      "description": ""
    },
    "name": "queue-downlink",
    "type": "CORE",
    "firstRuleNodeId": null,
    "root": false,
    "debugMode": true,
    "configuration": null
  },
  "metadata": {
    "firstNodeIndex": 3,
    "nodes": [
      {
        "additionalInfo": {
          "description": "",
          "layoutX": 430,
          "layoutY": 357
        },
        "type": "org.thingsboard.rule.engine.transform.TbTransformMsgNode",
        "name": "Create cmd payload",
        "debugMode": true,
        "singletonMode": false,
        "queueName": null,
        "configurationVersion": 0,
        "configuration": {
          "scriptLang": "JS",
          "jsScript": "\nvar cmd = hexToBase64(\"0000\"); // 5 min\n\nvar queueItem = {\n    confirmed: true,\n    data: cmd,\n    fPort: 1,\n    isEncrypted: true,\n    isPending: true\n\n}\n\nmsg = {\n    queueItem: queueItem\n}\nreturn {msg: msg, metadata: metadata, msgType: msgType};\n\nfunction hexToBase64(hexstring) {\n    var binary = '';\n    for (var i = 0; i < hexstring.length; i += 2) {\n        binary += String.fromCharCode(parseInt(hexstring.substr(i, 2), 16));\n    }\n    return base64Encode(binary);\n}\n\nfunction base64Encode(str) {\n    var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n    var encoded = '';\n    var i = 0;\n\n    while (i < str.length) {\n        var char1 = str.charCodeAt(i++);\n        var char2 = i < str.length ? str.charCodeAt(i++) : Number.NaN; // Not sure if the index \n        var char3 = i < str.length ? str.charCodeAt(i++) : Number.NaN; // checks are needed here\n\n        encoded += chars.charAt(char1 >> 2);\n        encoded += chars.charAt(((char1 & 3) << 4) | (char2 >> 4));\n        if (isNaN(char2)) {\n            encoded += '==';\n        } else {\n            encoded += chars.charAt(((char2 & 15) << 2) | (char3 >> 6));\n            encoded += isNaN(char3) ? '=' : chars.charAt(char3 & 63);\n        }\n    }\n\n    return encoded;\n}\n",
          "tbelScript": "return {msg: msg, metadata: metadata, msgType: msgType};"
        }
      },
      {
        "additionalInfo": {
          "description": "",
          "layoutX": 726,
          "layoutY": 135
        },
        "type": "org.thingsboard.rule.engine.rest.TbRestApiCallNode",
        "name": "Chirpstack V4",
        "debugMode": true,
        "singletonMode": false,
        "queueName": null,
        "configurationVersion": 1,
        "configuration": {
          "restEndpointUrlPattern": "http://192.168.50.184:8090/api/devices/4b7709bb66035c29/queue",
          "requestMethod": "POST",
          "useSimpleClientHttpFactory": false,
          "parseToPlainText": false,
          "ignoreRequestBody": false,
          "enableProxy": false,
          "useSystemProxyProperties": false,
          "proxyScheme": null,
          "proxyHost": null,
          "proxyPort": 0,
          "proxyUser": null,
          "proxyPassword": null,
          "readTimeoutMs": 0,
          "maxParallelRequestsCount": 0,
          "headers": {
            "Grpc-Metadata-Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJjaGlycHN0YWNrIiwiaXNzIjoiY2hpcnBzdGFjayIsInN1YiI6IjI3YzFjNDIwLWZlY2ItNDBlMS1iZWQzLTgyYmE1NTUxM2JkNyIsInR5cCI6ImtleSJ9.NEztPEw3Lz9ADxPhGwQ7yIk_GbaPtvedLWfAKC6MC5A",
            "Content-Type": "application/json",
            "accept": "application/json"
          },
          "useRedisQueueForMsgPersistence": false,
          "trimQueue": null,
          "maxQueueSize": null,
          "credentials": {
            "type": "anonymous"
          }
        }
      },
      {
        "additionalInfo": {
          "description": "",
          "layoutX": 717,
          "layoutY": 500
        },
        "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
        "name": "Save to DB",
        "debugMode": true,
        "singletonMode": false,
        "queueName": null,
        "configurationVersion": 0,
        "configuration": {
          "defaultTTL": 0,
          "skipLatestPersistence": false,
          "useServerTs": false
        }
      },
      {
        "additionalInfo": {
          "description": "",
          "layoutX": 141,
          "layoutY": 462
        },
        "type": "org.thingsboard.rule.engine.filter.TbJsFilterNode",
        "name": "demo",
        "debugMode": false,
        "singletonMode": false,
        "queueName": null,
        "configurationVersion": 0,
        "configuration": {
          "scriptLang": "TBEL",
          "jsScript": "return msg.temperature > 20;",
          "tbelScript": "return msg.temperature > 20;"
        }
      }
    ],
    "connections": [
      {
        "fromIndex": 0,
        "toIndex": 1,
        "type": "Success"
      },
      {
        "fromIndex": 0,
        "toIndex": 2,
        "type": "Failure"
      },
      {
        "fromIndex": 3,
        "toIndex": 0,
        "type": "True"
      },
      {
        "fromIndex": 3,
        "toIndex": 2,
        "type": "False"
      }
    ],
    "ruleChainConnections": null
  }
}

What I did to test that it worked is to send a temperature message and if it was May 20, send the script (Create cmd payload) that is the attached code.

I hope this helps you and if you don’t understand something, just send the consulate.