Registering a sensor in an TTN application via API

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.

Good morning descartes,
In my last attempt, I set the field mask the same as you suggested. The response of all the Post requests shows a success message but the device join to the TTN is not happening. The device tries all the time to find the network.
If you see the given above screenshots, The Post request is unable to write LoRaWAN version, Regional parameters version, and Frequency plan. The Activation mode also shows ABP activation.

Kind regards,
Imran Khan

Did you correct the field masks for the other three requests too?

Yes, I corrected all the four field masks for all the four Post requests.

And the result was …

The device got registered in the TTN but there are many field which are left empty. Network layer is left empty as given below.
ns
OTAA is also not activated and the device is unable to make a join.
The join server settings look fine though but device is unable to join the network. The Join server screenshot is given below.
js

OK, as per other thread, I’m due some light relief today, let me see what I can rustle up!

Thanks :blush:

OK, bit of boring debugging later and I found the culprit by comparing the Python JSON to the PHP JSON:

$data3 = [
‘end_device’ => [
multicate’ => False,

mulitcate should be multicast

and

‘field_mask’ => [
‘path’ => [

path should be paths

Here’s the whole lot, partial reworked as the use of data1, data2 etc is banned under the Geneva Convention:

<?php

$apiKey = "NNSXS.T0P.53CR3T.AP1.K3Y"

$app_id = "descartes-test01v3";
$app_eui = "0000000000000000";

$device_id = "otaa-test-setup-55";
$dev_eui = "9999999999999955";
$app_key = "19BEC34220EBF366070B59F723F234BE";

$idServer = [
	'end_device' => [
		'ids' => [
			'device_id' => $device_id,
			'dev_eui' => $dev_eui,
			'join_eui' => $app_eui
		],
		'join_server_address' => 		'eu1.cloud.thethings.network',
		'network_server_address' => 	'eu1.cloud.thethings.network',
		'application_server_address' => 'eu1.cloud.thethings.network',
		'name' => $device_id
	],
	'field_mask' => [
		'paths' => [
			'join_server_address', 'network_server_address', 'application_server_address', 'ids.dev_eui', 'ids.join_eui', 'name'
		]
	]
];

$joinServer = [
	'end_device' => [
		'ids' => [
			'device_id' => $device_id,
			'dev_eui' => $dev_eui,
			'join_eui' => $app_eui
		],
		'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' => $app_key
			],
		],
	],
	'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'
		],
	]
];

$networkServer = [
	'end_device' => [
		'multicast' => False,
		'supports_join' => True,
		'lorawan_version' => "MAC_V1_0_2",
		'ids' => [
			'device_id' => $device_id,
			'dev_eui' => $dev_eui,
			'join_eui' => $app_eui
		],
		'mac_settings' => [
			'supports_32_bit_f_cnt' => True
		],
		'supports_class_c' => False,
		'supports_class_b' => False,
		'lorawan_phy_version' => "PHY_V1_0_2_REV_B",
		'frequency_plan_id' => "EU_863_870_TTN"
	 ],
	'field_mask' => [
		'paths' => [
			'multicast', 'supports_join', 'lorawan_version',
			'ids.device_id', 'ids.dev_eui', 'ids.join_eui',
			'mac_settings.supports_32_bit_f_cnt',
			'supports_class_c', 'supports_class_b',
			'lorawan_phy_version', 'frequency_plan_id' 
		]
	]
];


$applicationServer = [
	'end_device' => [
		'ids' => [
			'device_id' => $device_id,
			'dev_eui' => $dev_eui,
			'join_eui' => $app_eui
		],
	],
	'field_mask' => [
		'paths' => [
			'ids.device_id', 'ids.dev_eui', 'ids.join_eui'
		]
	]
];
		
$data_end_device= json_encode($idServer);
$data_join_server = json_encode($joinServer);
$data_network_server = json_encode($networkServer);
$data_application_server = json_encode($applicationServer);

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

$authorization = "Authorization: Bearer " . $apiKey;

print($data_end_device."\n");
$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);
print($result1."\n\n\n");
                
print($data_join_server."\n");  
$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);
print($result2."\n\n\n");   

print($data_network_server."\n");                
$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);
print($result3."\n\n\n");

print($data_application_server."\n");  
$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);
print($result4."\n\n\n");

Will do some more tidying up and put this in to a repro

Many Many Thanks :innocent: :innocent:
I will also share my code once it is up and runing.

1 Like

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