Netty4 readableBytes is too small - java

I get the exception when decode with Netty4. the message's length only 640, but the readableBytes is not enough.
06-19 21:45:13.150 4192-4233/com.seewo.remote V/RemoteMassageDecoder: Decoder messageType == 1, messageLength: 640
06-19 21:45:13.152 4192-4233/com.seewo.remote E/exceptionCaught: io.netty.handler.codec.DecoderException: java.lang.Exception: readableBytes is too small
1、First,add decoder in ChannelInitializer
private static final int MAX_FRAME_LENGTH = 1024 * 1024;
private static final int LENGTH_FIELD_LENGTH = 4;
private static final int LENGTH_FIELD_OFFSET = 1;
private static final int LENGTH_ADJUSTMENT = 2;
private static final int INITIAL_BYTES_TO_STRIP = 0;
channelPipeline.addLast("decoder", new RemoteMassageDecoder(MAX_FRAME_LENGTH,
LENGTH_FIELD_LENGTH, LENGTH_FIELD_OFFSET, LENGTH_ADJUSTMENT, INITIAL_BYTES_TO_STRIP));
channelPipeline.addLast("encoder", new RemoteMessageEncoder());
2、second,decoder the bytes from server
#Override
protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
byte startCharacter = in.readByte();
int messageLength = in.readInt();
byte messageType = in.readByte();
in.readByte();
Log.v("RemoteMassageDecoder", "startCharacter == " + (startCharacter & 0xff));
Log.v("RemoteMassageDecoder", "Decoder messageType == " + messageType + ", messageLength: " + messageLength);
if (messageLength < 0) {
throw new Exception("messageLength < 0");
}
if (messageLength == 0 || messageType == 0) {
in.readByte();
return null;
}
if (in.readableBytes() < messageLength) {
throw new Exception("readableBytes is too small");
}
byte[] content = new byte[messageLength];
in.readBytes(content);
byte stopCharacter = in.readByte();
if (startCharacter != START_CHARACTER || stopCharacter != STOP_CHARACTER) {
return null;
}
return ProtocolPack.parseFrom(AESHelper.decryptContent(content));
}

The reason for this issue is simple: you can't expect the TCP stream will always return enough data at the same time.
The solution is also simple: Your ChannelHandler can just extends ReplyingDecoder which can help you handle underlying steam properly.

Related

How do I get X11 WM_CLASS for active window using JNA (Java)?

I use the following code to get the current (in focus) window in Linux:
X11 x11 = X11.INSTANCE;
X11.Display display = x11.XOpenDisplay(null);
X11.Window window = x11.XDefaultRootWindow(display);
Now I'd like to get WM_CLASS property of this window.
In Setting and Reading the WM_CLASS Property there is a following passage showing how to do this:
To read a window's WM_CLASS property, use XGetClassHint().
The XClassHint contains:
typedef struct {
char *res_name;
char *res_class;
} XClassHint;
However, when we look at X11.XWMHints (JNA API) we can see that there is no such a property res_class (that is, WM_CLASS).
So, how do get the WM_CLASS property of the current window?
You can use getWindowClass() method of X.Window class from jnacontrib package: it reads WC_CLASS property from provided window and replaces null-terminator characters (\0) with dots (.). Javadoc says:
Returns the property value as UTF8 string where every '\0' character is replaced by '.'.
X11 x11 = X11.INSTANCE;
X11.Display display = x11.XOpenDisplay(null);
X11.Window window = x11.XDefaultRootWindow(display);
String wmClass = new X.Window(new X.Display(display), window).getWindowClass();
Another way to get this value is to read it manually (copied some parts from contrib package):
static class XClassHint {
public final String resName;
public final String resClass;
public XClassHint(final String name, final String cls) {
this.resName = name;
this.resClass = cls;
}
#Override
public String toString() {
return String.format("%s:%s", this.resName, this.resClass);
}
}
private static XClassHint wmClass(X11 x11, X11.Display display, X11.Window window) throws UnsupportedEncodingException {
final X11.Atom xa_prop_type = X11.XA_STRING;
final X11.Atom xa_prop_name = X11.XA_WM_CLASS;
final int MAX_PROPERTY_VALUE_LEN = 4096;
X11.AtomByReference xa_ret_type_ref = new X11.AtomByReference();
IntByReference ret_format_ref = new IntByReference();
NativeLongByReference ret_nitems_ref = new NativeLongByReference();
NativeLongByReference ret_bytes_after_ref = new NativeLongByReference();
PointerByReference ret_prop_ref = new PointerByReference();
NativeLong long_offset = new NativeLong(0);
NativeLong long_length = new NativeLong(MAX_PROPERTY_VALUE_LEN / 4);
if (x11.XGetWindowProperty(display, window, xa_prop_name, long_offset, long_length, false,
xa_prop_type, xa_ret_type_ref, ret_format_ref,
ret_nitems_ref, ret_bytes_after_ref, ret_prop_ref) != X11.Success) {
String prop_name = x11.XGetAtomName(display, xa_prop_name);
throw new RuntimeException("Cannot get " + prop_name + " property.");
}
X11.Atom xa_ret_type = xa_ret_type_ref.getValue();
Pointer ret_prop = ret_prop_ref.getValue();
if (xa_ret_type == null) {
//the specified property does not exist for the specified window
return null;
}
if (xa_prop_type == null ||
!xa_ret_type.toNative().equals(xa_prop_type.toNative())) {
x11.XFree(ret_prop);
String prop_name = x11.XGetAtomName(display, xa_prop_name);
throw new RuntimeException("Invalid type of " + prop_name + " property");
}
int ret_format = ret_format_ref.getValue();
long ret_nitems = ret_nitems_ref.getValue().longValue();
// null terminate the result to make string handling easier
int nbytes;
if (ret_format == 32)
nbytes = Native.LONG_SIZE;
else if (ret_format == 16)
nbytes = Native.LONG_SIZE / 2;
else if (ret_format == 8)
nbytes = 1;
else if (ret_format == 0)
nbytes = 0;
else
throw new RuntimeException("Invalid return format");
int length = Math.min((int) ret_nitems * nbytes, MAX_PROPERTY_VALUE_LEN);
byte[] ret = ret_prop.getByteArray(0, length);
x11.XFree(ret_prop);
if( ret == null ){
return null;
}
// search for '\0'
int i;
for (i = 0; i < ret.length; i++) {
if (ret[i] == '\0') {
ret[i] = '.';
}
}
String wcSrc = new String(ret, "UTF8");
final String[] parts = wcSrc.split("\\.");
return new XClassHint(parts[0], parts[1]);
}

Issue in parsing TLV data in java, how to get value,length

I have tried many sample codes to parse APDU response to TLV format.
I am able to parse it properly if the response length is less but facing issue if length is more(how calculate length of a tag without any libraries)
NOTE: I am using predefined tags in Constants
code:
private HashMap<String, String> parseTLV(String apduResponse) {
HashMap<String, String> tagValue = new HashMap<>();
String remainingApdu = apduResponse.replaceAll(" ", "");
if (remainingApdu.endsWith(ResponseTags._SUCCESS_STATUSWORDS)) {
remainingApdu = remainingApdu.substring(0, remainingApdu.length() - 4);
}
while (remainingApdu != null && remainingApdu.length() > 2) {
remainingApdu = addTagValue(tagValue, remainingApdu);
}
return tagValue;
}
addTagValue method
private String addTagValue(HashMap<String, String> tagValue, String apduResponse) {
String tag = "";
String length = "";
String value = "";
int tagLen = 0;
if (tagUtils.isValidTag(apduResponse.substring(0, 2))) {
tagLen = readTagLength(apduResponse.substring(3));
// tagLen = 2;
tag = apduResponse.substring(0, 2);
} else if (tagUtils.isValidTag(apduResponse.substring(0, 4))) {
tagLen = 4;
tag = apduResponse.substring(0, 4);
} else {
return "";
}
Log.e("TAG_LEN","tag: "+tag+"taglen: "+tagLen);
if (tagUtils.shouldCheckValueFor(tag)) {
length = apduResponse.substring(tagLen, tagLen + 2);
int len = tagUtils.hexToDecimal(length);
value = apduResponse.substring(tagLen + 2, (len * 2) + tagLen + 2);
tagValue.put(tag, value);
if (ResponseTags.getRespTagsmap().containsKey(tag)) {
//logData = logData + "\nKEY:" + tag + " TAG:" + ResponseTags.getRespTagsmap().get(tag)/* + " VALUE:" + value + "\n "*/;
}
if (tagUtils.isTemplateTag(tag)) {
// logData = logData + "\n\t-->";
return addTagValue(tagValue, value) + apduResponse.substring(tag.length() + value.length() + length.length());
} else {
return apduResponse.substring(tag.length() + value.length() + length.length());
}
} else {
value = apduResponse.substring(2, 4);
tagValue.put(tag, value);
// logData = logData + "\n\t\tKEY:" + tag + " TAG:" + ResponseTags.getRespTagsmap().get(tag) /*+ " VALUE:" + value + "\n "*/;
return apduResponse.substring(tag.length() + value.length() + length.length());
}
}
readTagLength :
private int readTagLength(String apduResponse) {
int len_bytes = 0;
if (apduResponse.length() > 2) {
len_bytes = (apduResponse.length()) / 2;
}
Log.e("tlv length:", "bytes:" + len_bytes);
if (len_bytes < 128) {
return 2;
} else if (len_bytes > 127 && len_bytes < 255) {
return 4;
} else {
return 6;
}
}
I cannot able to get length properly for few cards(if apdu response is long)
Please help
First be sure the input data is proper before you go into the code. Take the full data and try it on https://www.emvlab.org/tlvutils/ .
Once its confirmed the data is proper, go through in EMV 4.3 Book 3,
Annex B Rules for BER-TLV Data Objects sections B1, B2, B3 - with utmost attention.
If you follow this precisely, then you wouldn't need to store a static list of tags; will save time in future.
Below sample has an assumption that TLV array is ending with special 0x00 tag but for sure you can ignore it.
Pojo class :
public class Tlv {
private short tag;
private byte[] value;
public Tlv(short tag) {
this.tag = tag;
}
public short getTag() {
return tag;
}
public byte[] getValue() {
return value;
}
public void setValue(byte[] valueBytes) {
this.value = valueBytes;
}
}
Utility method :
public static Map<Byte, Tlv> parse(ByteBuffer bb) throws TlvException {
Map<Byte, Tlv> tlvs = null;
tlvs = new HashMap<Byte, Tlv>();
try {
while (bb.remaining() > 0) {
byte tag = bb.get();
if(tag == 0x00)
continue;
int length = bb.get();
byte[] value = new byte[length];
bb.get(value, 0, length);
Tlv tlv = new Tlv(tag);
tlv.setValue(value);
tlvs.put(tag, tlv);
}
} catch (IndexOutOfBoundsException e) {
throw new TlvException("Malformed TLV part: " + bb.toString() + ".", e);
}
return tlvs;
}

How do I upload a file using the Java HttpServer API?

EDIT: I tried this using a multiple file upload, and I got 3 of 4 uploaded files, so it seems that the upload mechanism is only setting the offset too high for the first file.
I found a method for uploading files using the com.sun.net.httpserver library here, but it is not actually detecting any files from the form input. What it does is it finds the "starting point" of uploaded files, represented by List<Integer> offsets and then looks through the file to get bytes from it. The problem is that it sets each part of offsets as a number very close to the end of the form data, so nothing actually gets parsed. Here is my HttpHandler:
package app;
import com.sun.net.httpserver.*;
import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FormDataHandler implements HttpHandler {
#Override
public void handle(HttpExchange httpExchange) throws IOException {
Headers headers = httpExchange.getRequestHeaders();
String contentType = headers.getFirst("Content-Type");
if(contentType.startsWith("multipart/form-data")){
//found form data
String boundary = contentType.substring(contentType.indexOf("boundary=")+9);
// as of rfc7578 - prepend "\r\n--"
byte[] boundaryBytes = ("\r\n--" + boundary).getBytes(Charset.forName("UTF-8"));
byte[] payload = getInputAsBinary(httpExchange.getRequestBody());
ArrayList<MultiPart> list = new ArrayList<>();
List<Integer> offsets = searchBytes(payload, boundaryBytes, 0, payload.length - 1);
System.out.println(offsets);
for(int idx=0;idx<offsets.size();idx++){
int startPart = offsets.get(idx);
int endPart = payload.length;
if(idx<offsets.size()-1){
endPart = offsets.get(idx+1);
}
byte[] part = Arrays.copyOfRange(payload,startPart,endPart);
//look for header
int headerEnd = indexOf(part,"\r\n\r\n".getBytes(Charset.forName("UTF-8")),0,part.length-1);
/*This conditional is always false because headerEnd is not
found, due to part.length being to small, due to startPart
being too small, due to the current offset being to small*/
if(headerEnd>0) {
MultiPart p = new MultiPart();
byte[] head = Arrays.copyOfRange(part, 0, headerEnd);
String header = new String(head);
// extract name from header
int nameIndex = header.indexOf("\r\nContent-Disposition: form-data; name=");
if (nameIndex >= 0) {
int startMarker = nameIndex + 39;
//check for extra filename field
int fileNameStart = header.indexOf("; filename=");
if (fileNameStart >= 0) {
String filename = header.substring(fileNameStart + 11, header.indexOf("\r\n", fileNameStart));
p.filename = filename.replace('"', ' ').replace('\'', ' ').trim();
p.name = header.substring(startMarker, fileNameStart).replace('"', ' ').replace('\'', ' ').trim();
p.type = PartType.FILE;
} else {
int endMarker = header.indexOf("\r\n", startMarker);
if (endMarker == -1)
endMarker = header.length();
p.name = header.substring(startMarker, endMarker).replace('"', ' ').replace('\'', ' ').trim();
p.type = PartType.TEXT;
}
} else {
// skip entry if no name is found
continue;
}
// extract content type from header
int typeIndex = header.indexOf("\r\nContent-Type:");
if (typeIndex >= 0) {
int startMarker = typeIndex + 15;
int endMarker = header.indexOf("\r\n", startMarker);
if (endMarker == -1)
endMarker = header.length();
p.contentType = header.substring(startMarker, endMarker).trim();
}
//handle content
if (p.type == PartType.TEXT) {
//extract text value
byte[] body = Arrays.copyOfRange(part, headerEnd + 4, part.length);
p.value = new String(body);
} else {
//must be a file upload
p.bytes = Arrays.copyOfRange(part, headerEnd + 4, part.length);
}
list.add(p);
}
}
handle(httpExchange,list);
}else{
//if no form data is present, still call handle method
handle(httpExchange,null);
}
}
public void handle(HttpExchange he, List<MultiPart> parts) throws IOException {
OutputStream os = he.getResponseBody();
String response = "<h1>" + parts.size() + "</h1>";
he.sendResponseHeaders(200, response.length());
os.write(response.getBytes());
os.close();
}
public static byte[] getInputAsBinary(InputStream requestStream) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
byte[] buf = new byte[100000];
int bytesRead=0;
while ((bytesRead = requestStream.read(buf)) != -1){
//while (requestStream.available() > 0) {
// int i = requestStream.read(buf);
bos.write(buf, 0, bytesRead);
}
requestStream.close();
bos.close();
} catch (IOException e) {
}
return bos.toByteArray();
}
/**
* Search bytes in byte array returns indexes within this byte-array of all
* occurrences of the specified(search bytes) byte array in the specified
* range
* borrowed from https://github.com/riversun/finbin/blob/master/src/main/java/org/riversun/finbin/BinarySearcher.java
*
* #param srcBytes
* #param searchBytes
* #param searchStartIndex
* #param searchEndIndex
* #return result index list
*/
public List<Integer> searchBytes(byte[] srcBytes, byte[] searchBytes, int searchStartIndex, int searchEndIndex) {
final int destSize = searchBytes.length;
final List<Integer> positionIndexList = new ArrayList<Integer>();
int cursor = searchStartIndex;
while (cursor < searchEndIndex + 1) {
int index = indexOf(srcBytes, searchBytes, cursor, searchEndIndex);
if (index >= 0) {
positionIndexList.add(index);
cursor = index + destSize;
} else {
cursor++;
}
}
return positionIndexList;
}
/**
* Returns the index within this byte-array of the first occurrence of the
* specified(search bytes) byte array.<br>
* Starting the search at the specified index, and end at the specified
* index.
* borrowed from https://github.com/riversun/finbin/blob/master/src/main/java/org/riversun/finbin/BinarySearcher.java
*
* #param srcBytes
* #param searchBytes
* #param startIndex
* #param endIndex
* #return
*/
public int indexOf(byte[] srcBytes, byte[] searchBytes, int startIndex, int endIndex) {
if (searchBytes.length == 0 || (endIndex - startIndex + 1) < searchBytes.length) {
return -1;
}
int maxScanStartPosIdx = srcBytes.length - searchBytes.length;
final int loopEndIdx;
if (endIndex < maxScanStartPosIdx) {
loopEndIdx = endIndex;
} else {
loopEndIdx = maxScanStartPosIdx;
}
int lastScanIdx = -1;
label: // goto label
for (int i = startIndex; i <= loopEndIdx; i++) {
for (int j = 0; j < searchBytes.length; j++) {
if (srcBytes[i + j] != searchBytes[j]) {
continue label;
}
lastScanIdx = i + j;
}
if (endIndex < lastScanIdx || lastScanIdx - i + 1 < searchBytes.length) {
// it becomes more than the last index
// or less than the number of search bytes
return -1;
}
return i;
}
return -1;
}
public static class MultiPart {
public PartType type;
public String contentType;
public String name;
public String filename;
public String value;
public byte[] bytes;
}
public enum PartType{
TEXT,FILE
}
}
And here is my form:
<form action="http://localhost:8080/upl" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="Submit">
</form>
Does anybody know why this won't work? If not, is there a better option for HttpServer file uploads? I tried the Apache Commons API, but that didn't work either.

Jaunt Java getText() returning correct text but with lots of "?"

The title explains all, also, I have tried removing them
(because the text is there, but instead of "aldo" there is "al?do", also it seems to have a random pattern)
with (String).replace("?", ""), but with no success.
I have also used this, with a combination of UTF_8,UTF_16 and ISO-8859, with no success.
byte[] ptext = tempName.getBytes(UTF_8);
String tempName1 = new String(ptext, UTF_16);
An example of what I am getting:
Studded Regular Sweatshirt // Instead of this
S?tudde?d R?eg?ular? Sw?eats?h?irt // I get this
Could it be the website that notices the headless browser and tries to "spoof" its content? How can I overcome this?
It looks very likely that site you scrapping intent mix up the 3f and 64 characters into your result.
so you have to mask your self as a normal browser to scrapping or filter it out by replacing.
text simple
Sca???rfa???ce??? E???mbr???oi�d???ered L�e???athe
after filteration
Scarface Embroidered Leather
//Sca???rfa???ce??? E???mbr???oi�d???ered L�e???athe
//Scarface Embroidered Leathe
String hex="5363613f3f3f7266613f3f3f63653f3f3f20453f3f3f6d62723f3f3f6f69‌​643f3f3f65726564204c‌​653f3f3f61746865";
byte[] bytes= hexStringToBytes(hex);
//the only line you need
String res = new String(bytes,"UTF-8").replaceAll("\\\u003f","").replaceAll('�',"").replaceAll("�","");
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(new String(c));
}
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
public static String bytesToHexString(byte[] src){
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
public String printHexString( byte[] b) {
String a = "";
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
a = a+hex;
}
return a;
}

loadpixel() returns nullpointerexception

I was using processing in netbeans to play a movie on an array of ledstrips and I am using OPC.class for ledstrip fadecandy mapping. This code works on the processing sketch, but when I tried to use it on netbeans the loadpixel() in draw() method of OPC.java throws a nullpointer exception.
Stacktrace:
Exception in thread "Animation Thread" java.lang.NullPointerException
at processing.core.PApplet.loadPixels(PApplet.java:10625)
at com.processing.OPC.draw(OPC.java:139)
at com.processing.Video.draw(Video.java:62)
at processing.core.PApplet.handleDraw(PApplet.java:2402)
at processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1527)
at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:316)
Video.java
public class Video extends PApplet
{
OPC opc;
Movie movie;
public static void main(String args[])
{
PApplet.main(new String[] { "--present", "com.processing.Video" });
}
public void settings()
{
size(600, 240);
}
public void setup()
{
opc = new OPC(this, "192.168.15.10", 7890);
for(int i=0; i<24; i++) {
opc.ledStrip(i * 60, 60,
300, i * 240 / 24 + 240 / 48, 240 / 24, PI, false);
}
movie = new Movie(this, "waffle.mp4");
movie.loop();
}
public void movieEvent(Movie m)
{
m.read();
}
#Override
public void draw()
{
if (movie.available() == true) {
movie.read();
}
image(movie, 0, 0, width, height);
}
}
OPC.java
public class OPC extends PApplet implements Runnable
{
Thread thread;
Socket socket;
OutputStream output, pending;
String host;
int port;
int height = 240;
int width = 600;
int[] pixelLocations;
byte[] packetData;
byte firmwareConfig;
String colorCorrection;
boolean enableShowLocations;
PApplet parent;
OPC(PApplet parent, String host, int port)
{
this.host = host;
this.port = port;
thread = new Thread(this);
thread.start();
this.enableShowLocations = true;
registerMethod("draw", this);
}
public void led(int index, int x, int y){
if (pixelLocations == null) {
pixelLocations = new int[index + 1];
} else if (index >= pixelLocations.length) {
pixelLocations = Arrays.copyOf(pixelLocations, index + 1);
}
pixelLocations[index] = x + 600 * y;
}
public void ledStrip(int index, int count, float x, float y, float spacing, float angle, boolean reversed)
{
float s = sin(angle);
float c = cos(angle);
for (int i = 0; i < count; i++) {
led(reversed ? (index + count - 1 - i) : (index + i),
(int)(x + (i - (count-1)/2.0) * spacing * c + 0.5),
(int)(y + (i - (count-1)/2.0) * spacing * s + 0.5));
}
}
void showLocations(boolean enabled)
{
enableShowLocations = enabled;
}
void setColorCorrection(String s)
{
colorCorrection = s;
sendColorCorrectionPacket();
}
void sendFirmwareConfigPacket()
{
if (pending == null) {
return;
}
byte[] packet = new byte[9];
packet[0] = (byte)0x00; // Channel (reserved)
packet[1] = (byte)0xFF; // Command (System Exclusive)
packet[2] = (byte)0x00; // Length high byte
packet[3] = (byte)0x05; // Length low byte
packet[4] = (byte)0x00; // System ID high byte
packet[5] = (byte)0x01; // System ID low byte
packet[6] = (byte)0x00; // Command ID high byte
packet[7] = (byte)0x02; // Command ID low byte
packet[8] = (byte)firmwareConfig;
try {
pending.write(packet);
} catch (Exception e) {
dispose();
}
}
void sendColorCorrectionPacket()
{
if (colorCorrection == null) {
return;
}
if (pending == null) {
return;
}
byte[] content = colorCorrection.getBytes();
int packetLen = content.length + 4;
byte[] header = new byte[8];
header[0] = (byte)0x00; // Channel (reserved)
header[1] = (byte)0xFF; // Command (System Exclusive)
header[2] = (byte)(packetLen >> 8); // Length high byte
header[3] = (byte)(packetLen & 0xFF); // Length low byte
header[4] = (byte)0x00; // System ID high byte
header[5] = (byte)0x01; // System ID low byte
header[6] = (byte)0x00; // Command ID high byte
header[7] = (byte)0x01; // Command ID low byte
try {
pending.write(header);
pending.write(content);
} catch (Exception e) {
dispose();
}
}
public void draw()
{
if (pixelLocations == null) {
return;
}
if (output == null) {
return;
}
int numPixels = pixelLocations.length;
int ledAddress = 4;
setPixelCount(numPixels);
println("pixel loading");
loadPixels();
println("pixel loaded123");
for (int i = 0; i < numPixels; i++) {
int pixelLocation = pixelLocations[i];
int pixel = pixels[pixelLocation];
packetData[ledAddress] = (byte)(pixel >> 16);
packetData[ledAddress + 1] = (byte)(pixel >> 8);
packetData[ledAddress + 2] = (byte)pixel;
ledAddress += 3;
if (true) {
pixels[pixelLocation] = 0xFFFFFF ^ pixel;
}
}
writePixels();
if (enableShowLocations) {
updatePixels();
print("a");
}
}
void setPixelCount(int numPixels)
{
int numBytes = 3 * numPixels;
int packetLen = 4 + numBytes;
if (packetData == null || packetData.length != packetLen) {
// Set up our packet buffer
packetData = new byte[packetLen];
packetData[0] = (byte)0x00;
packetData[1] = (byte)0x00;
packetData[2] = (byte)(numBytes >> 8);
packetData[3] = (byte)(numBytes & 0xFF);
}
}
void setPixel(int number, int c)
{
println("set");
int offset = 4 + number * 3;
if (packetData == null || packetData.length < offset + 3) {
setPixelCount(number + 1);
}
packetData[offset] = (byte) (c >> 16);
packetData[offset + 1] = (byte) (c >> 8);
packetData[offset + 2] = (byte) c;
}
int getPixel(int number)
{
println("get");
int offset = 4 + number * 3;
if (packetData == null || packetData.length < offset + 3) {
return 0;
}
return (packetData[offset] << 16) | (packetData[offset + 1] << 8) | packetData[offset + 2];
}
void writePixels()
{
println("write");
if (packetData == null || packetData.length == 0) {
return;
}
if (output == null) {
return;
}
try {
output.write(packetData);
} catch (Exception e) {
dispose();
}
}
public void dispose()
{
if (output != null) {
println("Disconnected from OPC server");
}
socket = null;
output = pending = null;
}
public void run()
{
println("?");
if(output == null) { // No OPC connection?
try { // Make one!
socket = new Socket(host, port);
socket.setTcpNoDelay(true);
pending = socket.getOutputStream();
println("Connected to OPC server");
sendColorCorrectionPacket();
sendFirmwareConfigPacket();
output = pending;
} catch (ConnectException e) {
dispose();
} catch (IOException e) {
dispose();
}
}
try {
Thread.sleep(500);
}
catch(InterruptedException e) {
}
}
}
You should only have one class that extends PApplet.
Think of that class as your "main" class. Any other classes that need to use Processing functions will need an instance of that main class in order to access Processing functions. You can pass it in using the this keyword.
In fact, you're already doing that- notice that you pass this into your OPC class, and then store it in the parent parameter. You just never do anything with that parameter.
So step 1 is to remove the extends PApplet from your OBC class:
public class OPC implements Runnable
This will cause some compilation errors. That's okay, we'll fix them later.
Step 2 is to actually store the PApplet parent parameter in a class-level variable.
OPC(PApplet parent, String host, int port){
this.parent = parent;
//rest of constructor
Now that you have that, step 3 is to fix any compilation errors by using the parent variable to access Processing functions.
parent.println("pixel loading");
parent.loadPixels();
More info can be found in the Processing in eclipse tutorial. It's for eclipse, but the same principles apply in netbeans.

Categories