Matlab/Simulink : Comment recevoir des commandes MATLAB via une requête HTTP GET
Cet exemple montre comment recevoir des commandes MATLAB via une requête HTTP GET.
Dans notre exemple précédent Serveur de commandes TCP/IP Matlab sans aucune toolbox nous avons montré comment créer un serveur TCP/IP dans MATLAB sans recourir aux commandes exclusives d’une toolbox. Cependant, même lorsqu’il est exécuté en utilisant un Timer Matlab, il bloquera complètement l’interface graphique car Matlab fonctionne de manière intrinsèquement monothreadée.
Dans cet exemple, nous utiliserons une stratégie différente : Matlab lui-même est commandé via un Timer pour émettre périodiquement une requête HTTP vers un serveur Web externe. Le serveur web répondra alors avec une commande à exécuter dans Matlab.
Dans cet exemple, il n’y a aucun retour sur la sortie de la commande !
Fonction de requête MATLAB principale
function http_command()
% Fonction pour exécuter les commandes MATLAB reçues via HTTP
try
% URL pour la requête HTTP
url = 'http://127.0.0.1:17231/command';
% Envoyer la requête HTTP et recevoir la réponse
options = weboptions('Timeout', 0.1, 'ContentType', 'text');
response = webread(url, options);
% Vérifier le code de statut (webread lève une exception pour les réponses non-200)
% Si nous sommes ici, le code de statut était 200
% Vérifier si la réponse n'est pas vide
if ~isempty(response)
% Diviser la réponse en lignes
commandLines = strsplit(response, '\n');
% Exécuter chaque ligne comme une commande MATLAB
for i = 1:length(commandLines)
commandLine = strtrim(commandLines{i});
% Ignorer les lignes vides
if ~isempty(commandLine)
try
disp(['Exécution de la commande: ', commandLine]);
evalc(commandLine); % evalc supprime la sortie standard
catch cmdError
warning('Erreur lors de l''exécution de la commande "%s": %s', ...
commandLine, cmdError.message);
end
end
end
else
disp('Réponse vide reçue du serveur.');
end
catch httpError
% Gestion des erreurs HTTP
if contains(httpError.message, '404')
disp('HTTP 404: Ressource non trouvée.');
elseif contains(httpError.message, '500')
disp('HTTP 500: Erreur serveur.');
elseif contains(httpError.message, 'Connection')
disp('Erreur de connexion: Serveur possiblement inaccessible.');
else
disp(['Erreur HTTP: ', httpError.message]);
end
end
endTimer MATLAB
function http_command_timer()
% Crée un timer qui appelle executeHttpCommands() toutes les 0.5 secondes
% Si un timer avec ce nom existe déjà, le supprimer
existingTimer = timerfind('Name', 'HttpCommandTimer');
if ~isempty(existingTimer)
stop(existingTimer);
delete(existingTimer);
disp('Le timer existant a été arrêté et supprimé.');
end
% Créer un nouveau timer
t = timer('Name', 'HttpCommandTimer', ...
'Period', 0.5, ... % Intervalle du timer (0.5 secondes)
'ExecutionMode', 'fixedRate', ... % Taux de répétition fixe
'TimerFcn', @(~,~)http_command(), ... % Fonction à appeler
'ErrorFcn', @(~,~)disp('Erreur lors de l''exécution de la commande HTTP'));
% Démarrer le timer
start(t);
disp('Timer de commande HTTP démarré. Appelle executeHttpCommands() toutes les 0.5 secondes.');
disp('Utilisez stopHttpCommandTimer() pour arrêter le timer.');
endServeur Python
Ce serveur d’exemple simple émettra des commandes pour alternativement activer et désactiver un commutateur manuel.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from http.server import BaseHTTPRequestHandler, HTTPServer
import time
class CommandServer(BaseHTTPRequestHandler):
# Variable de classe pour suivre l'état
toggle_state = False
def do_GET(self):
if self.path == '/command':
# Préparer la commande alternée
if CommandServer.toggle_state:
command = "set_param('printit/Manual Switch', 'sw', '1');"
else:
command = "set_param('printit/Manual Switch', 'sw', '0');"
# Basculer l'état pour la prochaine requête
CommandServer.toggle_state = not CommandServer.toggle_state
# Envoyer la réponse HTTP
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.end_headers()
self.wfile.write(command.encode('utf-8'))
print(f"Command sent: {command}")
else:
# Erreur 404 pour tous les autres chemins
self.send_response(404)
self.send_header('Content-type', 'text/plain')
self.end_headers()
self.wfile.write(b'404 Not Found')
def run_server(port=17231):
server_address = ('127.0.0.1', port)
httpd = HTTPServer(server_address, CommandServer)
print(f"Server running at http://127.0.0.1:{port}")
print("Press Ctrl+C to stop")
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
print("Server stopped")
if __name__ == '__main__':
run_server()