Steuern eines Yamaha AVR RX-V2700 durch einen Moxa übers Netzwerk mit Java GUI

Hallo zusammen,

ich komme nicht weiter, sehe vielleicht auch den Wald vor lauter Bäumen nicht mehr.

Mein Audio Video Receiver “Yamaha RX-V 2700” hat eine RS232 Schnittstelle um ihn zu steuern.
Diese habe ich nun mit einem Moxa “NPort 5110” verbunden, der die RS232 Schnittstelle in meinem Netzwerk einbindet.

Am Jahresanfang habe ich dann ein Pythonprogramm geschrieben um den AVR anzusteuern. Dieses klappte wunderbar.

Hier das Pythonprogramm:



# -*- coding: utf-8 -*-
#!/usr/bin/env python

import socket  # Netzwerkverbindung

print
print ("--------------------------------------------------------")
print ("       YAMIC // Yamaha Control AVR RX-V2700 V.0.2")
print ("--------------------------------------------------------""
")
print ("00 -> YAMIC Beenden")
print ("01 -> Ein / Hauptzone einschalten [Wohnzimmer]")
print ("02 -> Aus / Hauptzone ausschalten [Wohnzimmer]")
print ("99 -> Wake ON RS232")

HOST = '192.168.1.5'  # IP Adresse vom Server
PORT = 4001  # Die Portnummer vom Server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect((HOST, PORT))  # Verbinduung mit dem Server aufbauen
while 1:
    try:
        auswahl = (input("IN -> Zeilennummer eingeben..."))  # Eingabe
        if auswahl == 00:  # Programm bei 00 schliessen
            break
        elif auswahl == 01:  # EIN s. o.
            print ("01 -> Ausgeführt")
            s.send("\x02\x30\x37\x45\x37\x45\x03")  # Sende HEX Code an AVR
        elif auswahl == 02:
            print ("02 -> Ausgeführt")  # AUS s. o. Zeile 14-20
            s.send("\x02\x30\x37\x45\x37\x46\x03")  # Sende HEX Code an AVR
        elif auswahl == 99:  # EIN s. o. Zeile 14-20
            print ("99 -> Ausgeführt")
            s.send("\x02\x34\x44\x30\x31\x03")  # Sende HEX Code an AVR
        else:
            print ("FM -> Eingabe ungültig!")  # Fehlermeldung
    except:
            print ("FM -> Falsche Eingabe: Bitte Zeilennummer eingeben!")
s.close()  # Verbindung zum Server schliessen

Nun habe das Programm in Java nochmals umgesetzt (Case 1 und Case 2 sind unterschiedlich, weil ich damit etwas probiert habe):

import java.io.*;
import java.net.*;
import javax.swing.JOptionPane;

public class YamicNet{
	public static void main(String args[]) throws Exception {

		String ipaddress = "192.168.1.5";
		int port = 4001;
		Socket socket = new Socket(ipaddress, port);
		OutputStream out = socket.getOutputStream();

		String inputChoice;
		int choice = 0;
		
		System.out.println("--------------------------------------------------------");
		System.out.println("   YamJaC // Yamaha Java Control AVR RX-V2700 V.0.1");
		System.out.println("--------------------------------------------------------");
		
		
		while(choice != -1){

			System.out.println("01 -> Ein / Hauptzone einschalten [Wohnzimmer]");
			System.out.println("02 -> Aus / Hauptzone ausschalten [Wohnzimmer]");
			inputChoice = JOptionPane.showInputDialog("Enter choice");
			choice = Integer.parseInt(inputChoice);

			switch(choice){
				case 1:
					
				byte [] AvrEin = {0x02, 0x30, 0x37, 0x45, 0x37, 0x45, 0x03};
				out.write(AvrEin);
				
				case 2:
				byte[] AvrAus = {(byte)0x02, (byte)0x30, (byte)0x37, (byte)0x45,(byte)0x37,(byte)0x46,(byte)0x03};
				out.write(AvrAus);
				//\x02\x30\x37\x45\x37\x46\x03
				break;

				default:
				System.out.println("Invalid choice");
				break;
			}
		}

		out.close();
		
		
		socket.close();
		System.exit(0);
	}
}

Beide Programme funktionieren ohne Probleme, jedoch ist die Bedienung nicht Frauenfreundlich und da es irgendwann über ein Tablet laufen soll ist eine GUI Pflicht.
Damit ich ein Verständnis entwickeln kann, wollte ich nun eine GUI erstmal für einen Rechner basteln. Das geht mit NetBeans sehr einfach und dank diesem Forums konnte sogar den Button mit Action belegen und etwas an den Moxa senden. Leider kommt am Moxa nicht das an was ich zum steuern benötige. Meine Befehle sind laut Beschreibung ASCII. In den obigen Programmen habe ich diese in HEX umgewandelt, weil es sonst nicht laufen würde.

Nun das Programm welches noch nicht die richtige Kommunikationsart gefunden hat:

package avr_yam;

public class MainYam extends javax.swing.JFrame {

  
    public Server BefehlSenden;
    public MainYam(){
        initComponents();{
    BefehlSenden = new Server(); //Übergibt den BefelSenden an die Verbindung zum senden
  

    
    }
    }
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        JButton_AVR_Ein = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        JButton_AVR_Ein.setText("Einschalten");
        JButton_AVR_Ein.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                JButton_AVR_EinActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(JButton_AVR_Ein)
                .addContainerGap(313, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(JButton_AVR_Ein)
                .addContainerGap(261, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        
          
    private void JButton_AVR_EinActionPerformed(java.awt.event.ActionEvent evt) {                                                
        // TODO add your handling code here:
	// Der Befehlscode der für das Einschalten zustädig ist.			
    BefehlSenden.send("0x02, 0x30, 0x37, 0x45, 0x37, 0x45, 0x03");
    
    }                                               

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(MainYam.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MainYam.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MainYam.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MainYam.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(() -> {
            new MainYam().setVisible(true);
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton JButton_AVR_Ein;
    // End of variables declaration                   
}

Die dazugehörige Verbindung:

package avr_yam;
import java.io.*;
import java.net.Socket;
 
public class Server {
public Socket server = null;
private DataOutputStream out = null;

public Server(){
try {
        System.out.print("warten ... ");
        Socket server = new Socket("192.168.1.5", 4001);
        out = new DataOutputStream(server.getOutputStream());
        System.out.println("Verbunden!");
    }
catch (Exception e)
    {
        System.out.println (e);
    }
                }
 
public void send (String befehl) {
try {
        out.writeBytes(befehl);
        out.flush();
    }
catch (Exception e)
    {
        System.out.println ("Fehler beim senden"+ e);
    }
    }
}

Den Netzwerkverkehr habe ich mit Wireshark beaobachtet.

Kommunikation OK, mit dem obigen Switch / Case Programm:

Kommunikation nicht OK, mit dem obigen GUI Programm:

Also ich denke es stimmt etwas mit der “BefehlSenden” Übergabe nicht, ich habe inzwischen soviel gelesen und getestet, das ich total verunsichert bin. Es ist selten aber in diesem Fall benötige ich Hilfe. :confused:

Zur Vollständigkeit das Kommandoheft vom RX-V2700:
http://webpix.ca/files/RX-Vx700_RS232C_Standard.pdf

Meine Kenntnisse in Netzwerkprogrammierung sind eingerostet.

…aber muss denn ein Server nicht einen [japi]ServerSocket[/japi] bekommen?

Wahrscheinlich gibts noch andere Problemstellen, die ich beim Code-Überfliegen nicht gesehen habe.

Im zweiten Screenshot sieht man doch ganz deutlich was falsch läuft: die Befehle werden ganz einfach als Zeichenkette gesendet.
Die send-Methode der Serverklasse sollte als Argument statt String byte[] bekommen.

*** Edit ***

Im MainYam sollte der aufrufende Code dann in etwa so aussehen:
BefehlSenden.send(new byte[] {(byte)0x02, (byte)0x30, (byte)0x37, (byte)0x45, (byte)0x37, (byte)0x45, (byte)0x03});

Super Danke euch beiden, die Lösung ist wie cmrudolph geschrieben hat, hab es einfach selber nicht umgestzt bekommen… Nun freue ich mich!!! :slight_smile: Hier nochmal der Code korrigiert:

package avr_yam;

public class MainYam extends javax.swing.JFrame {

  
    public Server BefehlSenden;
    public MainYam(){
        initComponents();{
    BefehlSenden = new Server();
  

    
    }
    }
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        JButton_AVR_Ein = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        JButton_AVR_Ein.setText("Einschalten");
        JButton_AVR_Ein.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                JButton_AVR_EinActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(JButton_AVR_Ein)
                .addContainerGap(313, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(JButton_AVR_Ein)
                .addContainerGap(261, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        
          
    private void JButton_AVR_EinActionPerformed(java.awt.event.ActionEvent evt) {                                                
        // TODO add your handling code here:
				
    BefehlSenden.send(new byte[] {(byte)0x02, (byte)0x30, (byte)0x37, (byte)0x45, (byte)0x37, (byte)0x45, (byte)0x03});
    
    }                                               

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(MainYam.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MainYam.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MainYam.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MainYam.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(() -> {
            new MainYam().setVisible(true);
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton JButton_AVR_Ein;
    // End of variables declaration                   
}

Server Verbindung:

package avr_yam;
import java.io.*;
import java.net.Socket;
 
public class Server {
public Socket server = null;
private DataOutputStream out = null;

public Server(){
try {
        System.out.print("warten ... ");
        Socket server = new Socket("192.168.1.5", 4001);
        out = new DataOutputStream(server.getOutputStream());
        System.out.println("Verbunden!");
    }
catch (Exception e)
    {
        System.out.println (e);
    }
                }
 
public void send (byte[] befehl) {
try {
        out.write(befehl);
        out.flush();
    }
catch (Exception e)
    {
        System.out.println ("Fehler beim senden"+ e);
    }
    }
}