Aller au contenu

Messages recommandés

Posté(e) (modifié)

Virtual Device pour amplificateur ONKYO TX-NR626 - v1.1.0

 

Je viens d'acquérir un nouveau jouet : un amplificateur home-cinéma ONKYO TX-NR626 et vous trouverez ci-dessous un Virtual Device pour le commander.

Avant de continuer, je tiens à  remercier @Krikroff pour son aide précieuse et l'utilisation d'une grosse partie du code de son Virtual Device. Il a fallut adapter, non sans mal !

 

Onkyo-TX-NR626.jpg

 

Cet amplificateur est connectable au réseau en wifi ou ethernet et peut être commandé à  l'aide du protocole ISCP over ethernet (eISCP) consultable dans ce document. Des infos ici aussi.

Avant toute chose, mea culpa pour les éventuelles erreurs de codage, je ne suis pas du tout codeur et ce ne sera certainement pas optimisé ou réglementaire.

Je pense que ce Virtual Device doit fonctionner avec pas mal d'amplificateur Onkyo dit "connectable".

 

Le Virtual Device :

 

gallery_11_7_5872.jpg

 

Le Home :

 

gallery_11_7_7441.jpg

 

N'oubliez pas de paramétrer l'IP de votre amplificateur (XXX.XXX.XXX.XXX). Le port est généralement 60128, vous n'avez pas besoin de le changer.

 

gallery_11_7_51060.jpg

 

Vous trouverez le Virtual Device dans le fichier ZIP en pièce jointe avec l'icône de l'amplificateur et un fichier README_FIRST.txt

Si ce fichier s'appelle comme ça c'est qu'il y a une raison. Il faut donc ABSOLUMENT le LIRE avant de jouer avec ce Virtual Device !

 

Ce post sera modifié en fonction des évolutions du Virtual Device.

 

Onkyo_TX-NR626_v1.1.0.zip

Modifié par Yohan
  • Upvote 1
Posté(e)

Tu peux essayer ce code qui devrait logiquement faire un mute sur un ampli Onkyo ?

--[[
 %% properties
 %% globals
 --]]

 fibaro:log("Start process");

 local _deviceIp = "192.168.1.49";
 local _devicePort = 60128;
 local _maxRetryProcess = 2;

 local function _process(retry)
       retry = retry or 0;
     --open the socket
     local tcpSocket = Net.FTcpSocket(_deviceIp, _devicePort);
     --set the read timeout
     tcpSocket:setReadTimeout(250);
       --notify user
     fibaro:log("Try Mute on, #" .. retry .. " please wait...");
       fibaro:sleep(250);   
       --send packet
     local bytes, errorCode = tcpSocket:write("ISCP\0\0\0\16\0\0\0\9\1\0\0\0!1AMT00\r");
     --check for error     
     if errorCode == 0 then
         --cli should return the string sent if success
         local result = tcpSocket:read();
         -- could compare to the encoded version of the call to confirm success
         fibaro:log(result);
         fibaro:sleep(1000);
         return true;
     else
         if retry < _maxRetryProcess then
               fibaro:log("Retry process, please wait...");
               fibaro:sleep(1000);
               return _process(retry + 1);
           end
         return false;
     end
 end

 local f, result = pcall(_process);

 if (f) then
     if (result == true) then
         fibaro:log("Command successufully transmited.");
     else
         fibaro:log("Cannot send command!");
     end
 else
       fibaro:log("Error: " .. f);
 end 

Adaptation de mon code par fuuss et rafal_II du fofo inter fibaro. c'est par ici: http://forum.fibaro.com/viewtopic.php?t=2974

rafal_II a publié un VD qui pourrait t'aider ;)

Posté(e)

Ahah, on doit avoir des connexions neuronales JC. J'étais hier soir sur le sujet du forum, je suis allé me coucher en pensant bosser ça today. Je me lève ce matin et que vois-je ? Ton message... j'ai bien ri  :D

Posté(e)

Bon, miam miam ça marche comme je le veux mais j'ai pas de retour d'état. Est-ce que tu pourrais m'en dire plus làdessus JC pour pouvoir récupérer les infos (je connais la commande àenvoyer en ISCP). Si tu regardes dans le fichier excel, dans l'onglet communication il parle de la réponse de l'ampli dans les 50ms après l'envoie de la commande. C'est cette info que j'aimerai récupérer.

J'aurai voulu aussi ne pas mettre en dur dans chaque bouton l'IP et le port de l'ampli. J'ai regardé comment t'avais fait mais j'ai rien compris. Faut-il fixer 2 variables globales ?

Merci par avance

Posté(e)

Bon je me réponds àmoi-même pour l'adresse IP et le Port, j'avais pas vu que tu récupérais ça sur le virtualdevice. J'ai rien dit :)

Posté(e)

Salut Benjy ;) , oui pour l'IP et le Port il faut utiliser fibaro:get(fibaro:getSelfId(), "IPAddress") et fibaro:get(fibaro:getSelfId(), "TCPPort") ... Je vais essayer de jeter un œil sur le retour d'info dans la soirée si possible :)

Posté(e) (modifié)

Bon alors voilà  où j'en suis

 

gallery_11_7_23452.jpg

 

Faut pas le dire hein, mais j'ai pompé sur Krikroff :15:

Le VD marche très bien, le numéro du slider correspond au numéro de volume sur l'ampli (au dessus de 75 l'ampli est à  fond alors attention, si vous ne voulez pas détériorer vos enceintes dans les paramètres de l'ampli fixez un volume maximum genre 50). Seul hic, c'est unidirectionnel, je n'ai pas le retour d'état de l'ampli et j'ai beau m'interroger sur le problème, je ne vois pas d'où ça vient. Normalement avec tcpsocket:read() je devrais l'obtenir non ? Parce que sinon j'ai toujours en réponse d'une commande : "ISCP" ; alors que d'après le document il devrait renvoyer le message complet (je pense qu'il ignore ce qui est après \).

Onkyo_TX-NR626_v1.0.vfib

Modifié par BenjyNet
Posté(e)

Bon j'avance un peu...

Effectivement le tcpsocket.read renvoie une chaine qui est mal interprétée si on l'affiche directement, on ne voit que l'entête ISCP. J'ai tenté de faire un string.gsub(result, "%A", ".") histoire de voir si j'obtenais quelque chose et effectivement le message change. Donc c'est bien dans la récupération de cette variable que ça merdouille mais je ne suis pas assez calé en traitement des strings/variables pour obtenir quelque chose de correct. Je continue mes tests, je vais bien finir par trouver quand même !

Posté(e)

Oh yeah, bon j'ai trouvé pour récupérer les infos qui m'intéresse comme par exemple savoir si l'ampli était connecté ou pas. Il faut faire sur le retour un string.sub(result, 22, 23)

Bon ok tout le monde s'en fout, je parle à  moi-même mais c'est pas grave  :)

Dès que j'ai quelque chose de concluant et que tout fonctionne je post le VD ici (si Yohan a fait son job !).

 

Edit: Il faut aussi que je pense à  clore le socket parce qu'en faisant pleins de tests là , l'ampli il sait plus où il habite !

  • Like 1
Posté(e)

T’inquiètes Benjy, il y a des oreilles pour t’écouter :) . C'est cool que ça avance bien !

Je me demande pourquoi le string.sub(result, 22, 23) marche et pas le reste, un problème d’échappement dans la chaine peut-être ? un fibaro:debug ne sortait rien ?

Posté(e)

Le fibaro:debug me sortait uniquement le début de la chaîne qui est constituée de cette sorte : "ISCP\0\0\0\16\0\0\0\11\1\0\0\0!1COMMAND\r"  (à  la place de COMMAND tu mets ce qui est dans le fichier excel).

J'avais donc "ISCP" qui s'affichait et c'est tout. Alors j'ai ouvert en même temps un telnet sur l'ampli qui affiche à  chaque fois les commandes reçues/envoyées.

Moi je pense que le retour est de la même forme et donc pour récupérer l'info intéressante il faudrait récupérer entre ! et \r

Si je prends l'exemple de l'allumage, pour l'interroger et connaître l'état, il faut faire : "ISCP\0\0\0\16\0\0\0\11\1\0\0\0!1PWRQSTN\r"

Ce qui retourne "ISCP\0\0\0\16\0\0\0\11\1\0\0\0!1PWR01\r" si allumé ou "ISCP\0\0\0\16\0\0\0\11\1\0\0\0!1PWR00\r" si éteint. Donc je récupère que l'information à  la 22eme et 23eme position soit 00 ou 01 (je pense même que seule la 23 position est utile).

 

Par contre ce qui m’étonne, d'après le document (et ce que j'ai pu observer sur le terminal), lorsque j'envoie une commande pour allumer l'ampli genre "ISCP\0\0\0\9\0\0\0\11\1\0\0\0!1PWR01\r" je devrai avoir en retour la même chaîne et ça n'a pas l'air d'être le cas car j'ai rien en position 22/23. C'est con qu'on n'ai pas de terminal pour voir l'état des variables en brut.

Posté(e)

Mouais :/ Bah non ça marche pas. L'ampli envoie pleins de données et j'ai l'impression que ça se mélange les pinceaux (enfin pas de son côté, lui il sait ce qu'il fait :P ).

J'arrive à  le piloter c'est déjà  pas mal.

Posté(e)

Encore en déplacement aujourd'hui je ne vais donc pas pouvoir d'aider pour l'instant ! Mais je suis certain que c'est un problème d’échappement cf. la sorite du debug... j'ai ma petite idée sur la question :), peut être dans la soirée ou demain.

Posté(e)

Il n'y a rien d'urgent Krikroff... moi ce qui m'agace le plus c'est de ne pas trouver la solution. J'aime pas avoir un problème et ne pas pouvoir le résoudre. Si tu veux voir comment réagit le telnet sur l'ampli il faudra que je te file la main sur l'ordi, parce qu'en fait il envoie plein de données tout le temps.

J'ai récupéré une appli chrome qui a une fenêtre debug, ça permet de voir les échanges entre l'ampli et l'appli et c'est dingue tout ce qu'il y a comme transfert. Je ne vois vraiment pas comment traiter toutes ces infos.

Merci de ton aide en tout cas.

Posté(e)

Bon je dois être fatigué mais je trouve pas pourquoi je reste bloqué sur ma boucle qui regarde si la réponse est conforme àce que j'attends. Une idée ?

fibaro:debug('Start process ON/OFF v1.0.1');
fibaro:log('Try to turn ON/OFF');

local _deviceIp = fibaro:get(fibaro:getSelfId(), "IPAddress");
local _devicePort = fibaro:get(fibaro:getSelfId(), "TCPPort");
local _maxRetryProcess = 5;

local function _checkPowerState(retry)
	retry = retry or 0;
	--notify user
	fibaro:debug("Request Power status, #" .. retry .. " please wait...");
	--send packet
	bytes, errorCode = _tcpSocket:write("ISCP\0\0\0\16\0\0\0\11\1\0\0\0!1PWRQSTN\r");
	-- check for error
	if errorCode == 0 then
		fibaro:debug("Power status command successufully transmited.");
    	-- amplifier sould return the string sent if success
    	local result = _tcpSocket:read();
    	local cmd_value = string.sub(result, 22,23)
    	-- check if result is equal than command to confirm success
    	fibaro:debug("Check result of command : " .. cmd_value);
    		if ((tonumber(cmd_value) ~= 0 or tonumber(cmd_value) ~= 1) and retry < _maxRetryProcess) then  --<- je sus bloqué ici
      		fibaro:sleep(1000);
      		return _checkPowerState(retry + 1);
      		else
      		return nil
    		end
        return tonumber(cmd_value);
    else
    	if retry < _maxRetryProcess then
      	fibaro:debug("Retry process, please wait...");
      	fibaro:sleep(2000);
      	return _checkPowerState(retry + 1);
      	end
    return nil;
    end
end

--open a local socket
_tcpSocket = Net.FTcpSocket(_deviceIp, _devicePort);
--set the read timeout
_tcpSocket:setReadTimeout(250);

local f, result = pcall(_checkPowerState);

-- close socket
_tcpSocket:disconnect();
-- destroy object
_tcpSocket = nil;

if (f) then
	if (result ~= nil) then fibaro:debug(result);
    	if (result == 0) then
      	fibaro:sleep(1000);
      	fibaro:call(fibaro:getSelfId(), "pressButton", 2); 
		fibaro:debug("Power is Off, try to turn On");
		elseif (result == 1) then
      	fibaro:sleep(1000);
      	fibaro:call(fibaro:getSelfId(), "pressButton", 3); 
		fibaro:debug("Power is On, try to turn Off");
		end
    else
    fibaro:debug("Cannot send command!");
    end
else
  	fibaro:debug("Error: " .. f);
end

Posté(e)

Je t'aiderais bien mais jamais essayer, mais faudrait que tu montre un peu les retour de ton ampli pour qu'on puisse t'aider :D

Posté(e)

Bah làc'est pas un problème de retour d'info c'est un problème de boucle, de test dans la boucle je pense. Parce que les valeurs de mes variables sont bonnes. Mais je ferais une video de ce que l'ampli retourne parce qu'avec des copies d'ecran vous allez pas comprendre.

Posté(e)

Alors j'ai changé ma ligne qui me posait problème en 

if ((tonumber(cmd_value) ~= 0 and retry < _maxRetryProcess) or (tonumber(cmd_value) ~= 1 and retry < _maxRetryProcess)) then

J'ai ma variable cmd_value qui vaut soit 0 soit 1 mais ça persiste à  rentrer dans la boucle si retry est plus petit que 5 (valeur de _maxRetryProcess).

Posté(e)

Benjy, il me semble que le code return tonumber(cmd_value); ne sera jamais exécuté car avant tu as un return dans ton if mais aussi dans ton else ...

Posté(e)

Arf oui attend j'ai changé un peu le code... voilà(je mets que la partie intéressante)

fibaro:debug("Check result of command : " .. cmd_value);
    		if (((tonumber(cmd_value) ~= 0) and (retry < _maxRetryProcess)) or ((tonumber(cmd_value) ~= 1) and (retry < _maxRetryProcess))) then
      		fibaro:sleep(1000);
      		return _checkPowerState(retry + 1);
      		else
      		return tonumber(cmd_value);
    		end

    else

En fait je voudrais que si dans ma variable cmd_valeur j'ai autre chose que 0 ou 1, je veux qu'il retente l'envoie de la commande.

Posté(e)

Et pourquoi pas :

if (tonumber(cmd_value) > 1 and retry < _maxRetryProcess) then
  return _checkPowerState(retry + 1);
else
  return tonumber(cmd_value);
end

mais quelles sont valeurs possibles pour cmd_value ?

 

PS: aussi, pour "catcher" plus facilement le code en phase de conception tu peux enlever le pcall ;)

Posté(e)

Alors en fait je t'explique, ce que j'aimerai c'est récupérer dans la réponse (result) ce qu'il y a entre ! et le \n.

Une réponse est de la forme ISCP\0\0\0\16\0\0\0\9\1\0\0\0!1PWR01\r

Le 9 représente le nombre de caractères entre ! et \n (y compris)

 

En fait dans la réponse ce qui est important c'est d'identifier la partie PWR01 car c'est là  que j'aurai l'info que je cherche. Ici par exemple je sais que l'ampli est allumé.

Après le soucis c'est que l'ampli communique en permanence et dans la reponse je peux avoir une trame qui ne correspond pas à  ma demande parce qu'il envoie par exemple le décompte du temps d'écoute de la station de radio si je suis sur la source NET.

Je te met dessous une copie d'écran expliquant comment est formé le message (j'ai pas tout saisi aux remarques du bas d'ailleurs).

gallery_11_7_65709.jpg

Posté(e)

Je ferais un truc comme ça pour la logique de traitement :)

local on = "ISCP\0\0\0\16\0\0\0\11\1\0\0\0!1PWR01\r";
local off = "ISCP\0\0\0\16\0\0\0\11\1\0\0\0!1PWR00\r";

parsePowerState = function(str)
  if (str ~= nil and string.len(str) == 24) then
    local r = str:match('!1PWR(.+)\r');
    if (r ~= nil) then
      return tonumber(r);
    end
  end
  return 0;
end

fibaro:debug(parsePowerState(on));
fibaro:debug(parsePowerState(off));

local result = on;
if (parsePowerState(result) == 1) then
  fibaro:debug("Ampli sur ON");
elseif (parsePowerState(result) == 0) then
  fibaro:debug("Ampli sur OFF");
else
  -- TODO
end
×
×
  • Créer...