[JAVA] Puis-je utiliser RXTX? Existe-t-il une alternative?

Communication série après une longue absence

Après un long moment, j'ai décidé d'utiliser Java pour la communication série, j'ai donc fait beaucoup de recherches. Cela fait un moment que j'écris des programmes en Java, et dans le passé il n'y avait que RXTX pour la communication série Java, mais maintenant, il y a des articles tels que des successeurs ou des alternatives dans la recherche. Vous trouverez ci-dessous les trois premiers articles d'une recherche Google sur "Java Serial Communication".

  1. Utilisons la communication série avec Java http://web.sfc.wide.ad.jp/~tinaba/tutorials/serial-j/index.html
  2. Défis et recherche alternative pour la bibliothèque de communication série Java RXTX https://qiita.com/kyosho/items/fc0c40458385c7d98232
  3. Génie logiciel / Communication série Java <https://www.torutk.com/projects/swe/wiki/Java%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%AB % E9% 80% 9A% E4% BF% A1> Le premier est comment utiliser RXTX, et le suivant et le suivant sont des suggestions de bibliothèques alternatives.

Com0com comme travail préparatoire

Installez l'émulateur Null-modem (https://sourceforge.net/projects/com0com/) en tant que port COM pour le moniteur. Il existe de nombreux articles qu'il n'est peut-être pas possible d'installer sur Windows 10 (64 bits), mais ici (Windows 10 Famille 64 bits) j'ai pu installer sans aucun problème. À propos, l'environnement de développement était «Eclipse 2020 (version Windows 64 bits)» de Pleiades All In One et «Full Edition» de «Platform», et seul JDT était en plus installé. Le "Tera Term" familier est utilisé pour le terminal moniteur COM.

Pouvez-vous remplacer

Ici, j'ai essayé les quatre tests suivants, mais dans mon environnement (Windows 10 Home), je ne pouvais pas "sortir des caractères avec PrintWriter etc. (envoyer)" et "recevoir des entrées de caractères du terminal avec Event (réception d'événement)" Ce n'était que RXTX. Mais aucun n'est parfait. Je n'ai pas essayé la réception de sondages.

  1. RXTX [http://fizzed.com/oss/rxtx-for-java]
  2. jSerialComm [http://fazecast.github.io/jSerialComm/]
  3. jpurejavacomm [http://www.sparetimelabs.com/purejavacomm/purejavacomm.php]
  4. jssc [https://github.com/scream3r/java-simple-serial-connector]

Essayez RXTX pour la première fois depuis longtemps

J'ai apporté "mfz-rxtx-2.2-20081207-win-x64.zip" du site ci-dessus. On dit qu'il place dll sous bin ou jar dans lib \ ext, mais comme il n'y a pas de dossier appelé lib / ext dans openjdk11, jar a été ajouté à la bibliothèque par "Add external archive" dans le chemin de construction d'Eclipse. La dll a jre / bin sous le dossier Eclipse, donc je l'ai poussée là-bas. L'instruction d'importation est omise, mais la déclaration de classe, l'interface et la fonction principale (ajoutez l'instruction throws car try / catch est gênant) sont les suivantes. C'est à peu près la même chose avec les autres.

public class RXTXtest implements SerialPortEventListener {
	public static void main(String[] args) throws Exception {
		new RXTXtest();
	}
	...(Omission)
}

Le constructeur et le premier processus sont les suivants. Une liste des ports COM accessibles par énumération s'affiche. Il peut être affiché sans aucun problème.

	String name;
	SerialPort port;
	RXTXtest() throws Exception {
		name=this.getClass().getSimpleName();
		Enumeration<CommPortIdentifier> ids=CommPortIdentifier.getPortIdentifiers();
		while(ids.hasMoreElements()) {
			CommPortIdentifier id=(CommPortIdentifier)ids.nextElement();
			System.out.println(id.getName());
		}
	...Omission
	}

Lorsque j'ai effectivement ouvert le port COM et essayé d'écrire avec PrintWriter (fonction d'envoi), une erreur fatale est apparue. "COM7 & COM8" est appairé à com0com, et si vous vous connectez au côté "COM8" avec Tera Term et "non", aucune erreur ne se produira, mais si vous vous connectez et surveillez, vous obtiendrez une ERREUR FATALE. C'était correct avant flush (), mais quand flush () cela devient FATAL.

		CommPortIdentifier id=CommPortIdentifier.getPortIdentifier("COM7");
		SerialPort port=(SerialPort) id.open(name, 2000);
		port.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
		port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
		port.addEventListener(this);
		PrintWriter pw=new PrintWriter(port.getOutputStream());
		pw.println(name+": "+"Tested!");
		pw.flush();

Le texte complet de FATAL ERROR est inclus pour référence. Que dois-je faire comme ça?

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000180004465, pid=4480, tid=4852
#
# JRE version: OpenJDK Runtime Environment (11.0.7+10) (build 11.0.7+10)
# Java VM: OpenJDK 64-Bit Server VM (11.0.7+10, mixed mode, tiered, compressed oops, g1 gc, windows-amd64)
# Problematic frame:
# C  [rxtxSerial.dll+0x4465]
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\akira\Documents\workspace\SerialTesting1\hs_err_pid4480.log
#
# If you would like to submit a bug report, please visit:
#   https://github.com/AdoptOpenJDK/openjdk-support/issues
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

Essayez jSerialComm

J'ai apporté "jSerialComm-2.6.2.jar" à partir du bouton "jar" en haut de http://fazecast.github.io/jSerialComm/. Ceci est également inclus dans le chemin de construction dans "Ajouter une archive externe". La zone autour du constructeur est la suivante. Étant donné que l'interface a été écrite pendant le traitement suivant la source de l'échantillon, elle n'est pas déclarée au début.

public class JSerialCommTest {
	public static void main(String[] args) throws Exception {
		new JSerialCommTest();
	}
	...Omission
}

La liste des ports disponibles est affichée dans un tableau. Intuitif mais pas intelligent. De plus, les paires de ports spéciaux "CNCA0" et "CNCB0" de com0com qui devraient être masqués sont également répertoriées (elles n'apparaissaient pas dans RXTX).

	SerialPort port;
	String name;
	JSerialCommTest() throws Exception {
		name=this.getClass().getSimpleName();
		SerialPort[] ports=SerialPort.getCommPorts();
		for(int i=0;i<ports.length;i++) System.out.println(ports[i].getSystemPortName());
		...Omission
	}

J'ai pu ouvrir et sortir sans aucun problème. Il peut être transmis au moins unilatéralement (sur RXTX, pw.flush () crache FATAL).

		port=SerialPort.getCommPort("COM7");
		port.setComPortParameters(9600, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
		port.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
		port.openPort();
		PrintWriter pw=new PrintWriter(port.getOutputStream());
		pw.println(name+": Tested!");
		pw.flush();

Le problème est du côté de la réception. Lors de la surveillance d'un événement en attendant l'entrée dans une boucle infinie comme indiqué ci-dessous, une exception se produit ou il n'y a pas de réponse. L'exception était liée à TimeOut, mais je n'ai pas pu la résoudre correctement en raison d'un manque de capacité.

		port.addDataListener(new SerialPortDataListener() {
			public int getListeningEvents() { return SerialPort.LISTENING_EVENT_DATA_AVAILABLE; }
			public void serialEvent(SerialPortEvent event) {
				if (event.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) return;
				byte[] newData = new byte[port.bytesAvailable()];
				int numRead = port.readBytes(newData, newData.length);
				pw.println("Read " + numRead + " bytes.");
			}
		});
		while(true) {}

Essayez jpurejavacomm

Le vieil homme est déjà fatigué. Ensuite, utilisons jpurejavacomm. J'ai apporté "purejavacomm-1.0.3.jar" du dossier bin de https://github.com/nyholku/purejavacomm. Il semble que cela seul ne fonctionnera pas, donc j'avais également besoin de "jna.jar". C'est sous le dossier dist ici https://github.com/java-native-access/jna. La définition de classe est presque la même que les autres. Encore une fois, l'interface est anonyme et écrite pendant le traitement, il n'y a donc pas d'outils.

public class JPureJavaCommTest  {
	public static void main(String[] args) throws Exception {
		new JPureJavaCommTest();
	}
	...Omission
}

Les ports disponibles de la liste des constructeurs se sont déroulés normalement. Jusqu'à présent, il n'y a aucun problème avec aucune bibliothèque.

	SerialPort port;
	String name;
	JPureJavaCommTest() throws Exception {
		name=this.getClass().getSimpleName();
		Enumeration<CommPortIdentifier> e=CommPortIdentifier.getPortIdentifiers();
		while(e.hasMoreElements()) {
			CommPortIdentifier id=(CommPortIdentifier)e.nextElement();
			System.out.println(id.getName());
		}
		...Omission
	}

De l'ouverture du port à la vérification de la fonction d'envoi, cela s'est terminé sans aucun problème. RXTX ne fonctionnait pas, mais jSerialComm était bon jusqu'à présent.

		CommPortIdentifier id=CommPortIdentifier.getPortIdentifier("COM7");
		port=(SerialPort)id.open(name,2000);
		port.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
		port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
	
		PrintWriter pw=new PrintWriter(port.getOutputStream());
		pw.println(name+": Tested!");
		pw.flush();

Eh bien, il n'y a pas de réaction lorsqu'il s'agit de recevoir des événements. Aucune erreur ou exception. Apparemment, quelque chose ne va pas?

		port.notifyOnDataAvailable(true);
		port.addEventListener(new SerialPortEventListener() {
			public void serialEvent(SerialPortEvent arg0) {
				pw.println(name+": SerialEvent!");
			}});
		while(true) {}

Je vais essayer jssc

c'est fini maintenant. Vous pouvez envoyer en série mais pas le recevoir avec java !! Mais voulez-vous essayer jssc à la fin? J'ai laissé tomber "jssc-2.9.2.jar" à partir d'ici https://github.com/java-native/jssc/releases, mais quand j'ai essayé de l'utiliser pendant un moment, cela ressemblait à NG, donc le précédent " J'ai utilisé "jssc-2.9.1.jar" (parce qu'un étranger a écrit que c'était une erreur qui n'apparaissait pas dans la version précédente, n'est-ce pas un bug?). À ce stade, je suis d'humeur à abandonner. De plus, "native-lib-loader-2.3.4.jar", "slf4j-api-1.7.30.jar" et "slf4j-simple-1.7.30.jar" sont également nécessaires. Qu'est-ce que Maven? Je ne sais pas ... La définition de classe est la suivante. Pour une raison quelconque, "new SerialPortEventListener ()" ne peut pas être exécuté pendant le traitement (y a-t-il un constructeur?), Donc l'interface est ajoutée avec l'instruction implements.

public class JSSCtest  implements SerialPortEventListener {
	public static void main(String[] args) throws Exception {
		new JSSCtest();
	}
	...Omission
}

Vous pouvez également lister les ports qui peuvent être utilisés normalement. Eh bien, je pourrais même faire du RXTX. Cela renvoie un tableau String [] au lieu de Enumuration. Cela ne me convient pas, mais c'est simple. Cependant, "CNCA0" et "CNCB0" qui doivent être masqués (ceux-ci n'apparaissent pas dans le gestionnaire de périphériques) sont également répertoriés ici. Il est utile de définir line.separator sur le caractère ls ici.

	SerialPort port;
	String ls;
	JSSCtest() throws Exception {
		ls=System.getProperty("line.separator");
		String[] ports = SerialPortList.getPortNames();
		for(int i = 0; i < ports.length; i++) {
		   System.out.println(ports[i]);
		}
		...Omission
	}

Vous pouvez ouvrir et envoyer des ports sans aucun problème, mais pour une raison quelconque, vous ne pouvez pas obtenir OutputStream et vous devez utiliser une méthode telle que writeString. J'ai utilisé le caractère ls parce que je ne pouvais pas bien casser la ligne (le contenu est System.geyProperty ("line.separator")), mais vous pouvez le définir pour que \ n puisse être reçu du côté de Tera Term.

		port=new SerialPort("COM7");
		port.openPort();
		port.setParams(SerialPort.BAUDRATE_9600,SerialPort.DATABITS_8, SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
		port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
		port.writeString("JSSC Test!"+ls);

		port.addEventListener(this);
		while(true) {}

Maintenant, en ce qui concerne la réception du problème, en conclusion, l'événement pourrait survenir, mais le contenu à recevoir n'est pas clair.

	public void serialEvent(SerialPortEvent arg0) {
		try {
			byte[] bs=port.readBytes();
			System.out.println(bs);
		} catch (SerialPortException e) {
			e.printStackTrace();
		}
	}

Si vous saisissez manuellement "aaabb" à partir du terme Tera, ce qui suit sera renvoyé. C'est facile à comprendre avec un personnage et un événement, mais qu'est-ce que c'est?

[B@1df7e046
[B@19c87720
[B@5ccaea7d
[B@4f8bbf28
[B@6d5c934f

Conclusion

  1. RXTX émet une ERREUR FATALE. Je suis désolé. Il n'est plus entretenu et est en stock!
  2. jSerialComm est instable. Aucune réponse ou levée d'exceptions. Voulez-vous travailler plus dur?
  3. jpurejavacomm ne répond pas à la réception des événements. Est-ce mauvais à utiliser?
  4. jssc pourra peut-être faire quelque chose à ce sujet. Il est nécessaire de scruter le contenu reçu.

Recommended Posts

Puis-je utiliser RXTX? Existe-t-il une alternative?
Comment utiliser Maven que je n'entends plus
Y a-t-il une instance même si le constructeur échoue?
J'ai essayé de résoudre le problème de la machine à karaoké Ruby (il y a un exemple de réponse)
J'ai essayé de résoudre le problème de la boisson bonus Ruby (il y a un exemple de réponse)