So, there's existing and fairly widely used code for mesh communication with Python. I'm not aware of any such Java code, however, so I wrote these two classes.
ScratchInputStream.java:
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
public class ScratchInputStream extends FilterInputStream {
private int remaining;
public ScratchInputStream(InputStream in){
super(in);
remaining = 0;
}
public int read() throws IOException {
byte[] data = new byte[1];
int read;
while((read = read(data)) == 0);
if(read == -1) return -1;
return data[0] & 0xff;
}
public String nextMessage() throws IOException {
return new String(readFull());
}
public byte[] readFull() throws IOException {
int size = readSizeField();
if(size == -1) return null;
byte[] data = new byte[size];
int off = 0;
while(true){
int read = in.read(data, off, size - off);
if(read == -1) return null;
off += read;
if(off < size) continue;
return data;
}
}
public int read(byte[] b, int off, int len) throws IOException {
if(len <= 0) return 0;
if(remaining > 0){
int read = in.read(b, off, Math.min(len, remaining));
remaining -= read;
return read;
}
int size = readSizeField();
if(size == -1) return -1;
int read = in.read(b, off, Math.min(len, size));
remaining = size - read;
return read;
}
private int readSizeField() throws IOException {
byte[] sizefield = new byte[4];
int read = in.read(sizefield);
if(read == -1) return -1;
if(read < 4) throw new IOException("Failed to read size field!");
return (sizefield[0] & 0xff) << 24 |
(sizefield[1] & 0xff) << 16 |
(sizefield[2] & 0xff) << 8 |
(sizefield[3] & 0xff);
}
public long skip(long n){
throw new UnsupportedOperationException();
}
public void mark(int readlimit){}
public void reset(){}
public boolean markSupported(){
return false;
}
}ScratchOutputStream.java:
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class ScratchOutputStream extends FilterOutputStream {
public ScratchOutputStream(OutputStream out){
super(out);
}
public void write(int b) throws IOException {
write(new byte[]{(byte) (b & 0xff)});
}
public void write(byte[] b, int off, int len) throws IOException {
out.write(new byte[]{
(byte) ((len << 24) & 0xff),
(byte) ((len << 16) & 0xff),
(byte) ((len << 8) & 0xff),
(byte) (len & 0xff),
});
out.write(b, off, len);
}
public void write(String s) throws IOException {
write(s.getBytes());
}
public void broadcast(String s) throws IOException {
write("broadcast \"" + s + "\"");
}
public void sensorUpdate(String name, Object value) throws IOException {
write("sensor-update \"" + name + "\" " +
((value instanceof Number) ? value.toString() : "\"" + value.toString() + "\""));
}
}Assuming you already have a socket which is connected to Scratch, usage is something like the following:
try {
in = new ScratchInputStream(sock.getInputStream());
out = new ScratchOutputStream(sock.getOutputStream());
out.sendMessage("broadcast \"test\""); //Or use out.broadcast("test")
System.out.println(in.nextMessage()); //Blocks until enough data is available
} catch (IOException e) {
e.printStackTrace();
}Hopefully you'll find these useful!
Offline
MathWizz wrote:
Ah! Very nice.
![]()
Thanks
Offline