Avatar billede nemlig Professor
02. maj 2025 - 16:22 Der er 19 kommentarer og
2 løsninger

Curl() og JSON

Hejsa.

Kan nogen forklare mig, hvorfor den første kodestump herunder virker, men ikke den sidste.
I den første benytter jeg ikke JSON, mens jeg gør det i den næste.
I den sidste får jeg fejl på "id"


$data = http_build_query( [
        "id" => $device_id
    ] );

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true );
curl_setopt($curl, CURLOPT_HTTPHEADER, ["Content-Type: application/x-www-form-urlencoded"] );
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);


$data =  [
    "id" => $device_id
] ;

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true );
curl_setopt($curl, CURLOPT_HTTPHEADER, ["Content-Type: application/json"] );
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
Avatar billede arne_v Ekspert
02. maj 2025 - 16:38 #1
Hvad er den præcise fejl?

Understøtter den web service POST af JSON?
Avatar billede nemlig Professor
02. maj 2025 - 17:03 #2
Når jeg benytter metode 1, får jeg dette retur:

{ "isok": true, "data": { "scene_id": "1746182188622" } }

Og når jeg benytter metode 2 med JSON, så får jeg dette retur:

{ "isok": false, "errors": { "wrong_id": "Wrong scene id!" } }

Jeg kan også kalde tjenesten via browserens URL med:
https://shelly.com/servernr/scene/manuel_run?auth_key=abcde&id=1746182188622
Så får jeg disse rå data retur:
{
  "isok": true,
  "data": {
    "scene_id": "1746182188622"
  }
}


og headeren viser:
Access-Control-Allow-Headers: X-CustomHeader,Keep-Alive,User-Agent,Cache-Control,Content-Type,Authorization
Access-Control-Allow-Methods: GET,POST,OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: X-CustomHeader,Keep-Alive,User-Agent,Cache-Control,Content-Type,Authorization
Connection: keep-alive
Content-Type: application/json
Date: Fri, 02 May 2025 12:40:28 GMT
Server: nginx/1.18.0 (Ubuntu)
Transfer-Encoding: chunked

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: da,en-US;q=0.7,en;q=0.3
Connection: keep-alive
Host: shelly-161-eu.shelly.cloud
Priority: u=0, i
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:138.0) Gecko/20100101 Firefox/138.0
Avatar billede arne_v Ekspert
02. maj 2025 - 17:16 #3
Hvilken type er $device_id? int eller string?

Eller omformuleret:

$data =  [
    "id" => $device_id
] ;

json_encode($data)

er det:

{"id":1746182188622}

eller:

{"id":"1746182188622"}

?
Avatar billede nemlig Professor
02. maj 2025 - 18:05 #4
Det er: {"id":"1746182188622"}

Jeg har denne kode:
$device_id = '1746182188622';
$data =  [
    "id"         => $device_id
];


Men sætter jeg $device_id sådan her:
$device_id = 1746182188622;

Så der $data således ud:
{"id":1746182188622}

Men stadig samme fejl.
Avatar billede nemlig Professor
02. maj 2025 - 18:16 #5
Jeg vil nu mene, at type skal være string. Et id kan nemlig også indeholde bogstager ;).
Avatar billede arne_v Ekspert
02. maj 2025 - 18:48 #6
Den skal uden tvivl være string, fordi det bruger de i svar.
Avatar billede arne_v Ekspert
02. maj 2025 - 18:51 #7
Er du sikker på at data struktur er flad?

Altså:

$data =  [
    "id" => $device_id
] ;

og ikke f.eks.:

$data =  [
    "data" => [ "id" => $device_id ]
] ;

?
Avatar billede nemlig Professor
02. maj 2025 - 19:18 #8
Nej, det er jeg ikke sikker på. Jeg ikke fået nogen dokumentation, men blot en URL med parametre - nemlig denne her (auth_key har jeg ændret):

https://shelly-161-eu.shelly.cloud/scene/manual_run?auth_key=....EC723B9D398C748&id=1746179581802

og det virker jo også med metode 1.

Jeg kan fint leve med metode 1 i trådstart, men forstår bare ikke hvorfor den anden metode ikke virker.

Du skal ikke bruge mere tid på det - jeg spørger Shellys support.
Avatar billede nemlig Professor
04. maj 2025 - 09:13 #9
Tak for dine input - jeg er blevet klogere på dem. Jeg troede faktisk, at de rå data der blev sendt til serveren, var de samme med de 2 metoder.

Jeg spørger Shellys support til deres ønskede JSON-dataformat.
Jeg kommunikerer nemlig med andre servere hos Shelly, og her fungerer det fint med JSON.
Avatar billede arne_v Ekspert
04. maj 2025 - 15:05 #10
Min pointe er at selvom man sender de fundamentalt samme data, så kan de godt være organiseret anderledes.

WWW URL encode er grundliggende en flad struktur mens JSON tillader nesting / flere niveauer.

Se denne demo:


<?php
$data = ['a' => 1, 'b' => 2, 'c' => 3];
$www = http_build_query($data);
echo "$www\r\n";
$json = json_encode($data);
echo "$json\r\n";
$json = json_encode($data, JSON_PRETTY_PRINT);
echo "$json\r\n";
$data = ['a' => 1, 'ab' => ['b' => 2, 'c' => 3]];
//$www = http_build_query($data);
//echo "$www\r\n";
$json = json_encode($data);
echo "$json\r\n";
$json = json_encode($data, JSON_PRETTY_PRINT);
echo "$json\r\n";
?>


Den sidste variant af data indeholder grundliggende de samme a, b og c men der er en nested struktur.

En struktur som man ikke kan gætte uden dokumentation.

Stadigvæk spekulation men af mangel på bedre forklaringer ...
Avatar billede nemlig Professor
05. maj 2025 - 14:04 #11
Tak for super gode input - det giver mig en meget bedre forståelse.
Jeg har skrevet til supporten og spurgt til deres krav.
Desværre har de ikke en offentlig API på denne del.
Avatar billede nemlig Professor
05. maj 2025 - 15:22 #12
Nu prøver jeg at kommunikere med serveren og med afsæt i deres offentlig API (det er den samme server, men denne gang er det et andet kald/funktion end trådstart).

"ids" bliver defineret forkert i min kode, da jeg får denne fejl retur - jeg kan heller ikke gennemskue, hvordan CHANNEL medtages (men det er ikke fejlen, da CHANNEL kan udelades).

{
    "isok": false,
    "errors": {
        "validation_errors": "validation_errors"
    },
    "data": {
        "switch.ids": [
            "The switch.ids attribute has errors."
        ]
    },
    "error": "VALIDATION_ERRORS"
}


Uddrag fra API til at kontrollere group-devices:
"switch": {
    "ids": string[];  // List of <ID>_<CHANNEL>  (channel defaults to 0 if not included)
    "command": {
        "on": boolean;          // (required) Output state
        "toggle_after": number;  // After how many seconds, the state should be set to oposite the value of "on"
    };
};


Min kode:
$data = [
    'switch' => [
        'ids' => 'ac15186c96a8,8813bfe0f458', 
        'command' => [
            'on' => true,       
            'toggle_after' => 1 
        ]
    ]
];


API'en ligger her: https://shelly-api-docs.shelly.cloud/cloud-control-api/communication-v2
Og jeg arbejder med afsnittet "Control a device group".

Fair nok, hvis du er ved at være "træt" af mig - så ignorerer du bare dette indlæg ;).
Avatar billede arne_v Ekspert
05. maj 2025 - 15:34 #13
Prøv:

'ids' => 'ac15186c96a8,8813bfe0f458', 
->
'ids' => ['ac15186c96a8,8813bfe0f458'], 

det skal være et array.
Avatar billede nemlig Professor
05. maj 2025 - 15:58 #14
Jeg har prøvet sådan her - er det ikke også dit forslag?:
$data = [
    'switch' => [
        'ids' => ['ac15186c96a8,8813bfe0f458'], 
        'command' => [
            'on' => true,       
            'toggle_after' => 1 
        ]
    ]
];

og får denne fejl:
{
    "failedCommands": []
}
Avatar billede arne_v Ekspert
05. maj 2025 - 16:08 #15
Ja.

Er det en fejl??
Avatar billede nemlig Professor
05. maj 2025 - 16:40 #16
Ja. Jeg har på anden skærm et kontrolpanel over min testopstilling og kan følge med, om det lykkedes at tænde/slukke en device.
Og der sker ingenting.

Jeg lige prøvet med en anden kommando (Tænd lys), og som virker. Lyset tænder og kvitteringen fra serveren er NULL.

Jeg skriver til supporten.

Bare lige en sidste ting..... Kan du gennemskue, hvordan CHANNEL nr. skal tilføjes i koden?
Avatar billede arne_v Ekspert
05. maj 2025 - 16:54 #17
Ups. Jeg havde misset kommaet.

Ikke:

'ids' => ['ac15186c96a8,8813bfe0f458'],

men:

'ids' => ['ac15186c96a8', '8813bfe0f458'],
Avatar billede arne_v Ekspert
05. maj 2025 - 16:55 #18
Channel skal vel være:

'ids' => ['ac15186c96a8_2', '8813bfe0f458_3'],

for channel 2 og 3.
Avatar billede nemlig Professor
05. maj 2025 - 17:18 #19
Tak for din ihærdighed med at hjælpe til løsningen.
Min kode ser sådan her ud:
$data = [
    'switch' => [
        'ids' => ['ac15186c96a8','8813bfe0f458'], 
        'command' => [
            'on' => true,       
            'toggle_after' => 1 
        ]
    ]
];

og kvitteringen:
{
    "failedCommands": {
        "149618404947032_0": "DEVICE_UNSUPPORTED_COMMAND"
    }
}


Jeg har også prøvet med:
'ids' => ['ac15186c96a8_2', '8813bfe0f458_3'],

Og med samme resultat/kvittering.

Endnu engang tusinde tak for hjælpen:).
Avatar billede arne_v Ekspert
05. maj 2025 - 17:25 #20
Hmmm.

Både DEVICE_UNSUPPORTED_COMMAND og hvilke channel numre der er valide kræve rnok lidt viden omkring "dimserne".
Avatar billede nemlig Professor
05. maj 2025 - 19:15 #21
HURRA HURRA - Det virker nu. Den ene dims understøtter ikke SWITCH-kommandoen.
Og du havde fuldstændig ret i metoden til angivelse af CHANNEL.

Denne kode spiller:

$data = [
    'switch' => [
        'ids' => ['ac15186c96a8_1','2cbcbba4accc_1'],
        'command' => [
            'on' => true,       
            'toggle_after' => 5 
        ]
    ]
];
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester