Im Trying to create a simple "Game Controller" by connecting a Analog stick to Arduino and processing the sent data in a Java file using Eclipse. Here are the Codes:
Arduino:
int Ver = 0;
int Hor = 0;
int data[2];
void setup(){
Serial.begin(9600);
}
void loop(){
Ver = analogRead(A0); //511 D = 0
Hor = analogRead(A1); //515 L = 0 max = 1023
data[0] = Ver;
data[1] = Hor;
Serial.print("[");
Serial.print(data[0], DEC);
Serial.print(",");
Serial.print(data[1], DEC);
Serial.println("]");
delay(50);
}
Java:
package Controller;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.util.Enumeration;
public class AnalogStick implements SerialPortEventListener {
SerialPort serialPort;
/** The port we're normally going to use. */
private static final String PORT_NAMES[] = { "/dev/tty.usbserial-A9007UX1", // Mac OS X
"/dev/ttyUSB0", // Linux
"COM12", // Windows
};
private BufferedReader input;
private static final int TIME_OUT = 2000;
private static final int DATA_RATE = 9600;
public void initialize() {
CommPortIdentifier portId = null;
Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
// First, Find an instance of serial port as set in PORT_NAMES.
while (portEnum.hasMoreElements()) {
CommPortIdentifier currPortId = (CommPortIdentifier) portEnum
.nextElement();
for (String portName : PORT_NAMES) {
if (currPortId.getName().equals(portName)) {
portId = currPortId;
break;
}
}
}
System.out.println("Port ID: ");
System.out.println(portId);
System.out.println("");
if (portId == null) {
System.out.println("Could not find COM port.");
return;
}
try {
// open serial port, and use class name for the appName.
serialPort = (SerialPort) portId.open(this.getClass().getName(),
TIME_OUT);
// set port parameters
serialPort.setSerialPortParams(DATA_RATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
// open the streams
input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
serialPort.getOutputStream();
// add event listeners
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
} catch (Exception e) {
System.err.println(e.toString());
}
}
public synchronized void close() {
if (serialPort != null) {
serialPort.removeEventListener();
serialPort.close();
}
}
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
String inputLine = input.readLine();
//System.out.println("" + inputLine);
String[] items = inputLine.replaceAll("\\[", "").replaceAll("\\]", "").split(",");
int[] data = new int[items.length];
for (int i = 0; i < items.length; i++) {
try {
data[i] = Integer.parseInt(items[i]);
} catch (NumberFormatException nfe) {};
}
//System.out.println("Ver: " + data[0] + " Hor: " + data[1]);
Robot robot = new Robot();
if(data[0] > 511 + 10 && data[1] < 515 + 169 && data[1] > 515 - 169){
System.out.println("Up");
robot.keyPress(KeyEvent.VK_W);
}
else if(data[0] < 511 - 10 && data[1] < 515 + 169 && data[1] > 515 - 169){
System.out.println("Down");
robot.keyPress(KeyEvent.VK_S);
}
if(data[1] < 515 - 10 && data[0] < 511 + 170 && data[0] > 511 - 170){
System.out.println("Left");
robot.keyPress(KeyEvent.VK_A);
}
else if(data[1] > 515 + 10 && data[0] < 511 + 170 && data[0] > 511 - 170){
System.out.println("Right");
robot.keyPress(KeyEvent.VK_D);
}
} catch (Exception e) {
System.err.println(e.toString());
//System.out.println("failed stuff");
}
}
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
}
}
public static void main(String[] args) throws Exception {
AnalogStick main = new AnalogStick();
main.initialize();
Thread t = new Thread() {
public void run() {
try {
Thread.sleep(5000000);
} catch (InterruptedException ie) {
}
}
};
t.start();
System.out.println("- Started -");
System.out.println("");
}
}
I press run on eclipse, and it works fine, but when I shift my mouse pointer to a different screen or try using the analog stick in a game (therefore switching screens), i get the following Error and the analog stick stops functioning within the game:
java.io.IOException: Underlying input stream returned zero bytes
I have a feeling that this error is caused by having too many data sent to the PC before the analog stick is able to process a single input line, but I am not sure since this is the first time I am working with a analog stick. Can somebody teach me
1) Why its not working as I expect it to work
2) How to fix this error
and
3) If there is a better way to program a analog stick, tell me how and/or show me a reference website
Thanks in advance
Related
I tried to run the sample code from:
https://learn.microsoft.com/en-us/azure/cognitive-services/speech-service/how-to-async-conversation-transcription
implementing helper class from:
https://github.com/Azure-Samples/cognitive-services-speech-sdk/blob/master/samples/java/jre/console/src/com/microsoft/cognitiveservices/speech/samples/console/WavStream.java
with some slight modifications so that it can read in wav files not limited to 16kHz 16bit single channel, and when I run it, this comes up:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Conversation transcriber canceled:SessionId:b2496d2c13424b3ba3138f2c8ce0893f ResultId:258796dbc69d491786f3ccdd8ec708d6 CancellationReason:Error CancellationErrorCode:ConnectionFailure Error details:<Connection failed (no connection to the remote host). Internal error: 1. Error details: 11001. Please check network connection, firewall setting, and the region name used to create speech factory. SessionId: b2496d2c13424b3ba3138f2c8ce0893f
Conversation transcriber stopped:SessionId: b2496d2c13424b3ba3138f2c8ce0893f.
I'm pretty sure that the API key and the region setup are correct and running and the Internet configuration isn't having any problem.
Here are the codes:
Main.java:
package speechsdk.quickstart;
import com.azure.core.util.polling.PollerFlux;
import com.azure.core.util.polling.SyncPoller;
import com.microsoft.cognitiveservices.speech.*;
import com.microsoft.cognitiveservices.speech.audio.*;
import com.microsoft.cognitiveservices.speech.remoteconversation.RemoteConversationTranscriptionClient;
import com.microsoft.cognitiveservices.speech.remoteconversation.RemoteConversationTranscriptionOperation;
import com.microsoft.cognitiveservices.speech.remoteconversation.RemoteConversationTranscriptionResult;
import com.microsoft.cognitiveservices.speech.transcription.Conversation;
import com.microsoft.cognitiveservices.speech.transcription.ConversationTranscriber;
import com.microsoft.cognitiveservices.speech.transcription.ConversationTranscriptionResult;
import javax.sound.sampled.AudioFileFormat;
import java.io.FileInputStream;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* Quickstart: recognize speech using the Speech SDK for Java.
*/
public class Main {
/**
* #param args Arguments are ignored in this sample.
*/
public static void main(String[] args) {
try {
// Create the speech config object
SpeechConfig speechConfig = SpeechConfig.fromSubscription("APIKEY", "SERVICEREGION");
speechConfig.setProperty("ConversationTranscriptionInRoomAndOnline", "true");
// Set the property for asynchronous transcription
speechConfig.setServiceProperty("transcriptionMode", "Async", ServicePropertyChannel.UriQueryParameter);
// Set the property for real-time plus asynchronous transcription
//speechConfig.setServiceProperty("transcriptionMode", "RealTimeAndAsync", ServicePropertyChannel.UriQueryParameter);
// pick a conversation Id that is a GUID.
String conversationId = UUID.randomUUID().toString();
// Create a Conversation
Conversation conversation = new Conversation(speechConfig, conversationId);
// Create an audio stream from a wav file or from the default microphone if you want to stream live audio from the supported devices
// Replace with your own audio file name and Helper class which implements AudioConfig using PullAudioInputStreamCallback
WavStream wavStream = new WavStream(new FileInputStream("sample.wav"));
PullAudioInputStreamCallback wavfilePullStreamCallback = wavStream;
// Create an audio stream format assuming the file used above is 16Khz, 16 bits and 8 channel pcm wav file
//AudioStreamFormat audioStreamFormat = AudioStreamFormat.getWaveFormatPCM((long)16000, (short)16,(short)8);
AudioStreamFormat audioStreamFormat = AudioStreamFormat.getWaveFormatPCM(wavStream.getSamplespersecond(), (short) wavStream.getBitspersample(), (short) wavStream.getChannel());
// Create an input stream
AudioInputStream audioStream = AudioInputStream.createPullStream(wavfilePullStreamCallback, audioStreamFormat);
// Create a conversation transcriber
ConversationTranscriber transcriber = new ConversationTranscriber(AudioConfig.fromStreamInput(audioStream));
// join a conversation
transcriber.joinConversationAsync(conversation);
// Add the event listener for the realtime events
transcriber.transcribed.addEventListener((o, e) -> {
System.out.println("Conversation transcriber Recognized:" + e.toString());
});
transcriber.canceled.addEventListener((o, e) -> {
System.out.println("Conversation transcriber canceled:" + e.toString());
try {
transcriber.stopTranscribingAsync().get();
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (ExecutionException ex) {
ex.printStackTrace();
}
});
transcriber.sessionStopped.addEventListener((o, e) -> {
System.out.println("Conversation transcriber stopped:" + e.toString());
try {
transcriber.stopTranscribingAsync().get();
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (ExecutionException ex) {
ex.printStackTrace();
}
});
// start the transcription.
Future<?> future = transcriber.startTranscribingAsync();
// Create a remote Conversation Transcription client
RemoteConversationTranscriptionClient client = new RemoteConversationTranscriptionClient(speechConfig);
// Get the PollerFlux for the remote operation
PollerFlux<RemoteConversationTranscriptionOperation, RemoteConversationTranscriptionResult> remoteTranscriptionOperation = client.getTranscriptionOperation(conversationId);
// Subscribe to PollerFlux to get the remote operation status
remoteTranscriptionOperation.subscribe(
pollResponse -> {
System.out.println("Poll response status : " + pollResponse.getStatus());
System.out.println("Poll response status : " + pollResponse.getValue().getServiceStatus());
}
);
// Obtain the blocking operation using getSyncPoller
SyncPoller<RemoteConversationTranscriptionOperation, RemoteConversationTranscriptionResult> blockingOperation = remoteTranscriptionOperation.getSyncPoller();
// Wait for the operation to finish
blockingOperation.waitForCompletion();
// Get the final result response
RemoteConversationTranscriptionResult resultResponse = blockingOperation.getFinalResult();
// Print the result
if(resultResponse != null) {
if(resultResponse.getConversationTranscriptionResults() != null) {
for (int i = 0; i < resultResponse.getConversationTranscriptionResults().size(); i++) {
ConversationTranscriptionResult result = resultResponse.getConversationTranscriptionResults().get(i);
System.out.println(result.getProperties().getProperty(PropertyId.SpeechServiceResponse_JsonResult.name()));
System.out.println(result.getProperties().getProperty(PropertyId.SpeechServiceResponse_JsonResult));
System.out.println(result.getOffset());
System.out.println(result.getDuration());
System.out.println(result.getUserId());
System.out.println(result.getReason());
System.out.println(result.getResultId());
System.out.println(result.getText());
System.out.println(result.toString());
}
}
}
System.out.println("Operation finished");
} catch (Exception ex) {
//System.out.println("Unexpected exception: " + ex.getMessage());
ex.printStackTrace();
assert(false);
System.exit(1);
}
}
}
Helper.java:
package speechsdk.quickstart;
import com.microsoft.cognitiveservices.speech.audio.PullAudioInputStreamCallback;
import com.microsoft.cognitiveservices.speech.internal.AudioConfig;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.slf4j.*;
class WavStream extends PullAudioInputStreamCallback {
private final InputStream stream;
private long samplespersecond;
private int bitspersample;
private int channel;
public long getSamplespersecond()
{
return samplespersecond;
}
public int getBitspersample()
{
return bitspersample;
}
public int getChannel()
{
return channel;
}
public WavStream(InputStream wavStream) {
try {
this.stream = parseWavHeader(wavStream);
} catch (Exception ex) {
throw new IllegalArgumentException(ex.getMessage());
}
}
#Override
public int read(byte[] dataBuffer) {
long ret = 0;
try {
ret = this.stream.read(dataBuffer, 0, dataBuffer.length);
} catch (Exception ex) {
System.out.println("Read " + ex);
}
return (int)Math.max(0, ret);
}
#Override
public void close() {
try {
this.stream.close();
} catch (IOException ex) {
// ignored
}
}
// endregion
// region Wav File helper functions
private int ReadInt32(InputStream inputStream) throws IOException {
int n = 0;
for (int i = 0; i < 4; i++) {
n |= inputStream.read() << (i * 8);
}
return n;
}
private long ReadUInt32(InputStream inputStream) throws IOException {
long n = 0;
for (int i = 0; i < 4; i++) {
n |= inputStream.read() << (i * 8);
}
return n;
}
private int ReadUInt16(InputStream inputStream) throws IOException {
int n = 0;
for (int i = 0; i < 2; i++) {
n |= inputStream.read() << (i * 8);
}
return n;
}
public InputStream parseWavHeader(InputStream reader) throws IOException {
// Note: assumption about order of chunks
// Tag "RIFF"
byte data[] = new byte[4];
int numRead = reader.read(data, 0, 4);
ThrowIfFalse((numRead == 4) && (data[0] == 'R') && (data[1] == 'I') && (data[2] == 'F') && (data[3] == 'F'), "RIFF");
// Chunk size
/* int fileLength = */ReadInt32(reader);
// Subchunk, Wave Header
// Subchunk, Format
// Tag: "WAVE"
numRead = reader.read(data, 0, 4);
ThrowIfFalse((numRead == 4) && (data[0] == 'W') && (data[1] == 'A') && (data[2] == 'V') && (data[3] == 'E'), "WAVE");
// Tag: "fmt"
numRead = reader.read(data, 0, 4);
ThrowIfFalse((numRead == 4) && (data[0] == 'f') && (data[1] == 'm') && (data[2] == 't') && (data[3] == ' '), "fmt ");
// chunk format size
long formatSize = ReadInt32(reader);
ThrowIfFalse(formatSize >= 16, "formatSize");
int formatTag = ReadUInt16(reader);
int channels = ReadUInt16(reader);
int samplesPerSec = (int) ReadUInt32(reader);
int avgBytesPerSec = (int) ReadUInt32(reader);
int blockAlign = ReadUInt16(reader);
int bitsPerSample = ReadUInt16(reader);
ThrowIfFalse(formatTag == 1, "PCM"); // PCM
//ThrowIfFalse(channels == 1, "single channel");
channel = channels;
//ThrowIfFalse(samplesPerSec == 16000, "samples per second");
samplespersecond = samplesPerSec;
//ThrowIfFalse(bitsPerSample == 16, "bits per sample");
bitspersample = bitsPerSample;
// Until now we have read 16 bytes in format, the rest is cbSize and is ignored
// for now.
if (formatSize > 16) {
numRead = reader.read(new byte[(int) (formatSize - 16)]);
ThrowIfFalse(numRead == (int)(formatSize - 16), "could not skip extended format");
}
// Second Chunk, data
// tag: data.
numRead = reader.read(data, 0, 4);
//for (byte i : data) System.out.print((char) i);
//System.out.println();
//ThrowIfFalse((numRead == 4) && (data[0] == 'd') && (data[1] == 'a') && (data[2] == 't') && (data[3] == 'a'), "data");
// data chunk size
// Note: assumption is that only a single data chunk
/* int dataLength = */ReadInt32(reader);
numRead = reader.read(data, 0, 4);
while (!((numRead == 4) && (data[0] == 'd') && (data[1] == 'a') && (data[2] == 't') && (data[3] == 'a')))
{
numRead = reader.read(data, 0, 4);
//for (byte i : data) System.out.print((char) i);
//System.out.println();
ReadInt32(reader);
}
//for (byte i : data) System.out.println((char) i);
return reader;
}
private static void ThrowIfFalse(Boolean condition, String message) {
if (!condition) {
throw new IllegalArgumentException(message);
}
}
// endregion
}
Using azure document, if you can please configure the following and provide us the log.
config.setProperty(PropertyId.Speech_LogFilename, "LogfilePathAndName");
By the way, what is the region you are using to do the transcription?
For conversation transcription, the input wave file should be 8 channel, 16 bits and 16 Khz wave file. Try putting a sleep after the following code till you get the session stopped called.
// start the transcription.
Future<?> future = transcriber.startTranscribingAsync();
Also if possible change the following code to
PollerFlux<RemoteConversationTranscriptionOperation, RemoteConversationTranscriptionResult> remoteTranscriptionOperation = client.getTranscriptionOperation(conversationId,5);
Do let us know if it works.
I'm using Raspbian on a Raspberry Pi 3. I'm learning how to code in Java (SE runtime version 1.8.0_65), and I need to communicate raw data with a USB connected Bill Acceptor. According to the manufacturer's documentation, the USB unit mimics a serial-type interface. When I plug the device in, it appears in /dev/serial/by-id. I wrote C code 20+ years ago using modems on SCO Unix setups. If memory serves, I basically treated the modems /dev/ttyxx as a file for reading and writing. I wrote a C++ program 10+ years ago on Windows XP using a similar Bill Acceptor unit (same manufacturer and model) connected to a serial port instead of USB. The documentation shows both USB and serial units use the same data strings for input and output, so I know the SendString data should be correct for triggering a valid response. However, I'm not getting a reply from the unit, so I'm guessing I'm not connecting properly to it.
Here is the code...
public static void main(String[] args) {
try
{
System.out.println("*****************************");
System.out.println("***** Starting Program *****");
System.out.println("*****************************");
String strUsbDeviceDir = "/dev/serial/by-id";
File myUsbDeviceDir = new File(strUsbDeviceDir);
if(myUsbDeviceDir.exists())
{
String[] myUsbDevices = myUsbDeviceDir.list();
for(int i=0; i<myUsbDevices.length; i++)
{
if(myUsbDevices[i].contains("EBDS_over_USB"))
{
System.out.println("Connecting to " + myUsbDevices[i]);
funcBillAcceptor(strUsbDeviceDir + "/" + myUsbDevices[i]);
}
else
{
System.out.println("Not using " + myUsbDevices[i]);
}
}
}
}
catch (Exception ex)
{
System.err.println(ex.toString());
}
}
public static void funcBillAcceptor(String strBillAcceptor)
{
boolean bOddCount = false;
byte[] SendString = new byte[8];
byte[] RecvString = new byte[10];
byte CheckDigit;
int iSendStringCount, iRecvStringCount, iRecvEmptyCount;
try
{
File fBillAcceptor = new File(strBillAcceptor);
if(!fBillAcceptor.canRead())
{
System.out.println("No Read Permission for " + strBillAcceptor);
return;
}
if(!fBillAcceptor.canWrite())
{
System.out.println("No Write Permission for " + strBillAcceptor);
return;
}
RandomAccessFile rafBillAcceptor = new RandomAccessFile(strBillAcceptor, "rwd");
if(rafBillAcceptor != null)
{
System.out.println("Successfully opened " + strBillAcceptor);
}
while(fBillAcceptor.exists())
{
SendString[0] = (byte) 0x02; //STX
SendString[1] = (byte) 0x08;
if(bOddCount)
{
SendString[2] = (byte) 0x10;
bOddCount = false;
}
else
{
SendString[2] = (byte) 0x11;
bOddCount = true;
}
SendString[3] = (byte) 0x1F;
SendString[4] = (byte) 0x0C;
SendString[5] = (byte) 0x00;
SendString[6] = (byte) 0x03; //ETX
//CheckDigit skips STX (byte 0) with byte 1 as seed/initial value
//To calculate the check digit, start with next byte (2)
CheckDigit = SendString[1];
iSendStringCount = 2;
while(SendString[iSendStringCount] != 0x03)
{
CheckDigit = (byte) (SendString[iSendStringCount]^CheckDigit); //XOR current CheckDigit value with next byte
iSendStringCount++;
}
iSendStringCount++; //advance one more so we don't overwrite ETX
SendString[iSendStringCount] = (byte) CheckDigit;
try
{
rafBillAcceptor.write(SendString);
System.out.println("Sent: " + DatatypeConverter.printHexBinary(SendString));
}
catch (Exception ex)
{
System.err.println("Write exception: " + ex.toString());
}
System.out.println("Reading...");
iRecvStringCount = iRecvEmptyCount = 0;
try
{
do
{
iRecvStringCount = rafBillAcceptor.read(RecvString);
System.out.println("Read " + iRecvStringCount + " bytes.");
if(iRecvStringCount < 0)
{
iRecvEmptyCount++;
Thread.sleep(5);
}
} while (iRecvStringCount < 0 && iRecvEmptyCount < 100);
if(iRecvStringCount > 0)
{
System.out.println("Received: " + DatatypeConverter.printHexBinary(RecvString));
}
}
catch (Exception ex)
{
System.err.println("Read exception: " + ex.toString());
}
}
}
catch (Exception ex)
{
System.err.println(ex.toString());
}
}
Here is the output I'm getting...
*****************************
***** Starting Program *****
*****************************
Connecting to usb-Silicon_Labs_Series_2000_Bill_Acceptor__EBDS_over_USB__46580120748-if00-port0
Successfully opened /dev/serial/by-id/usb-Silicon_Labs_Series_2000_Bill_Acceptor__EBDS_over_USB__46580120748-if00-port0
Sent: 0208111F0C00030A
Reading...
Am I missing something obvious, or just going about this all wrong? Thanks for any suggestions!
I was able to successfully communicate with the Bill Acceptor from a Raspberry Pi 3 (running Raspbian) using the RXTXComm library. When communicating with the device from an old Windows XP computer using a 9-pin serial/RS232 harness, I had to use 9600/7/E/1. If I don't use those values for setSerialPortParams (in my sample code), I'm not able to correctly send/receive data. So, you need to know what the device is expecting in order to use this approach with other "serial" hardware connected via USB. Below is code with the basic functionality. I started with one of the sample programs that come with the RXTXComm library and built out from there. Since this is a sample program, I haven't yet added logic to verify the checksum digit for data coming from the device.
You may notice at the bottom of the code that I'm able to determine the /dev/ttyUSBx using the canonical name of the device that I pull from the /dev/serial/by-id directory/folder. It finds the correct device name regardless of which USB port the unit is plugged in to or what order the USB devices get initialized by the system. I have a card dispenser that is also a USB serial device, so I was able to test and confirm this functionality.
public TwoWaySerialComm()
{
super();
}
static boolean bReadyToSend = false;
void connect ( String portName ) throws Exception
{
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if ( portIdentifier.isCurrentlyOwned() )
{
System.out.println("Error: " + portName + " is currently in use.");
}
else
{
CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
if ( commPort instanceof SerialPort )
{
SerialPort serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(9600, SerialPort.DATABITS_7, SerialPort.STOPBITS_1, SerialPort.PARITY_EVEN);
InputStream in = serialPort.getInputStream();
OutputStream out = serialPort.getOutputStream();
// Thread handling logic
// https://www.javaspecialists.eu/archive/Issue056.html
Thread readThread = new Thread(new SerialReader(in));
readThread.start();
Thread writeThread = new Thread(new SerialWriter(out));
writeThread.start();
// Running threads for 10 seconds then stopping to ensure threads are shutting down
long threadCurrTime = System.currentTimeMillis();
long threadStartTime = System.currentTimeMillis();
while( (threadCurrTime - threadStartTime) < 10000)
{
try
{
Thread.sleep(100);
}
catch (InterruptedException ex)
{
Logger.getLogger(TwoWaySerialComm.class.getName()).log(Level.SEVERE, null, ex);
}
threadCurrTime = System.currentTimeMillis();
}
if(writeThread.isAlive())
{
//System.out.println("Sending interrupt to SerialWriter thread...");
writeThread.interrupt();
writeThread.join();
//System.out.println("SerialWriter thread is shut down.");
}
//else
//{
// System.out.println("SerialWriter thread is already shut down.");
//}
if(readThread.isAlive())
{
//System.out.println("Sending interrupt to SerialReader thread...");
readThread.interrupt();
readThread.join();
//System.out.println("SerialReader thread is shut down.");
}
//else
//{
// System.out.println("SerialReader thread is already shut down.");
//}
commPort.close();
}
else
{
System.out.println("Error: " + portName + " is not recognized as a valid serial device.");
}
}
}
/* SerialReader thread logic */
public static class SerialReader implements Runnable
{
InputStream in;
boolean bShuttingDown = false;
public SerialReader ( InputStream in )
{
this.in = in;
}
public void run ()
{
byte[] RecvString = new byte[12];
String strResponse;
int len = -1;
try
{
while (!bShuttingDown)
{
len = this.in.read(RecvString);
if( len > -1 )
{
strResponse = "";
if(RecvString[0] == 0x02 && RecvString[9] == 0x03)
{
if(RecvString[3] == 0x00 && RecvString[4] == 0x00 && RecvString[5] == 0x00 && RecvString[6] == 0x00)
{
strResponse = "Device not ready.";
}
else
{
//-- RecvString[3]------------------
if(RecvString[3] == 0x01)
strResponse = " - Idling";
else
if(RecvString[3] == 0x02)
strResponse = " - Accepting";
else
if(RecvString[3] == 0x04)
{
strResponse = " - Escrowed";
if(RecvString[5] == 0x08)
strResponse += " $1";
else
if(RecvString[5] == 0x10)
strResponse += " $2";
else
if(RecvString[5] == 0x18)
strResponse += " $5";
else
if(RecvString[5] == 0x20)
strResponse += " $10";
else
if(RecvString[5] == 0x28)
strResponse += " $20";
else
strResponse += " unrecognized bill inserted";
}
else
if(RecvString[3] == 0x08)
strResponse = " - Stacking";
else
if(RecvString[3] == 0x10)
strResponse = " - Stacked";
else
if(RecvString[3] == 0x11)
strResponse = " - Returning";
else
if(RecvString[3] == 0x12)
strResponse = " - Returned";
//-- RecvString[4]------------------
if(RecvString[4] == 0x01)
strResponse += " - Cheated";
else
if(RecvString[4] == 0x02)
strResponse += " - Rejected";
else
if(RecvString[4] == 0x04)
strResponse += " - Jammed";
else
if(RecvString[4] == 0x08)
strResponse += " - Bill Stacker Full";
else
if(RecvString[4] == 0x10)
strResponse += " - Removable Cassette Installed";
else
if(RecvString[4] == 0x11)
strResponse += " - Reserved";
else
if(RecvString[4] == 0x12)
strResponse += " - Calibration mode";
//-- RecvString[5]------------------
if(RecvString[5] == 0x01)
strResponse += " - Power Up Reset";
else
if(RecvString[5] == 0x02)
strResponse += " - Invalid Command";
else
if(RecvString[5] == 0x04)
strResponse += " - Non-recoverable fault";
}
if(!strResponse.contains("Idling"))
System.out.println("Recv: " + DatatypeConverter.printHexBinary(RecvString) + strResponse);
}
else
{
System.out.println("Recv (invalid): " + DatatypeConverter.printHexBinary(RecvString));
}
try
{
Thread.sleep(100); // need this delay before we send next polling message, otherwise the data doesn't come in correctly
bReadyToSend = true;
}
catch (InterruptedException ex)
{
Thread.currentThread().interrupt();
//System.out.println("Shut down SerialReader thread.");
bShuttingDown = true;
break;
}
}
}
}
catch ( IOException ex )
{
System.out.println("Recv exception: " + ex.toString());
}
}
}
/* SerialWriter thread logic */
public static class SerialWriter implements Runnable
{
OutputStream out;
long lastSendTime = System.currentTimeMillis() - 1001;
long currSendTime;
byte[] SendString = new byte[8];
byte CheckDigit;
int iSendStringCount;
boolean bOddCount = true;
boolean bShuttingDown = false;
public SerialWriter ( OutputStream out )
{
this.out = out;
}
public void run ()
{
while(!bShuttingDown)
{
currSendTime = System.currentTimeMillis();
if(currSendTime - lastSendTime > 1000) // if it's been more than a second, send query string
bReadyToSend = true;
if(bReadyToSend)
{
SendString[0] = (byte) 0x02; //STX
SendString[1] = (byte) 0x08;
if(bOddCount)
{
SendString[2] = (byte) 0x10;
bOddCount = false;
}
else
{
SendString[2] = (byte) 0x11;
bOddCount = true;
}
SendString[3] = (byte) 0x7F;
SendString[4] = (byte) 0x1C;
SendString[5] = (byte) 0x00;
SendString[6] = (byte) 0x03; //ETX
//CheckDigit skips STX (byte 0) with byte 1 as seed/initial value
//To calculate the check digit, start with next byte (2)
CheckDigit = SendString[1];
iSendStringCount = 2;
while(SendString[iSendStringCount] != 0x03)
{
CheckDigit = (byte) (SendString[iSendStringCount]^CheckDigit); //XOR current CheckDigit value with next byte
iSendStringCount++;
}
iSendStringCount++; //advance one more so we don't overwrite ETX
SendString[iSendStringCount] = (byte) CheckDigit;
try
{
lastSendTime = System.currentTimeMillis();
this.out.write(SendString);
//System.out.println("Sent: " + DatatypeConverter.printHexBinary(SendString));
}
catch ( IOException ex )
{
System.out.println("Send exception: " + ex.toString());
}
try
{
Thread.sleep(1); // this is hear simply to catch an external interrupt
}
catch (InterruptedException ex)
{
Thread.currentThread().interrupt();
//System.out.println("Shut down SerialWriter thread.");
bShuttingDown = true;
break;
}
bReadyToSend = false;
}
}
}
}
public static void main ( String[] args )
{
try
{
System.out.println("*****************************");
System.out.println("***** Starting Program *****");
System.out.println("*****************************");
String strUsbDeviceDir = "/dev/serial/by-id";
File myUsbDeviceDir = new File(strUsbDeviceDir);
if(myUsbDeviceDir.exists())
{
String[] myUsbDevices = myUsbDeviceDir.list();
for(int i=0; i<myUsbDevices.length; i++)
{
if(myUsbDevices[i].contains("EBDS_over_USB"))
{
File tempFile = new File(strUsbDeviceDir + "/" + myUsbDevices[i]);
String usbCanonicalName = tempFile.getCanonicalFile().toString(); //gives me /dev/ttyUSBx where 'x' is the USB device number
System.out.println("Connecting to " + usbCanonicalName + " (" + myUsbDevices[i] + ")");
(new TwoWaySerialComm()).connect(usbCanonicalName);
}
else
{
System.out.println("Not using " + myUsbDevices[i]);
}
}
}
}
catch ( Exception ex )
{
System.out.println("Connect exception: " + ex.toString());
}
System.out.println("*****************************");
System.out.println("***** Program Finished ******");
System.out.println("*****************************");
}
Output when I put a $1 bill in (I'm developing/compiling from NetBeans IDE 8.2 on Windows 10 Pro and running using remote debugging on the RPi3. I'm guessing that's the source of the RXTX Version mismatch warning):
*****************************
***** Starting Program *****
*****************************
Connecting to /dev/ttyUSB0 (usb-Silicon_Labs_Series_2000_Bill_Acceptor__EBDS_over_USB__46580120748-if00-port0)
Stable Library
=========================================
Native lib Version = RXTX-2.2pre2
Java lib Version = RXTX-2.1-7
WARNING: RXTX Version mismatch
Jar version = RXTX-2.1-7
native lib Version = RXTX-2.2pre2
Recv (invalid): 020000000000000000000000
Recv (invalid): 0B2001100800503603540000
Recv: 020B20041008005036035100 - Escrowed $1 - Removable Cassette Installed
*****************************
***** Program Finished ******
*****************************
I hope this description and sample code can help someone else.
I'm trying to read gmail messages using showmsg.java in the javamail sample package, and I keep getting this error when I run it. The program compiles fine though.
Here's the error message:
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: javax/mail/internet/ParseException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: javax.mail.internet.ParseException
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 7 more
Here's the code:
import java.util.*;
import java.io.*;
import javax.mail.*;
import javax.mail.event.*;
import javax.mail.internet.*;
/*
* Demo app that exercises the Message interfaces.
* Show information about and contents of messages.
*
* #author John Mani
* #author Bill Shannon
*/
public class msgshow {
static String protocol;
static String host = null;
static String user = null;
static String password = null;
static String mbox = null;
static String url = null;
static int port = -1;
static boolean verbose = false;
static boolean debug = false;
static boolean showStructure = false;
static boolean showMessage = false;
static boolean showAlert = false;
static boolean saveAttachments = false;
static int attnum = 1;
public static void main(String argv[]) {
int optind;
InputStream msgStream = System.in;
for (optind = 0; optind < argv.length; optind++) {
if (argv[optind].equals("-T")) {
protocol = argv[++optind];
} else if (argv[optind].equals("-H")) {
host = argv[++optind];
} else if (argv[optind].equals("-U")) {
user = argv[++optind];
} else if (argv[optind].equals("-P")) {
password = argv[++optind];
} else if (argv[optind].equals("-v")) {
verbose = true;
} else if (argv[optind].equals("-D")) {
debug = true;
} else if (argv[optind].equals("-f")) {
mbox = argv[++optind];
} else if (argv[optind].equals("-L")) {
url = argv[++optind];
} else if (argv[optind].equals("-p")) {
port = Integer.parseInt(argv[++optind]);
} else if (argv[optind].equals("-s")) {
showStructure = true;
} else if (argv[optind].equals("-S")) {
saveAttachments = true;
} else if (argv[optind].equals("-m")) {
showMessage = true;
} else if (argv[optind].equals("-a")) {
showAlert = true;
} else if (argv[optind].equals("--")) {
optind++;
break;
} else if (argv[optind].startsWith("-")) {
System.out.println(
"Usage: msgshow [-L url] [-T protocol] [-H host] [-p port] [-U user]");
System.out.println(
"\t[-P password] [-f mailbox] [msgnum ...] [-v] [-D] [-s] [-S] [-a]");
System.out.println(
"or msgshow -m [-v] [-D] [-s] [-S] [-f msg-file]");
System.exit(1);
} else {
break;
}
}
try {
// Get a Properties object
Properties props = System.getProperties();
// Get a Session object
Session session = Session.getInstance(props, null);
session.setDebug(debug);
if (showMessage) {
MimeMessage msg;
if (mbox != null)
msg = new MimeMessage(session,
new BufferedInputStream(new FileInputStream(mbox)));
else
msg = new MimeMessage(session, msgStream);
dumpPart(msg);
System.exit(0);
}
// Get a Store object
Store store = null;
if (url != null) {
URLName urln = new URLName(url);
store = session.getStore(urln);
if (showAlert) {
store.addStoreListener(new StoreListener() {
public void notification(StoreEvent e) {
String s;
if (e.getMessageType() == StoreEvent.ALERT)
s = "ALERT: ";
else
s = "NOTICE: ";
System.out.println(s + e.getMessage());
}
});
}
store.connect();
} else {
if (protocol != null)
store = session.getStore(protocol);
else
store = session.getStore();
// Connect
if (host != null || user != null || password != null)
store.connect(host, port, user, password);
else
store.connect();
}
// Open the Folder
Folder folder = store.getDefaultFolder();
if (folder == null) {
System.out.println("No default folder");
System.exit(1);
}
if (mbox == null)
mbox = "INBOX";
folder = folder.getFolder(mbox);
if (folder == null) {
System.out.println("Invalid folder");
System.exit(1);
}
// try to open read/write and if that fails try read-only
try {
folder.open(Folder.READ_WRITE);
} catch (MessagingException ex) {
folder.open(Folder.READ_ONLY);
}
int totalMessages = folder.getMessageCount();
if (totalMessages == 0) {
System.out.println("Empty folder");
folder.close(false);
store.close();
System.exit(1);
}
if (verbose) {
int newMessages = folder.getNewMessageCount();
System.out.println("Total messages = " + totalMessages);
System.out.println("New messages = " + newMessages);
System.out.println("-------------------------------");
}
if (optind >= argv.length) {
// Attributes & Flags for all messages ..
Message[] msgs = folder.getMessages();
// Use a suitable FetchProfile
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.ENVELOPE);
fp.add(FetchProfile.Item.FLAGS);
fp.add("X-Mailer");
folder.fetch(msgs, fp);
for (int i = 0; i < msgs.length; i++) {
System.out.println("--------------------------");
System.out.println("MESSAGE #" + (i + 1) + ":");
dumpEnvelope(msgs[i]);
// dumpPart(msgs[i]);
}
} else {
while (optind < argv.length) {
int msgnum = Integer.parseInt(argv[optind++]);
System.out.println("Getting message number: " + msgnum);
Message m = null;
try {
m = folder.getMessage(msgnum);
dumpPart(m);
} catch (IndexOutOfBoundsException iex) {
System.out.println("Message number out of range");
}
}
}
folder.close(false);
store.close();
} catch (Exception ex) {
System.out.println("Oops, got exception! " + ex.getMessage());
ex.printStackTrace();
System.exit(1);
}
System.exit(0);
}
public static void dumpPart(Part p) throws Exception {
if (p instanceof Message)
dumpEnvelope((Message)p);
/** Dump input stream ..
InputStream is = p.getInputStream();
// If "is" is not already buffered, wrap a BufferedInputStream
// around it.
if (!(is instanceof BufferedInputStream))
is = new BufferedInputStream(is);
int c;
while ((c = is.read()) != -1)
System.out.write(c);
**/
String ct = p.getContentType();
try {
pr("CONTENT-TYPE: " + (new ContentType(ct)).toString());
} catch (ParseException pex) {
pr("BAD CONTENT-TYPE: " + ct);
}
String filename = p.getFileName();
if (filename != null)
pr("FILENAME: " + filename);
/*
* Using isMimeType to determine the content type avoids
* fetching the actual content data until we need it.
*/
if (p.isMimeType("text/plain")) {
pr("This is plain text");
pr("---------------------------");
if (!showStructure && !saveAttachments)
System.out.println((String)p.getContent());
} else if (p.isMimeType("multipart/*")) {
pr("This is a Multipart");
pr("---------------------------");
Multipart mp = (Multipart)p.getContent();
level++;
int count = mp.getCount();
for (int i = 0; i < count; i++)
dumpPart(mp.getBodyPart(i));
level--;
} else if (p.isMimeType("message/rfc822")) {
pr("This is a Nested Message");
pr("---------------------------");
level++;
dumpPart((Part)p.getContent());
level--;
} else {
if (!showStructure && !saveAttachments) {
/*
* If we actually want to see the data, and it's not a
* MIME type we know, fetch it and check its Java type.
*/
Object o = p.getContent();
if (o instanceof String) {
pr("This is a string");
pr("---------------------------");
System.out.println((String)o);
} else if (o instanceof InputStream) {
pr("This is just an input stream");
pr("---------------------------");
InputStream is = (InputStream)o;
int c;
while ((c = is.read()) != -1)
System.out.write(c);
} else {
pr("This is an unknown type");
pr("---------------------------");
pr(o.toString());
}
} else {
// just a separator
pr("---------------------------");
}
}
/*
* If we're saving attachments, write out anything that
* looks like an attachment into an appropriately named
* file. Don't overwrite existing files to prevent
* mistakes.
*/
if (saveAttachments && level != 0 && p instanceof MimeBodyPart &&
!p.isMimeType("multipart/*")) {
String disp = p.getDisposition();
// many mailers don't include a Content-Disposition
if (disp == null || disp.equalsIgnoreCase(Part.ATTACHMENT)) {
if (filename == null)
filename = "Attachment" + attnum++;
pr("Saving attachment to file " + filename);
try {
File f = new File(filename);
if (f.exists())
// XXX - could try a series of names
throw new IOException("file exists");
((MimeBodyPart)p).saveFile(f);
} catch (IOException ex) {
pr("Failed to save attachment: " + ex);
}
pr("---------------------------");
}
}
}
public static void dumpEnvelope(Message m) throws Exception {
pr("This is the message envelope");
pr("---------------------------");
Address[] a;
// FROM
if ((a = m.getFrom()) != null) {
for (int j = 0; j < a.length; j++)
pr("FROM: " + a[j].toString());
}
// REPLY TO
if ((a = m.getReplyTo()) != null) {
for (int j = 0; j < a.length; j++)
pr("REPLY TO: " + a[j].toString());
}
// TO
if ((a = m.getRecipients(Message.RecipientType.TO)) != null) {
for (int j = 0; j < a.length; j++) {
pr("TO: " + a[j].toString());
InternetAddress ia = (InternetAddress)a[j];
if (ia.isGroup()) {
InternetAddress[] aa = ia.getGroup(false);
for (int k = 0; k < aa.length; k++)
pr(" GROUP: " + aa[k].toString());
}
}
}
// SUBJECT
pr("SUBJECT: " + m.getSubject());
// DATE
Date d = m.getSentDate();
pr("SendDate: " +
(d != null ? d.toString() : "UNKNOWN"));
// FLAGS
Flags flags = m.getFlags();
StringBuffer sb = new StringBuffer();
Flags.Flag[] sf = flags.getSystemFlags(); // get the system flags
boolean first = true;
for (int i = 0; i < sf.length; i++) {
String s;
Flags.Flag f = sf[i];
if (f == Flags.Flag.ANSWERED)
s = "\\Answered";
else if (f == Flags.Flag.DELETED)
s = "\\Deleted";
else if (f == Flags.Flag.DRAFT)
s = "\\Draft";
else if (f == Flags.Flag.FLAGGED)
s = "\\Flagged";
else if (f == Flags.Flag.RECENT)
s = "\\Recent";
else if (f == Flags.Flag.SEEN)
s = "\\Seen";
else
continue; // skip it
if (first)
first = false;
else
sb.append(' ');
sb.append(s);
}
String[] uf = flags.getUserFlags(); // get the user flag strings
for (int i = 0; i < uf.length; i++) {
if (first)
first = false;
else
sb.append(' ');
sb.append(uf[i]);
}
pr("FLAGS: " + sb.toString());
// X-MAILER
String[] hdrs = m.getHeader("X-Mailer");
if (hdrs != null)
pr("X-Mailer: " + hdrs[0]);
else
pr("X-Mailer NOT available");
}
static String indentStr = " ";
static int level = 0;
/**
* Print a, possibly indented, string.
*/
public static void pr(String s) {
if (showStructure)
System.out.print(indentStr.substring(0, level * 2));
System.out.println(s);
}
}
The command I'm using to run is java msgshow -D -T imaps -H imap.gmail.com -U [USER] -P [PASS] and the command I'm using to compile it is javac -cp ".:./:./lib:./lib/*" msgshow.java. The javax.mail.jar is contained in the lib folder
This is some alternate code that's much shorter and gets the same errors:
import java.util.*;
import java.io.*;
import javax.mail.*;
import smtp;
import imaps;
//import java.mail.*;
//import com.sun.mail.*;
public class AccessGmail {
public static void main (String[] args) {
Scanner scan = new Scanner(System.in);
try
{
Properties prop = new Properties();
prop.load(new FileInputStream(new File("smtp.properties")));
Session session = Session.getDefaultInstance(prop, null);
String pass = scan.next();
Store store = session.getStore("imaps");
store.connect("smtp.gmail.com","shane.l.gvoice#gmail.com",pass);
Folder inbox = store.getFolder("inbox");
inbox.open(Folder.READ_ONLY);
int messageCount = inbox.getMessageCount();
System.out.println("Message Count: "+messageCount);
}
catch (FileNotFoundException e){}
catch (IOException e){}
catch(NoSuchProviderException e){}
catch(MessagingException e){}
}
}
You're not setting the CLASSPATH when you're running the program so it's not finding the javax.mail.jar file:
java -cp ".:lib/javax.mail.jar" msgshow -D -T imaps -H imap.gmail.com -U [USER] -P [PASS]
I am trying to send text messages from Java/Netbeans using a cell modem based on the SIM900. Using TeraTerm, I verify that I can send messages using the modem with basic AT commands. The following code attempts to use jssc to send messages.
I do not get errors and the data appears to be written to the modem, but I never receive a text message. For the phone number, I have tried both with an +, and without.
In TeraTerm, the number must be without the + to work. Many variations have been tried, and many .println's used. Still not making progress.
I hope someone can see the error of my ways.
Thanks in advance. Doug
package jssc_test;
import jssc.SerialPort;
import jssc.SerialPortException;
import jssc.SerialPortList;
public class Jssc_test {
public static SerialPort serialPort=null;
public static void main(String[] args) throws InterruptedException {
try {
String[] portNames = SerialPortList.getPortNames();
for(int i = 0; i < portNames.length; i++){
System.out.println(portNames[i]);
}
if(portNames.length < 1){
System.out.println("No ports available");
System.exit(0);
}
else{
serialPort = new SerialPort(portNames[0]);
}
System.out.println("Port opened: " + serialPort.openPort());
System.out.println("Params set: " + serialPort.setParams(9600, 8, 1, 0));
System.out.println("\"Hello World!!!\" successfully writen to port: " + serialPort.writeBytes("Hello World!!!".getBytes()));
serialPort.writeBytes(" AT+CMGF=1".getBytes());
Thread.sleep(1000);
System.out.println("bytes back = " + serialPort.readString());
serialPort.writeBytes(" AT+CMGS=\"585*******\"".getBytes()); // \r = <CR>. Tried both with and without '+'. In TeraTerm, only works without +. error if use: \r\n
//Thread.sleep(1000);
//System.out.println("bytes back = " + serialPort.readString());
//serialPort.writeBytes("0x0D".getBytes()); // send <CR>
Thread.sleep(1000);
System.out.println("bytes back = " + serialPort.readString());
serialPort.writeBytes("THIS IS A TEST from DS.".getBytes()); // placing Cntr-Z string in text did not work: \u001A
//serialPort.writeBytes("0x0D".getBytes()); // send <CR>
serialPort.writeBytes("0x1A".getBytes()); // send <ctrl>Z
Thread.sleep(1000);
System.out.println("bytes back = " + serialPort.readString());
System.out.println("Port closed: " + serialPort.closePort());
}
catch (SerialPortException ex){
System.out.println(ex);
}
} // ******************* end main ***************
} // *********************** end main class ***********************
I was able to answer the question I posed above. Below code works. The event listener does not need to be in there. The major changes that helped are defining the new line and end of file as bytes "public static final Byte eof = 0x1A, nl=0x0D;" then writing the bytes to the serialPort separately from the commands "serialPort.writeByte(nl);". I hope this helps others.
Doug
PS: I wrote a java class that may simplify sending code to the SIM900 using jssc, if anyone is interested.
package jssc_test;
//import jssc.SerialPort;
//import jssc.SerialPortException;
//import jssc.SerialPortList;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import jssc.*;
import static jssc.SerialPort.PURGE_RXCLEAR;
import static jssc.SerialPort.PURGE_TXCLEAR;
import static jssc_test.Jssc_test.serialPort;
/**
*
* #author DStockman
*/
public class Jssc_test {
public static SerialPort serialPort=null;
public static final Byte eof = 0x1A, nl=0x0D;
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws InterruptedException {
//SerialPort serialPort = null;
try {
String[] portNames = SerialPortList.getPortNames();
for(int i = 0; i < portNames.length; i++){
System.out.println(portNames[i]);
}
if(portNames.length < 1){
System.out.println("No ports available");
System.exit(0);
}
else{
serialPort = new SerialPort(portNames[0]);
}
System.out.println("Port opened: " + serialPort.openPort());
System.out.println("Params set: " + serialPort.setParams(9600, 8, 1, 0));
serialPort.writeBytes("ATI".getBytes()); // get modem ID
serialPort.writeByte(nl);
Thread.sleep(1000);
System.out.println("modem ID = " + serialPort.getEventsMask());
/*
int mask = SerialPort.MASK_RXCHAR + SerialPort.MASK_CTS + SerialPort.MASK_DSR;//Prepare mask
serialPort.setEventsMask(mask);//Set mask
try{
serialPort.addEventListener(new SerialPortReader());//Add SerialPortEventListener
}
catch (SerialPortException ex) {
System.out.println(ex);
}
*/
// just looking up settings
System.out.println("events mask = " + serialPort.getEventsMask());
System.out.println("flow control mode = " + serialPort.getFlowControlMode());
System.out.println("output buffer bytes = " + serialPort.getOutputBufferBytesCount());
//serialPort.purgePort(PURGE_RXCLEAR | PURGE_TXCLEAR);
serialPort.writeBytes(" AT+CMGF=1".getBytes());
serialPort.writeByte(nl);
Thread.sleep(1000);
System.out.println("bytes back set modem to text mode = " + serialPort.readString());
System.out.println("Success entering number: " + serialPort.writeBytes(" AT+CMGS=\"5857738696\";".getBytes())); // \r = <CR>. Tried both with and without '+'. In TeraTerm, only works without +. error if use: \r\n
serialPort.writeByte(nl);
Thread.sleep(1000);
System.out.println("bytes back after number entered = " + serialPort.readString());
serialPort.writeBytes("THIS IS A third TEST from DS 09/29/16.2.".getBytes());
serialPort.writeByte(nl);
Thread.sleep(1000);
serialPort.writeByte(eof);
Thread.sleep(1000);
System.out.println("bytes back = " + serialPort.readString());
Thread.sleep(10000);
//serialPort.purgePort(SerialPort.PURGE_TXCLEAR);
//attempt to get msgs received by modem
serialPort.writeBytes("AT+CMGL=\"ALL\"".getBytes());
serialPort.writeByte(nl);
Thread.sleep(1000);
System.out.println("bytes back = " + serialPort.readString());
System.out.println("Port closed: " + serialPort.closePort());
}
catch (SerialPortException ex){
System.out.println(ex);
}
} // ******************* end main ***************
} // *********************** end main class ***********************
class SerialPortReader implements SerialPortEventListener {
public void serialEvent(SerialPortEvent event) {
if(event.isRXCHAR()){//If data is available
if(event.getEventValue() == 1){//Check bytes count in the input buffer
//Read data, if 10 bytes available
try {
System.out.println("bytes back inside listener = " + serialPort.readString());
byte buffer[] = Jssc_test.serialPort.readBytes(10);
System.out.println("listener text:");
System.out.print(Arrays.toString(buffer));
System.out.println("End listener text:");
}
catch (SerialPortException ex) {
System.out.println(ex);
}
}
}
else if(event.isCTS()){//If CTS line has changed state
if(event.getEventValue() == 1){//If line is ON
System.out.println("CTS - ON");
}
else {
System.out.println("CTS - OFF");
}
}
else if(event.isDSR()){///If DSR line has changed state
if(event.getEventValue() == 1){//If line is ON
System.out.println("DSR - ON");
}
else {
System.out.println("DSR - OFF");
}
}
}
}
I want to take real-time data using modbus tcp/ip simulator for filling of a tank that uses port no 502.
How can I write a code in java to get the holding register value from the simulator and also I want to control the values of it?
If you use a Modbus library like this one most of the work is already done for you.
ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder("localhost").build();
ModbusTcpMaster master = new ModbusTcpMaster(config);
CompletableFuture<ReadHoldingRegistersResponse> future =
master.sendRequest(new ReadHoldingRegistersRequest(0, 10), 0);
future.thenAccept(response -> {
System.out.println("Response: " + ByteBufUtil.hexDump(response.getRegisters()));
ReferenceCountUtil.release(response);
});
import java.io.* ;
import java.net.* ;
import java.util.*;
public class Modcli {
public static void main(String argv[]) {
if (argv.length < 4) {
System.out.println("usage: java test3 dns_name unit reg_no num_regs");
System.out.println("eg java test3 aswales8.modicon.com 5 0 10");
return;
}
try {
String ip_adrs = argv[0];
int unit = Integer.parseInt(argv[1]);
int reg_no = Integer.parseInt(argv[2]);
int num_regs = Integer.parseInt(argv[3]);
System.out.println("ip_adrs = "+ip_adrs+" unit = "+unit+" reg_no = "+
reg_no+" num_regs = "+num_regs);
// set up socket
Socket es = new Socket(ip_adrs,502);
OutputStream os= es.getOutputStream();
FilterInputStream is = new BufferedInputStream(es.getInputStream());
byte obuf[] = new byte[261];
byte ibuf[] = new byte[261];
int c = 0;
int i;
// build request of form 0 0 0 0 0 6 ui 3 rr rr nn nn
for (i=0;i<5;i++) obuf[i] = 0;
obuf[5] = 6;
obuf[6] = (byte)unit;
obuf[7] = 3;
obuf[8] = (byte)(reg_no >> 8);
obuf[9] = (byte)(reg_no & 0xff);
obuf[10] = (byte)(num_regs >> 8);
obuf[11] = (byte)(num_regs & 0xff);
// send request
os.write(obuf, 0, 12);
// read response
i = is.read(ibuf, 0, 261);
if (i<9) {
if (i==0) {
System.out.println("unexpected close of connection at remote end");
} else {
System.out.println("response was too short - "+i+" chars");
}
} else if (0 != (ibuf[7] & 0x80)) {
System.out.println("MODBUS exception response - type "+ibuf[8]);
} else if (i != (9+2*num_regs)) {
System.out.println("incorrect response size is "+i+
" expected"+(9+2*num_regs));
} else {
for (i=0;i<=2;i++) {
int w = (ibuf[0+i+i]<<8) + ibuf[1+i+i];
System.out.println("word "+i+" = "+w);
}
for (i=3;i<=5;i++) {
int w = (ibuf[i+3]) ;
System.out.println("word "+i+" = "+w);
}
for (i=0;i<num_regs;i++) {
int w = (ibuf[9+i+i]<<8) + ibuf[10+i+i];
System.out.println("word "+i+" = "+w);
}
}
// close down
es.close();
} catch (Exception e) {
System.out.println("exception :"+e);
}
}
}