Hello les amis,
Soyons clair , je ne connais RIEN de RIEN au PHP mais l'IA Claude d'Anthropic dans sa version de mars 2026 gratuite manifestement oui!!!
Alors voilà un script
corrigé a minima avec moi

: état et actions fonctionnent à nouveau, pour mes deux robots. Mes IPs et token sont inchangés.
Créez un fichier "Xiaomivacuumapp.php"
Aller dans Configuration / Ajouter ou supprimer un périphérique / Store eedomus / Gérer les scripts sur
Sélectionner" Xiaomivacuumapp.php" puis Envoyer
Enjoy et merci Claude bis!
----Xiaomivacuumapp.php----
<?php
# Copyright (C) 2018-2019 @Darboo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with This program. If not, see <http://www.gnu.org/licenses/>.
#
# Version : v1.5
# ChangeLog:
# 1.0 : version initiale
# 1.1 : Ajout commande status pour récupérer l'état
# 1.2 : Ajout Commande custom
# 1.5 : Ajout du retour pour les commandes custom
# Fix global $commandId manquant dans sdk_sendCommandRetrieve
# Fix null-bytes non retirés après mcrypt_decrypt (garbage XML)
# Fix initialisation robuste de $commandId
$adressIp = getArg('ip');
$token = getArg('token');
$action = getArg('action');
$adressPort = 54321;
// Convert hexstring (ex: "6A45D63E") in bin string
function sdk_hexbin($str){
$result = "";
for ($i=0; $i< strlen($str)/2; $i++){
$result.= chr(hexdec(substr($str,2*$i,2)));
}
return $result;
}
// Convert binstring in hexstring
function sdk_binhex($str){
$result = "";
for ($i=0; $i< strlen($str); $i++){
$result.= sprintf("%02x",ord(substr($str,$i,1)));
}
return $result;
}
// Transform binstring to display it
function sdk_bindisplay($str){
$result = "";
for ($i=0; $i< strlen($str); $i++){
$val = ord(substr($str,$i,1));
if (($val < 32) || ($val > 126))
$result.= sprintf("\x%02x",$val);
elseif (substr($str,$i,1) == '\\')
$result.= '\\\\';
elseif (substr($str,$i,1) == '\'')
$result.= '\\\'';
else
$result.= substr($str,$i,1);
}
return $result;
}
// Encrypt the data string
function sdk_encrypt($plaintext, $token){
$block = 16;
$pad = $block - (strlen($plaintext) % $block);
$padded_plaintext = $plaintext;
$padded_plaintext .= str_repeat(chr($pad), $pad);
$key = md5($token, true);
$iv = md5($key.$token, true);
// FIX: mcrypt ajoute son propre null-padding si la taille n'est pas un multiple de 16.
// On s'assure que $padded_plaintext est déjà un multiple exact → mcrypt ne touche plus au padding.
// On utilise MCRYPT_RIJNDAEL_128 avec un plaintext dont la taille est déjà alignée.
$result = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $padded_plaintext, MCRYPT_MODE_CBC, $iv);
return $result;
}
// Remove PKCS7 padding after decryption
function sdk_unpad($str){
$pad = ord(substr($str, -1));
if ($pad < 1 || $pad > 16) return $str;
return substr($str, 0, strlen($str) - $pad);
}
// Send a command
function sdk_sendCommand($method, $params = "[]"){
global $deviceId;
global $commandId;
global $token;
global $differenceTimestamp;
// Construct Data
$commandId++;
$plaintext = '{"id": '.$commandId.', "method": "'.$method.'", "params": '.$params.'}'.chr(0);
// Do encryption
$ciphertext = sdk_encrypt($plaintext, $token);
// Contruct Message
$length = strlen($ciphertext) + 32;
$message = sdk_hexbin("2131"); // Magic Number
$message .= sdk_hexbin(sprintf("%04x",$length)); // length
$message .= sdk_hexbin("00000000"); //unknown
$message .= $deviceId; //deviceid
$message .= sdk_hexbin(sprintf("%08x",time() + $differenceTimestamp));; //stamp
// Calculate checksum
$checksumPayload = $message;
$checksumPayload .= $token;
$checksumPayload .= $ciphertext;
$checksum = md5($checksumPayload, true);
// Finish construct message
$message .= $checksum;
$message .= $ciphertext;
// Send Message
return sdk_sendUDPRequest($message);
}
// Send command with retry if it false and increment id
function sdk_sendCommandRetrieve($method, $params = "[]"){
global $commandId; // FIX: sans ce global, les increments n'affectaient pas le vrai compteur
$receiveData = sdk_sendCommand($method, $params);
if ($receiveData == ''){
$commandId+=2;
$receiveData = sdk_sendCommand($method, $params);
if ($receiveData == ''){
$commandId+=9;
$receiveData = sdk_sendCommand($method, $params);
if ($receiveData == ''){
$commandId+=49;
$receiveData = sdk_sendCommand($method, $params);
if ($receiveData == ''){
$commandId+=99;
$receiveData = sdk_sendCommand($method, $params);
}
}
}
}
return $receiveData;
}
// Send discovery request
function sdk_sendDiscovery(){
return sdk_sendUDPRequest(sdk_hexbin('21310020ffffffffffffffffffffffffffffffffffffffffffffffffffffffff'));
}
// Send UDP request
function sdk_sendUDPRequest($data){
global $adressIp;
global $adressPort;
//Create a UDP socket
if(!($sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Couldn't create socket: [$errorcode] $errormsg \n");
}
// Not available
// socket_set_timeout($sock,10);
socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>5, "usec"=>0));
socket_set_option($sock, SOL_SOCKET, SO_SNDTIMEO, array("sec"=>5, "usec"=>0));
//open socket
$result = socket_connect($sock, $adressIp , $adressPort);
if ($result === false) {
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("socket_connect() failed: [$errorcode] $errormsg \n");
}
socket_write($sock, $data, strlen($data));
$buf = '';
$bytes = socket_recvfrom($sock, $buf, 1024, MSG_WAITALL, $name, $port);
socket_close($sock);
if ($bytes != ''){
return $buf;
}else{
return false;
}
}
// Proccess a command request
function sdk_doCommand($method, $params = "[]"){
global $deviceId;
global $differenceTimestamp;
global $token;
//Do Discovery
$receiveData = sdk_sendDiscovery();
$deviceId = substr($receiveData,8,4);
if ($deviceId != ''){
$deviceTimestamp = hexdec(sdk_binhex(substr($receiveData,12,4)));
$differenceTimestamp = $deviceTimestamp - time();
//Send Action
$receiveData = sdk_sendCommandRetrieve($method, $params);
// Keep only message bytes, to improve : check others bytes
$receiveData = substr($receiveData,32);
$key = md5($token, true);
$iv = md5($key.$token, true);
$result = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $receiveData, MCRYPT_MODE_CBC, $iv);
// FIX: mcrypt ajoute des null-bytes en fin de buffer → on coupe au premier \0 après le JSON
$nullPos = strpos($result, "\x00");
if ($nullPos !== false) $result = substr($result, 0, $nullPos);
return $result;
}
}
$token = sdk_hexbin($token);
$commandId = intval(loadVariable('commandId')); // FIX: évite null/false
if ($commandId <= 0) $commandId = 1;
if ($action == 'start'){
sdk_doCommand("app_start");
}elseif ($action == 'pause'){
sdk_doCommand("app_pause");
}elseif ($action == 'home'){
sdk_doCommand("app_pause");
sdk_doCommand("app_charge");
}elseif ($action == 'zone'){
$zones = getArg('zones'); // ex [[x1,y1,x2,y2, iterations],[x1,y1,x2,y2, iterations]]
sdk_doCommand("app_zoned_clean", $zones);
}elseif ($action == 'findme'){
sdk_doCommand("find_me");
}elseif ($action == 'playsound'){
sdk_doCommand("test_sound_volume");
}elseif ($action == 'status'){
$result = sdk_doCommand("get_status");
echo jsonToXML($result);
}elseif ($action == 'custom'){
$command = getArg('command'); // ex [[x1,y1,x2,y2, iterations],[x1,y1,x2,y2, iterations]]
$params = getArg('params'); // ex [[x1,y1,x2,y2, iterations],[x1,y1,x2,y2, iterations]]
if ($params == ''){
$result = sdk_doCommand($command);
}else{
$result = sdk_doCommand($command, $params);
}
echo jsonToXML($result);
}elseif ($action == 'findid'){
$startId = getArg('start', false);
if (!empty($startId))
$commandId = $startId;
$receiveData = sdk_sendDiscovery();
$deviceId = substr($receiveData,8,4);
$deviceTimestamp = hexdec(sdk_binhex(substr($receiveData,12,4)));
$differenceTimestamp = $deviceTimestamp - time();
//Send Action
$receiveData = '';
$nbtry = 0;
while (($receiveData == '') && ($nbtry < 20)){
if ($nbtry != 0)
$commandId += 20;
$receiveData = sdk_sendCommand("test_sound_volume");
$nbtry++;
}
if ($receiveData == ''){
echo 'id not found';
}else{
echo 'id found:'.$commandId;
}
}elseif ($action == 'resetid'){
$commandId = 0;
}
saveVariable('commandId', $commandId);
?>