Registering a sensor in an TTN application via API

Thank you so much rikietje. Thats work.

You’re welcome!
A very good tip @descartes gave me when I was struggling with this a while ago was to use network page in the browser inspect while registering or deleting devices.

It makes the same API calls and you can see the formats etc.

Good luck!

2 Likes

Hello rikietje,

I have implemented my Post Request in PHP the same as you did in Python. The device registry and network server responses are fine but I am getting errors in joint and application servers post requests.

Response of data1

 {
     “ids”:{
         “device_id”:“boden-07”,
         “application_ids”:{
                          “application_id”:“boden-messung”
                             },
         “dev_eui”:“647FDA0000006FC8”,
         “join_eui”:“647FDA8010000100”
            },
         “created_at”:“2021-05-31T14:35:18.966Z”,
         “updated_at”:“2021-05-31T14:35:18.966Z”,
         “name”:“boden-07”,
         “version_ids”{},
         “network_server_address”:“eu1.cloud.thethings.network”,
         “application_server_address”:“eu1.cloud.thethings.network”,
         “join_server_address”:“eu1.cloud.thethings.network”
            }

Response of data2

{
“code”:3,“message”:“error:pkg/rpcmiddleware/validator:field_mask_paths (forbidden path(s) in field mask)”,
“details” [{
@type”:“type.googleapis.com/ttn.lorawan.v3.ErrorDetails",
“namespace”:“pkg/rpcmiddleware/validator”,
“name”:“field_mask_paths”,
“message_format”:"forbidden
path(s) in field mask”,
“attributes”:{
“forbidden_paths”:[
“boden-07”,
“647FDA0000006FC8”,
“647FDA8010000100”,
“”,
“”,
“”,
“”,
“F8A9C76B75013D14873807577430FF73”
]
},
“correlation_id”:“95c4a05d3f2840b4be1827d6f0fe2c71”,
“code”:3
}
]
}

Response of data3

 {
    “ids”:{
          “device_id”:“boden-07”,
          “application_ids”:{
                “application_id”:“boden-messung”
                },
          “dev_eui”:“647FDA0000006FC8”,
          “join_eui”:“647FDA8010000100”
                },
          “created_at”:“2021-05-31T14:35:19.477465462Z”,
          “updated_at”:“2021-05-31T14:35:19.477465462Z”
                }

Response of data4

 {
        “code”:3,
        “message”:“error:pkg/rpcmiddleware/validator:field_mask_paths (forbidden path(s) in field mask)”,
        “details”:[{
        "@type":“[type.googleapis.com/ttn.lorawan.v3.ErrorDetails",
        “namespace”:“pkg/rpcmiddleware/validator”,
        “name”:“field_mask_paths”,
        “message_format”:"forbidden
        ](http://type.googleapis.com/ttn.lorawan.v3.ErrorDetails%22,
        %22namespace%22:%22pkg/rpcmiddleware/validator%22,
        %22name%22:%22field_mask_paths%22,
        %22message_format%22:%22forbidden) path(s) in field mask”,
        “attributes”:{
        “forbidden_paths”:[
        “boden-07”,
        “647FDA0000006FC8”,
        “647FDA8010000100”
        ]
        },
        “correlation_id”:“2c93bda3a9654c5e987c5fff069d9007”,
        “code”:3
        }
        ]
        }

This is the response to my all four post requests.

$url1 = 'https://eu1.cloud.thethings.network/api/v3/applications/'.$this->appId.'/devices';
$url2 = 'https://eu1.cloud.thethings.network/api/v3/js/applications/'.$this->appId.'/devices';
$url3 = 'https://eu1.cloud.thethings.network/api/v3/ns/applications/'.$this->appId.'/devices';
$url4 = 'https://eu1.cloud.thethings.network/api/v3/as/applications/'.$this->appId.'/devices';

The above are the four URLs.
The four JSON data (data1, data2, data3, data4) are the same as you implemented.
Can you please guide me a bit on why I am getting this forbidden field_mask_paths error. Thank you so much.

Kind regards
Imran Khan

Hello descartes,
can you please check my error and give me a valuable suggestion? Thanks

Yes, but only if you repost that black & green blob as text. If it can be copied & pasted, it should be.

Close, but what was wrong with the formatting options </>

1 Like

Are you using post to register new devices? I got the same error when I was using put

Yes I am using Post to register my device.

Post request response of $data1 is to register the device:

{
    “ids”:{
        “device_id”:“boden-07”,
        “application_ids”:{
                          “application_id”:“boden-messung”
                           },
    “dev_eui”:“647FDA0000006FC8”,
    “join_eui”:“647FDA8010000100”
    },
    “created_at”:“2021-05-31T14:35:18.966Z”,
    “updated_at”:“2021-05-31T14:35:18.966Z”,
    “name”:“boden-07”,
    “version_ids”{},
    “network_server_address”:“eu1.cloud.thethings.network”,
    “application_server_address”:“eu1.cloud.thethings.network”,
    “join_server_address”:“eu1.cloud.thethings.network”
    }

Post request response of $data2 is for the join server:

    {
    “code”:3,“message”:“error:pkg/rpcmiddleware/validator:field_mask_paths (forbidden path(s) in field mask)”,
    “details” [{
    "@type":“[type.googleapis.com/ttn.lorawan.v3.ErrorDetails",
    “namespace”:“pkg/rpcmiddleware/validator”,
    “name”:“field_mask_paths”,
    “message_format”:"forbidden
    ](http://type.googleapis.com/ttn.lorawan.v3.ErrorDetails%22,%22namespace%22:%22pkg/rpcmiddleware/validator%22,%22name%22:%22field_mask_paths%22,%22message_format%22:%22forbidden) path(s) in field mask”,
    “attributes”:{
    “forbidden_paths”:[
    “boden-07”,
    “647FDA0000006FC8”,
    “647FDA8010000100”,
    "",
    "",
    "",
    "",
    “F8A9C76B75013D14873807577430FF73”
    ]
    },
    “correlation_id”:“95c4a05d3f2840b4be1827d6f0fe2c71”,
    “code”:3
    }
    ]
    }

Post request response of $data3 is for the network server:

{
“ids”:{
“device_id”:“boden-07”,
“application_ids”:{
“application_id”:“boden-messung”
},
“dev_eui”:“647FDA0000006FC8”,
“join_eui”:“647FDA8010000100”
},
“created_at”:“2021-05-31T14:35:19.477465462Z”,
“updated_at”:“2021-05-31T14:35:19.477465462Z”
}

Post request response of $data4 is for the application server:

{
    “code”:3,
    “message”:“error:pkg/rpcmiddleware/validator:field_mask_paths (forbidden path(s) in field mask)”,
    “details”:[{
    "@type":“[type.googleapis.com/ttn.lorawan.v3.ErrorDetails",
    “namespace”:“pkg/rpcmiddleware/validator”,
    “name”:“field_mask_paths”,
    “message_format”:"forbidden
    ](http://type.googleapis.com/ttn.lorawan.v3.ErrorDetails%22,
    %22namespace%22:%22pkg/rpcmiddleware/validator%22,
    %22name%22:%22field_mask_paths%22,
    %22message_format%22:%22forbidden) path(s) in field mask”,
    “attributes”:{
    “forbidden_paths”:[
    “boden-07”,
    “647FDA0000006FC8”,
    “647FDA8010000100”
    ]
    },
    “correlation_id”:“2c93bda3a9654c5e987c5fff069d9007”,
    “code”:3
    }
    ]
    }

These are all four responses to my four Post requests. I hope now it will be more readable and clear to you. Thank you so much.

Really? I mean really?

Just edit your original post and format the log sections using the </> tool on the editor box please. The bold headings are nice, but it’s the computer data we ask people to format.

And then read the how to format your post topic please.

Sorry, it was my mistake. Now I tried my best to format the post according to your expectations. Thanks.

My expectations are the same as everyone else’s and were written down in the post on how to format posts with the link I gave you and I told you about the </> - it really helps if people read answers. We are volunteers here, we aren’t paid to wade through dense blocks of text that don’t provide structure.

Anyway, in the meanwhile, the Python works (as expected) so there will be something about your PHP conversion. I’m somewhat scared to ask you to post your code, but, using the power you have gained with the </> tool, can you show us your PHP please.

PHP does not understand JSON format so what I did is, I packed everything in array and converted it into json. The arrays of all four data are given below. In the field_mask field, I inserted directly the value of the variables.

                $data1 = [
                       'end_device' => [
                                   'ids' => [
                                       'device_id' => $this->deviceId,
                                        'dev_eui' => $this->devEui,
                                        'join_eui' => $this->appEui
                                        ],
                            'join_server_address' => 'eu1.cloud.thethings.network',
                            'network_server_address' => 'eu1.cloud.thethings.network',
                            'application_server_address' => 'eu1.cloud.thethings.network',
                            'name' => $this->deviceId
                                ],
                         'field_mask' => [
                                 'paths' => [
                                        'eu1.cloud.thethings.network',
                                        'eu1.cloud.thethings.network',
                                        'eu1.cloud.thethings.network',
                                        $this->devEui,
                                        $this->appEui,
                                        $this->deviceId
                                        ],
                                 ],
                            ];


              $data2 = [
                            'end_device' => [
                                        'ids' => [
                                                'device_id' => $this->deviceId,
                                                'dev_eui' => $this->devEui,
                                                'join_eui' => $this->appEui
                                                ],
                                'network_server_address' => 'eu1.cloud.thethings.network',
                                'application_server_address' => 'eu1.cloud.thethings.network',
                                'network_server_kek_label' => '',
                                'application_server_kek_label' => '',
                                'application_server_id' => '',
                                'net_id' => Null,
                                'root_keys' => [
                                          'app_key' => [
                                                  'key' => $this->appKey
                                        ],
                                    ],
                                    ],
                                'field_mask' => [
                                        'paths' => [
                                                 $this->deviceId,
                                                 $this->devEui,
                                                 $this->appEui,
                                                '',
                                                '',
                                                '',
                                                Null,
                                                $this->appKey
                                             ],
                                        ],
                                ];



                 $data3 = [
                        'end_device' => [
                                    'multicate' => False,
                                    'supports_join' => True,
                                    'lorawan_version' => $this->loraVersion,
                                    'ids' => [
                                          'device_id' => $this->deviceId,
                                           'dev_eui' => $this->devEui,
                                           'join_eui' => $this->appEui
                                        ],
                        'mac_settings' => [
                                        'supports_32_bit_f_cnt' => True
                                ],
                        'supports_class_c' => False,
                        'supports_class_b' => False,
                        'lorawan_phy_version' => $this->phyVersion,
                        'frequency_plan_id' => $this->frequencyPlan,
                         ],
                         'field_mask' => [
                                  'path' => [
                                         False,
                                         True,
                                         $this->loraVersion,
                                         $this->deviceId,
                                         $this->devEui,
                                         $this->appEui,
                                         True,
                                         False,
                                         False,
                                         $this->phyVersion,
                                         $this->frequencyPlan
                                        ],
                                    ],
                            ];

      

             $data4 = [
                      'end_device' => [
                                'ids' => [
                                    'device_id' => $this->deviceId,
                                    'dev_eui' => $this->devEui,
                                    'join_eui' => $this->appEui
                                ],
                                ],
                        'field_mask' => [
                                 'paths' => [
                                        $this->deviceId,
                                        $this->devEui,
                                        $this->appEui
                                    ],
                            ],
                        ];

I converted all of them into JSON using json_encode()

$data_end_device= json_encode($data1);
$data_join_server = json_encode($data2);
$data_network_server = json_encode($data3);
$data_application_server = json_encode($data4);

I am using bearer authentication to make the PHP Post request.

$url1 = 'https://eu1.cloud.thethings.network/api/v3/applications/'.$this->appId.'/devices';
$url2 = 'https://eu1.cloud.thethings.network/api/v3/js/applications/'.$this->appId.'/devices';
$url3 = 'https://eu1.cloud.thethings.network/api/v3/ns/applications/'.$this->appId.'/devices';
$url4 = 'https://eu1.cloud.thethings.network/api/v3/as/applications/'.$this->appId.'/devices';

 $app_api = Application::where('app_id', $this->appId)->first()->api_key;
 
$authorization = "Authorization: Bearer " . $app_api;

$ch1 = curl_init($url1);
curl_setopt($ch1, CURLOPT_HTTPHEADER, array($authorization, 'Content-Type: application/json'));
curl_setopt($ch1, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch1, CURLOPT_POSTFIELDS, $data_end_device);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch1, CURLOPT_FOLLOWLOCATION, 1);
$result1 = curl_exec($ch1);
curl_close($ch1);
                

$ch2 = curl_init($url2);
curl_setopt($ch2, CURLOPT_HTTPHEADER, array($authorization, 'Content-Type: application/json'));
curl_setopt($ch2, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch2, CURLOPT_POSTFIELDS, $data_join_server);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_FOLLOWLOCATION, 1);
$result2 = curl_exec($ch2);
curl_close($ch2);

                
$ch3 = curl_init($url3);
curl_setopt($ch3, CURLOPT_HTTPHEADER, array($authorization, 'Content-Type: application/json'));
curl_setopt($ch3, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch3, CURLOPT_POSTFIELDS, $data_network_server);
curl_setopt($ch3, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch3, CURLOPT_FOLLOWLOCATION, 1);
$result3 = curl_exec($ch3);
curl_close($ch3);

$ch4 = curl_init($url4);
curl_setopt($ch4, CURLOPT_HTTPHEADER, array($authorization, 'Content-Type: application/json'));
curl_setopt($ch4, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch4, CURLOPT_POSTFIELDS, $data_application_server);
curl_setopt($ch4, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch4, CURLOPT_FOLLOWLOCATION, 1);
$result4 = curl_exec($ch4);
curl_close($ch4);

Ta da!!!

OK, will have a run at this later this morning after I’ve unbroken my iMac after a bad OS install test yesterday.

Many thanks :grinning:

Good morning descartes,
I have solved my last issue. Now all of my four Post requests went fine and got positive responses. I actually provided the wrong parameters in the field_mask field. Instead of providing values in the field_mask, I provided the fields that should be used and it worked fine. As an example, I am providing one of my data below.

               $data2 = [
                    'end_device' => [
                                'ids' => [
                                        'device_id' => $this->deviceId,
                                        'dev_eui' => $this->devEui,
                                        'join_eui' => $this->appEui
                                        ],
                        'network_server_address' => 'eu1.cloud.thethings.network',
                        'application_server_address' => 'eu1.cloud.thethings.network',
                        'network_server_kek_label' => '',
                        'application_server_kek_label' => '',
                        'application_server_id' => '',
                        'net_id' => Null,
                        'root_keys' => [
                                  'app_key' => [
                                          'key' => $this->appKey
                                ],
                            ],
                            ],
                        'field_mask' => [
                                'paths' => [
                                    'network_server_address', 
                                    'application_server_address', 
                                    'ids.device_id', 
                                    'ids.dev_eui',
                                    'ids.join_eui', 
                                    'network_server_kek_label', 
                                    'application_server_kek_label',
                                    'application_server_id',
                                    'net_id', 
                                    'root_keys.app_key.key'
                                     ],
                                ],
                        ];

Below is the response of my first Post request.

{"
 ids":{
 "device_id":"boden-07",
 "application_ids":{
 "application_id":"boden-messung"
 },
 "dev_eui":"647FDA0600006FC8",
 "join_eui":"647FDA3010000100"
 },
 "created_at":"2021-06-02T08:42:24.061Z",
 "updated_at":"2021-06-02T08:42:24.061Z",
 "name":"boden-07",
 "version_ids":{},
 "network_server_address":"eu1.cloud.thethings.network",
 "application_server_address":"eu1.cloud.thethings.network",
 "join_server_address":"eu1.cloud.thethings.network"
 } 

Below is the response of the second Post

{
    "ids":{
    "device_id":"boden-07",
    "application_ids":{
    "application_id":"boden-messung"
    },
    "dev_eui":"647FDA0000002FC8",
    "join_eui":"607FDA8010000100"
    },
    "created_at":"2021-06-02T08:42:24.200521997Z",
    "updated_at":"2021-06-02T08:42:24.200521997Z",
    "network_server_address":"eu1.cloud.thethings.network",
    "application_server_address":"eu1.cloud.thethings.network",
    "root_keys":{
    "app_key":{
    "key":"F2A3C66B75013D14873807577430FF73"
    }
    }
    }

Below is the response of my third Post request

{
"ids":{
"device_id":"boden-07",
"application_ids":{
"application_id":"boden-messung"
},
"dev_eui":"607FDA0000003FC8",
"join_eui":"649FDA2010000100"
},
"created_at":"2021-06-02T08:42:24.327125687Z",
"updated_at":"2021-06-02T08:42:24.327125687Z"
}

Below is the response of my fourth Post request

{
"ids":{
"device_id":"boden-07",
"application_ids":{
"application_id":"boden-messung"
},
"dev_eui":"607FDA0000003FC8",
"join_eui":"649FDA2010000100"
},
"created_at":"2021-06-02T08:42:24.464742974Z",
"updated_at":"2021-06-02T08:42:24.464742974Z"
}

Now I have another issue. In my End Devices → General Settings, there is a field “Join Server address”, which is left empty as below.
jserror

The Network layer is also left empty as below.

ns

Application layer is unexpandable and the Join Settings are given as below.

js

Can we please guide me a bit, where am I making mistakes or what might be wrong? Thank you so much. My device does not join the network.

Kind regards
Imran Khan

Not forgotten you, at worst can look at it after supper

Good morning descartes,

Can you please have a look today at my code and give me a useful tip to solve my issue?

Kind regards
Imran Khan

Not sure if it will be today - in the end I had to backup 5Tb so I could re-install from a clean disk - but I’ll leave it open on my desktop to remind me.

Ah, hang on, whilst copying & pasting this over so I can have this open I see that you have replaced the field mask static values with variables for no apparent reason - I have no idea what effect this will have but it’s not in the Python (which I’ve confirmed works) and it’s not in the documentation either, although that’s not explicitly shown but there is an example here:

https://www.thethingsindustries.com/docs/getting-started/api/#multi-step-actions

So,:

'field_mask' => [
	 'paths' => [
			'eu1.cloud.thethings.network',
			'eu1.cloud.thethings.network',
			'eu1.cloud.thethings.network',
			$this->devEui,
			$this->appEui,
			$this->deviceId
			],
	 ],
];

should be

'field_mask' => [
	 'paths' => [

  "join_server_address", 
  "network_server_address", 
  "application_server_address", 
  "description", 
  "name", 
  "ids.dev_eui", 
  "ids.join_eui"

	 ],
];

But I’m yet to figure out the details of the field mask, I suspect that’s what it’s being told to return. But certainly giving it data rather than field names isn’t going to help.