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