Envoi d'une commande html avec python [Résolu]

Signaler
-
 Discret68 -
Bonjour à tous

Je dispose d'une carte équipée de 8 relais fonctionnant à l'aide de commandes html. J'ai développé un programme sur PC en VB.Net et tout fonctionne comme attendu.
Aujourd'hui, j'essaie (en vain) de reproduire ce que je fais en VB.Net mais cette fois-ci, en python sur un Raspberry Pi.

La carte dispose d'une adresse IP et requiert un nom et un mot de passe pour y accéder, ainsi qu'une commande pour activer ou désactiver un relais.
A titre d'exemple, voici la syntaxe qui permet d'activer le relais n°1 : http://192.168.1.120/relay.gi?relayon1=on
La commande relayon1=off permet de désactiver le même relais.

Cette syntaxe utilisée dans un simple navigateur internet fonctionne, la commutation des relais s'effectue.

Je cherche donc à introduire cette syntaxe dans un programme python. J'ai parcouru pas mal de sites concernant l'utilisation des modules httlib, requests, urllib, ... , ainsi que les aides respectives, mais je ne trouve pas d'exemple qui fonctionne, notamment lié à la nécessité d'utiliser un nom et un mot de passe pour la prise en compte de la commande.

Python et l'anglais ne sont pas vraiment ma tasse de thé. Je ne tourne même pas en rond, je ne tourne simplement pas !

Lorsque j'utilise ce code à titre de test pour accéder à la carte :
import httplib
httpServ= httplib.HTTPConnection("192.168.1.120")
httpServ.request("GET","/")
response = httpServ.getresponse()
print response.status, response.reason
httpServ.close


La réponse est 401 Unauthorized, ce qui n'est pas étonnant dans le sens où aucun mot de passe n'étant transmis, la carte refuse naturellement l'accès.

Voila, si quelqu'un pouvait me proposer le bout de programme qui réponde à mon besoin, il en sera sincèrement remercié.

Merci à vous

Jean-Pierre

4 réponses

Messages postés
5434
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
29 octobre 2020
913
Salut Discret68,

Tu n'indiques pas comment l'authentification se fait. C'est une information importante, car selon le procédé d'authentification, le dialogue entre la carte et le client http sera différent.

La plus simple pour un site Web est de laisser l'authentification être gérée par le serveur Web sous la forme de l'authentification HTTP Basic Auth. C'est peut-être ce que propose ta carte.

Le module Python suivant https://requests.readthedocs.io/en/master/ supporte cette authentification de base et d'autres plus élaborées :

https://requests.readthedocs.io/en/master/user/authentication/

Avec un HTTP Basic Auth servant à authentifier l'accès à la racine du serveur http où se trouve relay.gi, cela serait un truc du genre :

from requests.auth import HTTPBasicAuth
r = requests.get('http://192.168.1.120/relay.gi?relayon1=on', auth=HTTPBasicAuth('user', 'pass'))


Le même module permet de gérer d'autres protocoles d'authentification (Digest, OAuth1 et 2, OpenID,...), de faire des requêtes GET ou POST, de gérer http et https,... vois la doc.

Dal
Messages postés
13071
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
13 novembre 2020
727
bonjour, tu as une carte, un PC, et un Raspberry Pi.
quand tu accèdes à la carte à partir du PC, tu écris "Cette syntaxe fonctionne". Cependant, je suppose qu'elle ne fonctionne que parce que tu as précédemment envoyé une ou plusieurs requêtes avec le mot de passe. est-ce exact?
tu indiques que tu as développé un programme VB.Net qui fonctionne. ce programme fonctionne-t'il sans que le mot de passe ait été préalablement rentré dans la navigateur?
par ailleurs, je suis étonné que ton code Python soit si rudimentaire: t'es-tu réellement basé sur ton programme VB.Net (que tu ne nous montres pas)?
Pour permettre une meilleure compréhension de la problématique, voici quelques explications complémentaires :

Cette carte relais est connectée sur le réseau Ethernet de la maison sur lequel sont également connectés différents ordinateurs (Mac, PC, RPI) ainsi que différents périphériques, plusieurs cartes relais, dont celle pour laquelle je voudrais pouvoir la piloter via un programme en Python sur un des RPI

Actuellement, cette carte relais est pilotée via un interface graphique que j’ai développé en VB.Net sous Windows. Cet interface me permet de lancer la commutation individuel des relais (marche, arrêt ou impulsion). Les relais sont commutés manuellement selon les besoins. A contrario, il y en a un qui doit pouvoir être commuté automatiquement, mais cette fois-ci par un programme en Python qui fonctionne en continu sur un RPI.

Pour envoyer la commande de commutation en VB.Net, voici les éléments de programmation :
La commande globale de commutation est composée de 2 chaines de caractères qui sont concaténées de manière à n’en former qu’une, qui est envoyée à la carte :
La 1ère chaine contient les infos communes à la commande générale : l’identifiant (admin), le mot de passe (MotPasse), le n° d’IP (192.168.1.120).

Vu que le programme permet de s’adapter aux besoins des uns et des autres, ces paramètres sont gérés en variables stockées dans des registres.

La 1ère partie de la variable globale est géb-nérée au lancement du programme sur la base des paramètres enregistrés, ce qui donne : Cde_Carte = "http://" & Identifiant & ":" & Mot_passe & "@" & IP_Carte & "/relay.cgi"

Concrètement, chez moi, ça donne : "http://admin:MotPasse@192.168.1.120/relay.cgi" 

Ensuite, en fonction de l’appui sur le bouton correspondant à un des relais, je vais soit le mettre en service, soit l’arrêter s’il est en service. J’ai également la possibilité de faire travailler un relais en mode impulsion avec une durée d’activation réglable.

Voici le sous-programme qui permet de compléter la 1ère partie de la commande pour en obtenir la commande globale. La commande ainsi constituée est envoyé à la carte relais :

Public Sub AppliquerEtat_Relais(ByVal Num_Relais, ByVal Etat_Relais) 'Procédure pour envoyer une commande à la carte relais
If My.Computer.Network.Ping(IP_Carte) Then ‘ test pour vérifier que la carte est bien en service
Select Case Etat_Relais
Case "on" ' on veux activer le relais
aURL = Cde_Carte & "?relayon" & Str(Num_Relais) & "=on"
V_Rel(Num_Relais) = 1
Case "off" 'on veux désactiver le relais
aURL = Cde_Carte & "?relayoff" & Str(Num_Relais) & "=off"
V_Rel(Num_Relais) = 0
Case "pulse" ' on veux une impulsion
aURL = Cde_Carte & "?pulse" & Str(Num_Relais) & "=pulse"
End Select
aXMLHTTP = CreateObject("MSXML2.XMLHTTP")
Call aXMLHTTP.Open("GET", aURL, False) 'Envoi de la commande à la carte
Call aXMLHTTP.send()
Else
MsgBox("Commande impossible, la carte relais n'est pas connectée")
End If
End Sub

Concrètement, si je veux activer le relais n°1, j’ajoute le terme « ?relayon1=on » à la 1ère partie de la commande et j’obtiens la commande html complète qui est : "http://admin:MotPasse@192.168.1.120/relay.cgi?relayon1=on"

Tout cela fonctionne sans problème.

En complément, si je place la commande littérale complète ci-dessus dans la zone de commande d’un navigateur internet quelconque sur un ordinateur tout aussi quelconque, la commande s’effectue bien.

Maintenant, ce que je souhaite faire, c’est envoyer cette commande avec la syntaxe définie à la carte relais via un programme Python. Tout ce qui est constitution de la chaine de caractère qui constitue la commande en Python ne me pose pas de problème, c’est juste comment écrire le bout de programme qui va me permettre de l’envoyer à la carte, en 1 ou plusieurs morceaux si nécessaire.

Les quelques lignes en Python dans mon message initial n’avaient pour objectif que de montrer ce que j’essayais de faire, sachant que je ne sais pas comment prendre en compte les paramètres de connexion (identifiant, mot de passe, commande de commutation).

J’avoue que l’appropriation du Python est une réelle difficulté pour moi et que les exemples que j’ai pu trouver sur le net ne m’ont pas permis de trouver LA solution. Je n’ai trouvé aucun exemple qui prenne en compte un identifiant et un mot de passe.

@ Dal : je vais tester l’exemple que tu proposes
Messages postés
13071
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
13 novembre 2020
727
pourquoi pas alors:
httpServ.request("GET","admin:MotPasse@192.168.1.120/relay.cgi?relayon1=on")
>
Messages postés
13071
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
13 novembre 2020

Oui, mais dans ce cas, comment initialises tu httpServ car il est nécessaire de déclarer une valeur.

J'ai essayé avec le n° d'IP : httpServ= httplib.HTTPConnection("192.168.1.166") . Pas de message d'erreur, mais aucune action coté carte relais.
@ Dal : l'exemple que tu as donné fonctionne parfaitement. Les relais commutent bien conformément aux commandes transmises.

J'ai lu (mais pas tout) la documentation dont tu as mis les liens.

J'avais une question complémentaire liée à l'utilisation de la carte (chaque chose en son temps) et dans la documentation, j’ai trouvé la réponse.

La carte peut être interrogée afin d'obtenir l'état en cours d'activation des relais.
On récupère une chaine de caractère contenant entre autre le texte "output":"10000000".
L'état des 8 relais est codé binairement sur 8bit. Dans l'exemple, le relais n°1 est activé.

Il faut envoyer la commande "http://192.168.1.120/state.cgi" en lieu et place de la commande de commutation et on récupère la réponse par la commande r.text.

Ensuite, c'est du traitement alphanumérique.

En tout cas, grand merci à toi.

Jean-Pierre