I have a ChannelGroup containing 4 clients that have logged in one by one and have been added to the group as they log in through the Netty method handlerAdded.
static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
#Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
channels.add(ctx.channel());
assignGroup(ctx.channel());
}
I later save my ChannelGroup in an object named GameMaster and initialize a game loop that gives each client a chance to play its turn:
static ChannelGroup channels; // contains the actual channels, saved in contructor
public void bettingPhase(boolean isOk) {
int i = 0;
int y = 0;
for (Channel chan : channels) { // Should start on the first client that logged in
Server.MyMessage.Builder message = Server.MyMessage.newBuilder();
message.setKeyword("304");
message.setValue("Please input a contract:");
chan.writeAndFlush(message); // PROBLEM HERE
while (isOk == false) { // Loop to check the playing client's input
Server.MyMessage.Builder message2 = Server.MyMessage.newBuilder();
try {
Thread.sleep(1000);
if (playerAnswer.getKeyword().equals("CONTRACT")) {
System.out.println("Player has inputed contract.");
i++;
message2.setKeyword("310");
chan.writeAndFlush(message); // Tells the current client his turn is over
System.out.println("End of turn for player.");
for (Channel channel : channels) { // Loop to tell the next client it's his turn
if (y == i) {
message2.setKeyword("309");
channel.writeAndFlush(message);
System.out.println("Start of turn for player.");
}
y++;
}
isOk = true;
playerAnswer.clearKeyword();
}
} catch (Exception e) {
e.printStackTrace();
}
}
isOk = false;
}
}
Please excuse this big chunk of code.
But for some reason my sentence "304 Please input a contract:" sent via chan.writeAndFlush(message); is sent to another client (and not the first one as it should through the loop) !
Am I missing something?
What do you mean by "first one"? ChannelGroup is a Set and it makes no guarantee to maintain insertion order when being iterated.
Related
Hello im working on a project for myself. i have serveral RFID cards. I want to send a RFID code(cardID) to my arduino and then scan a random rfid card. if the sent RFID code and the one scaned are matching i want to send back a string/number or just one byte back to my java programm.
so far sending to my arduino and checking the RFID card is working fine however im stuck at sending something back to my java programm.
i was thinking about using serielConnection but tbh its very difficult to understand.
can someone help me out ?
thanks in advance
my java code
package test;
import java.io.IOException;
import com.fazecast.jSerialComm.SerialPort;
public class Startup {
public static void main(String[] args) throws IOException, InterruptedException {
SerialPort sp = SerialPort.getCommPort("COM4"); // device name TODO: must be changed
sp.setComPortParameters(115200, 8, 33, 34); // 9600,8,1,0default connection settings for Arduino
sp.setComPortTimeouts(SerialPort.TIMEOUT_WRITE_BLOCKING, 0, 0); // block until bytes can be written
if (sp.openPort()) {
System.out.println("Port is open :)");
} else {
System.out.println("Failed to open port :(");
return;
}
/*for (Integer i = 0; i < 5; ++i) {
sp.getOutputStream().write(i.byteValue());
sp.getOutputStream().flush();
System.out.println("Sent number: " + i);
Thread.sleep(4000); //default 1000
}
*/
//rfid tag 0x82,130
//rfid card 118
Integer i = 0;//0x82,130
sp.getOutputStream().write(i.byteValue());
sp.getOutputStream().flush();
System.out.println("Sent number: " + i);
Thread.sleep(8000);
if (sp.closePort()) {
System.out.println("Port is closed :)");
} else {
System.out.println("Failed to close port :(");
return;
}
//from arduino
}
}
arduino code:
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 26
#define SS_PIN 5
#define MISO_PIN 19
#define MOSI_PIN 23
#define SCK_PIN 18
byte incomingByte = Serial.read();
MFRC522 mfrc522(SS_PIN, RST_PIN);
MFRC522::MIFARE_Key key;
void setup() {
Serial.begin(115200); // Initialize serial communications with the PC
pinMode(16,OUTPUT);
pinMode(21,OUTPUT);
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
SPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN);
mfrc522.PCD_Init(); // Init MFRC522
delay(40); // Optional delay. Some board do need more time after init to be ready, see Readme
mfrc522.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader details
//dump_byte_array(key.keyByte, MFRC522::MF_KEY_SIZE);
}
void loop() {
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
if(Serial.available() > 0){
byte incomingByte = Serial.read();
if (mfrc522.uid.uidByte[0] == incomingByte )/*&&*/ //それぞれ読んだカードの値と比較したい16進数の値を比較
)
{
digitalWrite(16,HIGH);
delay(5000);
digitalWrite(16,LOW);
delay(50);
}
else{
digitalWrite(21,HIGH);
delay(2000);
digitalWrite(21,LOW);
}
}
}
as i understand so far, for the arduino i just have to add this to send data from the arduino
SerielWrite(a number);
what is giving me a headache is how to receive it in java.
i already know that i need rxtx or jseriel libary for my java code.
i also already tryed some examples to recieve a number but it didnt work at all.
does someone maybe has a very easy code to receive a number in java ?
To recieve data in java from the arduino, you need a SerialDataListener to listen for data on the Serial Port. This can be done by creating a class which implements the SerialDataListener interface. This examples just prints to the console whatever data is read from the Serial Port but you can make it do whatever you'd like.
import com.fazecast.jSerialComm.*;
public class ComPortListener implements SerialPortDataListener {
private static String bufferReadToString = ""; // empty, but not null
private static int cutoffASCII = 10; // ASCII code of the character used for cut-off between received messages
#Override
public int getListeningEvents() {
return SerialPort.LISTENING_EVENT_DATA_AVAILABLE; //returns data on the Serial Port
}
#Override
public void serialEvent(SerialPortEvent event) {
byte[] buffer = new byte[event.getSerialPort().bytesAvailable()];
event.getSerialPort().readBytes(buffer, buffer.length);
String s = new String(buffer);
bufferReadToString = bufferReadToString.concat(s); //converts the bytes read from the Serial port to a string
if ((bufferReadToString.indexOf(cutoffASCII) + 1) > 0) {
System.out.println(bufferReadToString); //prints out the recived data
}
}
}
To use this, add the following code to your Startup class
if (sp.openPort()) {
System.out.println("Port is open :)");
ComPortListener listenerObject = new ComPortListener(); //creates new listener object
serialPort.addDataListener(listenerObject);
}
So ... I have a bit of software that's supposed to communicate with a memcached server (using no external libraries).
For testing purposes, let's settle on a simple get hello\r\n command.
I start memcached with the -vv option, this is what the command produces via telnet:
<15 new auto-negotiating client connection
15: Client using the ascii protocol
<15 get hello
>15 END
Now here is what the same command issued from my software produces:
<15 new auto-negotiating client connection
I'm connecting as following:
private void reconnect(){
InetSocketAddress remote;
int nofServers = m.servers.size();
for(int i = 0; i < R; ++i){
boolean success = false;
while(!success) {
try {
SocketChannel oldConnection = connections.get(i);
if (oldConnection != null) oldConnection.close();
remote = m.servers.get((myServerIndex + i) % nofServers).address();
SocketChannel chan = SocketChannel.open(remote);
chan.configureBlocking(false);
chan.register(this.selector, SelectionKey.OP_READ);
connections.set(i, chan);
success = true;
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
After that, the software falls into simple enough a NIO loop:
#Override
public void run() {
MyRequest curr = null;
this.canHandleNewRequest = true;
while (true) {
if (canHandleNewRequest) {
curr = myQueue.poll();
}
if (canHandleNewRequest && curr != null) {
canHandleNewRequest = false;
for (int i = 0; i < R; ++i) {
connections.get(i).keyFor(this.selector).interestOps(SelectionKey.OP_WRITE);
}
}
try {
selector.select();
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey k = it.next();
it.remove();
if (!k.isValid()) continue;
if (k.isConnectable()) finishConnection(k);
else if (k.isReadable()) this.read(k, curr);
else if (k.isWritable()) this.write(k, curr);
}
} catch (IOException ex) {
ex.printStackTrace();
reconnect();
}
if(curr != null && /*have sent to all servers I need to*/){
curr = null;
this.canHandleNewRequest = true;
}
}
}
where
private void write(SelectionKey k, MyRequest currentRequest){
try {
SocketChannel chan = (SocketChannel) k.channel();
ByteBuffer out = currentRequest.getSendBuffer(); //DO NOT FLIP (to resume sending from last sent position)
assert(chan != null);
assert(out != null);
//System.out.println(new String(out.array()));
chan.write(out); //TODO: make this work!
if(!out.hasRemaining()) { //do not enable read until whole command has been sent
currentRequest.partiallySent();
k.interestOps(SelectionKey.OP_READ);
}
}catch(IOException ex){
ex.printStackTrace();
}
//TODO: create response structure
}
I even tried to substitute the write method for a dummy command provider:
else if(k.isWritable()){
SocketChannel chan = (SocketChannel)k.channel();
ByteBuffer msg = ByteBuffer.wrap("get hello\r\n".getBytes());
msg.flip();
while(msg.hasRemaining()) {
System.out.println("writing ...");
chan.write(msg);
}
k.interestOps(SelectionKey.OP_READ);
}
but this only gets stuck in the "writing" loop (never terminates).
You should think that at least the server should react to that command but it doesn't.
So ... how do I get this working?
The second line from the log providing the command via telnet produces,
15: Client using the ascii protocol
makes me think there might be something I need to send to the server prior to engaging in actual memcached commands... except I seem to miss it in the protocol.
Help would be appreciated.
EDIT
This seems to be the issue: flipping a buffer in the getSendBuffer method and then returning it is not the same as returning it unflipped and then flipping it in the write method.
I find this rather strange. Can this be or is this merely masking a different error?
With NIO you should always check whether all of the buffer has been written, which is not being done doing in the first write block. Having said that, unless there's a lot of data being written, the whole buffer is usually written in a single call to write. So, it's unlikely to be the root problem here.
In the alternative writing code block the hasRemaining condition is negated, it should be:
while(msg.hasRemaining()) {
System.out.println("writing ...");
chan.write(msg);
}
Could you include what's being sent first? Is the first command terminated with \r\n?
I'm extending the BaseIOIOLooper to open up a UART device and send messages. I'm testing with a readback, where I send a packet over a line and receive that packet on another line and print it out. Because I don't want the InputStream.read() method to block, I am handling packet formation and input in a different thread. I have narrowed my problem down to the InputStream.read() method, which returns -1 (no bytes read, but no exception).
Here is what it looks like in the Looper thread:
#Override
protected void setup() throws ConnectionLostException, InterruptedException {
log_.write_log_line(log_header_ + "Beginning IOIO setup.");
// Initialize IOIO UART pins
// Input at pin 1, output at pin 2
try {
inQueue_ = MinMaxPriorityQueue.orderedBy(new ComparePackets())
.maximumSize(QUEUESIZE).create();
outQueue_ = MinMaxPriorityQueue.orderedBy(new ComparePackets())
.maximumSize(QUEUESIZE).create();
ioio_.waitForConnect();
uart_ = ioio_.openUart(1, 2, 38400, Uart.Parity.NONE, Uart.StopBits.ONE);
// Start InputHandler. Takes packets from ELKA on inQueue_
in_= new InputHandler(inQueue_, uart_.getInputStream());
in_.start();
// Start OutputHandler. Takes packets from subprocesses on outQueue_
out_= new OutputHandler(outQueue_);
out_.start();
// Get output stream
os_=uart_.getOutputStream();
// Set default target state
setTargetState(State.TRANSFERRING);
currInPacket_[0]=1; //Initial value to start transferring
log_.write_log_line(log_header_ + "IOIO setup complete.\n\t" +
"Input pin set to 1\n\tOutput pin set to 2\n\tBaud rate set to 38400\n\t" +
"Parity set to even\n\tStop bits set to 1");
} catch (IncompatibilityException e) {
log_.write_log_line(log_header_+e.toString());
} catch (ConnectionLostException e) {
log_.write_log_line(log_header_+e.toString());
} catch (Exception e) {
log_.write_log_line(log_header_+"mystery exception: "+e.toString());
}
}
And in the InputHandler thread:
#Override
public void run() {
boolean notRead;
byte i;
log_.write_log_line(log_header_+"Beginning InputHandler thread");
while (!stop) {
i = 0;
notRead = true;
nextInPacket = new byte[BUFFERSIZE];
readBytes = -1;
//StringBuilder s=new StringBuilder();
//TODO re-implement this with signals
while (i < READATTEMPTS && notRead) {
try {
// Make sure to adjust packet size. Done manually here for speed.
readBytes = is_.read(nextInPacket, 0, BUFFERSIZE);
/* Debugging
for (int j=0;j<nextInPacket.length;j++)
s.append(Byte.toString(nextInPacket[j]));
log_.write_log_line(log_header_+s.toString());
*/
if (readBytes != -1) {
notRead = false;
nextInPacket= new byte[]{1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0};
synchronized (q_) {
q_.add(nextInPacket);
}
//log_.write_log_line(log_header_ + "Incoming packet contains valid data.");
} else i++;
} catch (IOException e) {
log_.write_log_line(log_header_ + "mystery exception:\n\t" + e.toString());
}
}
if (i>=READATTEMPTS)
log_.write_log_line(log_header_+"Too many read attempts from input stream.");
/*
try {
sleep(100);
} catch (InterruptedException e) {
log_.write_log_line(log_header_+"fuck");
}
*/
}
}
On an oscilloscope, pins 1 and 2 both read an oscillating voltage, albeit at a very high amplitude, which is of some concern. Point is nothing is available to be read from the InputStream in the InputHandler class. Any ideas?
-1 returned from read() should only happen whenever the UART is closed. The closure can happen as result of explicitly calling close() on the Uart object or calling softReset() on the IOIO object.
The Android log might give you some clues about what's going on.
The reading you're seeing on the oscilloscope is suspicious: how high is "very high amplitude"? You should only ever see 0V or 3.3V on those pins, or floating in case the pins where not opened (or closed) for some reason.
I have been trying to use serial communication with my Arduino Uno and have used the library jSSC-2.6.0. I am using a SeriaPortEvent listener to receive bytes from the Serial Port (Arduino) and store them in a linked list.
public synchronized void serialEvent(SerialPortEvent serialPortEvent) {
if (serialPortEvent.isRXCHAR()) { // if we receive data
if (serialPortEvent.getEventValue() > 0) { // if there is some existent data
try {
byte[] bytes = this.serialPort.readBytes(); // reading the bytes received on serial port
if (bytes != null) {
for (byte b : bytes) {
this.serialInput.add(b); // adding the bytes to the linked list
// *** DEBUGGING *** //
System.out.print(String.format("%X ", b));
}
}
} catch (SerialPortException e) {
System.out.println(e);
e.printStackTrace();
}
}
}
}
Now if I send individual data in a loop and don't wait for any response the serialEvent usually prints bytes received, to the Console.
But If I try and wait till there is some data in the linked list the program just keeps on looping and the SerialEvent never adds bytes to the LinkedList, it even does not even register any bytes being received.
This works and the correct bytes are sent by Arduino received by SerialEvent and printed to the Console:
while(true) {
t.write((byte) 0x41);
}
But this method just stucks at this.available() which returns the size of the LinkedList,
as in no data is actually received from the Arduino or receieved by the serialEvent:
public boolean testComm() throws SerialPortException {
if (!this.serialPort.isOpened()) // if port is not open return false
return false;
this.write(SerialCOM.TEST); // SerialCOM.TEST = 0x41
while (this.available() < 1)
; // we wait for a response
if (this.read() == SerialCOM.SUCCESS)
return true;
return false;
}
I have debugged the program and sometimes debugging, the program does work but not always. Also the program only gets stuck when i try and check if there is some bytes in the linkedlist i.e while(available() < 1). Otherwise if I dont check I eventually receive the correct response of bytes from Arduino
Found the answer myself after wasting 4hours. I was better off using the readBytes() method with a byteCount of 1 and timeOut of 100ms just to be on the safe side. So now the read method looks like this.
private byte read() throws SerialPortException{
byte[] temp = null;
try {
temp = this.serialPort.readBytes(1, 100);
if (temp == null) {
throw new SerialPortException(this.serialPort.getPortName(),
"SerialCOM : read()", "Can't read from Serial Port");
} else {
return temp[0];
}
} catch (SerialPortTimeoutException e) {
System.out.println(e);
e.printStackTrace();
}
return (Byte) null;
}
I don't know if this is the best approach so that's why I'm asking your help guys.
This is my problem, I'm developing an app where you have the 'read' button, when the user hit this button then the program start to read some values and save this values in my database, okay ?
So I think when the user hit 'read' I start a thread, that's because the user can do another thing if he wants without the app been freeze.
But I cannot access the values read by this thread.
There's another way to do that ?
EDIT:
private void jtb_readerItemStateChanged(java.awt.event.ItemEvent evt) {
// getting some values provided by the user
if (buttonReaderState()){
if (supervisory == null)
supervisory = new Supervisory(ip, broadcast, deviceID);
supervisory.start();
}
}
// Supervisory class
public void start(){
Scan scan = new Scan();
Thread t = new Thread(scan);
t.start();
threadState = true;
}
class Scan extends Thread{
public void run(){
// inside the tread I have to initiate another 'supervisory' object, is that right ?
Supervisory s = new Supervisory(ip, broadcast, deviceID);
while (threadState){
try {
s.active();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public void active() throws IOException, Exception {
// getting this values from my hardware like temperature and anothers things.
for (int i = 0; i < ois.size(); i++) {
ObjectIdentifier oi = ois.get(i);
//analog input
if (i == 1)
aI = Float.parseFloat(getPresentValue(localDevice, oi));
//analog output
if (i == 2)
aO = Float.parseFloat(getPresentValue(localDevice, oi));
//binary input
if (i == 3)
bI = getBinaryValue(getPresentValue(localDevice, oi));
//binary output
if (i == 4)
bO = getBinaryValue(getPresentValue(localDevice, oi));
}
}
After reading this values I would like to show this values in the interface that I'm building, but it seems that I cannot have access to these values (aI,aO,bI,bO).
Pass a reference to the interface you have. E.g. you can add a JFrame owner field to Supervisory class and pass your values there.