As per [ https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW4 ] the proper notification format appears to be:
OutputStream os; // assuming this connection is valid/open
// header
os.write(command); // 1 byte | value of 2 in doc but 1 in notnoop/java-apns ?
os.write(frame_length); // 4 bytes | value of total size of frame items:
// item 1 - token
os.write(item_id_1); // 1 byte | value of 1
os.write(item_length_1); // 2 bytes | value of size of data (32 for token):
os.write(item_data_1); // 32 bytes | token data
// = total frame item size: 35
// item 2 - payload
os.write(item_id_2); // 1 byte | value of 2
os.write(item_length_2); // 2 bytes | value of size of data (175 for my payload):
os.write(item_data_2); // 175 bytes | payload data
// = total frame item size: 178
// item 3 - identifier
os.write(item_id_3); // 1 byte | value of 3
os.write(item_length_3); // 2 bytes | value of size of data (4)
os.write(item_data_3); // 4 byte | identifier data
// = total frame item size: 7
// item 4 - expiration date
os.write(item_id_4); // 1 byte | value of 4
os.write(item_length_4); // 2 bytes | value of size of data (4)
os.write(item_data_4); // 4 byte | expiration data
// = total frame item size: 7
// item 5 - priority
os.write(item_id_5); // 1 byte | value of 5
os.write(item_length_5); // 2 bytes | value of size of data (1):
os.write(item_data_5); // 1 byte | priority data
// = total frame item size: 4
Assuming that's all correct, that should give a frame data length total of: 35 + 178 + 7 + 7 + 4 = 232 by summing all of the frame item totals.
However in looking over some of the notnoop/java-apns code:
public byte[] marshall() {
if (marshall == null) {
marshall = Utilities.marshallEnhanced(COMMAND, identifier,
expiry, deviceToken, payload);
}
return marshall.clone();
}
public int length() {
int length = 1 + 4 + 4 + 2 + deviceToken.length + 2 + payload.length;
//1 = ?
//4 = identifier length
//4 = expiration length
//2 = ?
//32 = token length
//2 = ?
//x = payload length
final int marshalledLength = marshall().length;
assert marshalledLength == length;
return length;
}
I fail to see how this is calculating the length correctly. My code however does not work while this presumably does. What am I doing wrong?
First problem: I was examining an enhanced format (uses command 1) while trying to use a new format (uses command 2).
Second problem: I wasn't using some form of ByteBuffering so the packet wasn't formed right.
The total frame size calculations were correct in both cases.
Related
I'm trying to write a simple output to a file but I'm getting the wrong output. This is my code:
Map<Integer,List<Client>> hashMapClients = new HashMap<>();
hashMapClients = clients.stream().collect(Collectors.groupingBy(Client::getDay));
Map<Integer,List<Transaction>> hasMapTransactions = new HashMap<>();
hasMapTransactions = transactions.stream().collect(Collectors.groupingBy(Transaction::getDay));
//DAYS
String data;
for (Integer key: hashMapClients.keySet()) {
data = key + " | ";
for (int i = 0; i <hashMapClients.get(key).size();i++) {
data += hashMapClients.get(key).get(i).getType() + " | " + hashMapClients.get(key).get(i).getAmountOfClients() + ", ";
writer.println(data);
}
}
I get this output
1 | Individual | 0,
1 | Individual | 0, Corporation | 0,
2 | Individual | 0,
2 | Individual | 0, Corporation | 0,
But it should be, also it should not end with , if it's the last one.
1 | Individual | 0, Corporation | 0
2 | Individual | 0, Corporation
| 0
What am I doing wrong?
It sounds like you only want to write data to the output in the outer loop, not the inner loop. The latter of which is just for building the data value to write. Something like this:
String data;
for (Integer key: hashMapClients.keySet()) {
// initialize the value
data = key + " | ";
// build the value
for (int i = 0; i <hashMapClients.get(key).size();i++) {
data += hashMapClients.get(key).get(i).getType() + " | " + hashMapClients.get(key).get(i).getAmountOfClients() + ", ";
}
// write the value
writer.println(data);
}
Edit: Thanks for pointing out that the last character also still needs to be removed. Without more error checking, that could be as simple as:
data = data.substring(0, data.length() - 1);
You can add error checking as your logic requires, perhaps confirming that the last character is indeed a comma or confirming that the inner loop executes at least once, etc.
One problem is that you are calling println after every Client, rather than waiting until the whole list is built. Then, to fix the problem with the trailing comma, you can use a joining collector.
Map<Integer,List<Client>> clientsByDay = clients.stream()
.collect(Collectors.groupingBy(Client::getDay));
/* Iterate over key-value pairs */
for (Map.Entry<Integer, List<Client>> e : clientsByDay) {
/* Print the key */
writer.print(e.getKey());
/* Print a separator */
writer.print(" | ");
/* Print the value */
writer.println(e.getValue().stream()
/* Convert each Client to a String in the desired format */
.map(c -> c.getType() + " | " + c.getAmountOfClients())
/* Join the clients together in a comma-separated list */
.collect(Collectors.joining(", ")));
}
I'm creating a Java Client program that sends a command to server and server sends back an acknowledgement and a response string.
The response is sent back in this manner
client -> server : cmd_string
server -> client : ack_msg(06)
server -> client : response_msg
Client code
public static void readStream(InputStream in) {
byte[] messageByte = new byte[20];// assuming mug size -need to
// know eact msg size ?
boolean end = false;
String dataString = "";
int bytesRead = 0;
try {
DataInputStream in1 = new DataInputStream(in);
// while ctr==2 todo 2 streams
int ctr = 0;
while (ctr < 2) {//counter 2 if ACK if NAK ctr=1 todo
bytesRead = in1.read(messageByte);
if (bytesRead > -1) {
ctr++;
}
dataString += new String(messageByte, 0, bytesRead);
System.out.println("\ninput byte arr "+ctr);
for (byte b : messageByte) {
char c=(char)b;
System.out.print(" "+b);
}
}
System.out.println("MESSAGE: " + dataString + "\n bytesread " + bytesRead + " msg length "
+ dataString.length() + "\n");
char[] chars = dataString.toCharArray();
ArrayList<String> hex=new ArrayList<>();
// int[] msg ;
for (int i = 0; i < chars.length; i++) {
int val = (int) chars[i];
System.out.print(" " + val);
hex.add(String.format("%04x", val));
}
System.out.println("\n"+hex);
} catch (Exception e) {
e.printStackTrace();
}
// ===
}
Output
client Socket created ..
response:
input byte arr 1
6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
input byte arr 2
2 -77 67 79 -77 48 -77 3 -116 0 0 0 0 0 0 0 0 0 0 0
MESSAGE: ##³CO³0³##
(where # is some not supported special character )
bytesread 9 msg length 10
dec: 6 2 179 67 79 179 48 179 3 338
hex: [0006, 0002, 00b3, 0043, 004f, 00b3, 0030, 00b3, 0003, 0152]
bytes: 2 -77 67 79 -77 48 -77 3 -116 0 0 0 0 0 0 0 0 0 0 0 (bytes recieved in 2nd packet)
connection closed
Problem: I'm reading the last value incorrect, I have verified using wireshark the server has sent back the response as 06 02 b3 43
4f b3 30 b3 03 8c
Some how I'm reading the last value in correctly. Is there some issue with the reading stream?
EDIT
Rest of the response is read correctly but the last character should be 8c But is read as 0152Hex
Response from server : 06 02 b3 43 4f b3 30 b3 03 8c
Read by program : [0006, 0002, 00b3, 0043, 004f, 00b3, 0030, 00b3, 0003, 0152]
issue with reading the last character
EDIT 2
Response is received as 2 packets/streams
packet 1 byte arr : 6 (ACK)
packet 2 byte arr: 2 -77 67 79 -77 48 -77 3 -116 (response)
complete response read by client
dec: 6 2 179 67 79 179 48 179 3 338
hex: [0006, 0002, 00b3, 0043, 004f, 00b3, 0030, 00b3, 0003, 0152]
Thanks
The problem in this question was a matter of signed variables versus unsigned variables. When you have a number in computer memory, it is represented by a bunch of bits, each of them 0 or 1. Bytes are generally 8 bits, shorts are 16 etc. In an unsigned number, 8 bits will get you from positive 0 to 255, but not to negative numbers.
This is where signed numbers come in. In a signed number, the first bit tells you whether the following bits represent a negative or positive value. So now you can use 8 bits to represent -128 to +127. (Notice that the positive range is halved, from 255 to 127, because you "sacrifice" half of your range to the negative numbers).
So now what happens if you convert signed to unsigned? Depending on how you do it, things can go wrong. In the problem above, the code char c=(char)b; was converting a signed byte to an unsigned char. The proper way to do this is to "make your byte unsigned" before converting it to a char. You can do that like this: char c=(char)(b&0xFF); more info on casting a byte here.
Essentially, you can just remember that except for char, all java numbers are signed, and all you need to do is paste the &0xFF to make it work for a byte, 0xFFFF to make it work for a short, etc.
The details about why this works are as follows. Calling & means a bitwise and, and 0xFF is hexadecimal for 255. 255 is above the limit of a signed byte (127), so the number b&0xFF gets upgraded to a short by java. However, the short signed bit is on bit 16, while the byte signed bit is on bit 8. So now the byte signed bit becomes a normal 'data' bit in the short, and so the sign of your byte is essentially discarded.
If you do a normal cast, java recognizes that doing direct bitconversion like above would mean that you lose the sign, and java expects you don't like that (at least, that is my assumption), so it preserves the sign for you. So if this isn't what you want, you explicitly tell java what to do.
I have an java app and I'm trying to print code. Everything works fine until my data is an integer,only digits. The printing is made in another function like this :
byte[] configLabel = getConfigLabel();
printerConnection.write(configLabel);
private byte[] getConfigLabel() {
byte[] configLabel = null;
String str=inputbarcode.getText().toString();
String str2 = "link";
StringBuilder print = new StringBuilder("! UTILITIES\r\n");
print.append("IN-MILLIMETERS\r\n");
print.append("SETFF 15 2.5\r\n");
print.append("PRINT\r\n");
print.append("! 0 180 180 180 1\r\n");
print.append("CENTER\r\n");
print.append("BARCODE 128 1 1 50 0 20"+str.toString()+"\r\n");
print.append("T 0 3 0 80"+str.toString()+"\r\n");
print.append("T 0 3 0 100"+str2+"\r\n");
print.append("PRINT\r\n");
configLabel=String.valueOf(print).getBytes();
return configLabel;
}
Your code snippet shows missing separator between the barcode and text commands and the actual barcode or text content. Insert one space character at the end of the following strings in your code:
change "BARCODE 128 1 1 50 0 20" to "BARCODE 128 1 1 50 0 20 "
change to "T 0 3 0 80" to "T 0 3 0 80 "
change "T 0 3 0 100" to "T 0 3 0 100 "
Im trying to read the weight from a scale using the serial port.
But i think i'm receiving data with and i don't know how to print it without the
My serial event:
public void serialEvent(SerialPortEvent event){
switch(event.getEventType()) {
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
outputBufferEmpty(event);
break;
case SerialPortEvent.DATA_AVAILABLE:
byte[] readBuffer = new byte[20];
try {
int numBytes = inputStream.read(readBuffer);
String str = new String (readBuffer, "UTF-8");
ok+=str;
//System.out.print(str);
System.out.println();
System.out.print(ok.replaceAll("\\s+", ""));
//System.out.print(str.replace("\n", "").replace("\r", ""));
} catch (IOException ex) {}
break;
}
}
I tried all.
But this is my output now:
0
0 0
0 0 0
0 0 0 .
0 0 0 . 0
0 0 0 . 0 5
0 0 0 . 0 5 0
0 0 0 . 0 5 0
And I want this:
000.050 KG
This is the protocol of my scale:
For more information my scale is: Mettler Toledo VIVA or an OHAUS RV Series
Why dont u try to make it directly to double?
import java.nio.ByteBuffer;
public static double toDouble(byte[] bytes) {
return ByteBuffer.wrap(bytes).getDouble();
}
I guess the answer is:
You created a string from the entire 20-byte byte array, rather than the portion that you just read.
Change the line that creates the string to:
String str = new String(readBuffer, 0, numBytes, "UTF-8")
The extra gaps in your output were probably caused by the null-bytes from the end of the array, although it's hard to know for sure without details on what type of output device you were using (not that important)
I have a web page with random 1's and 0's in the body and I want to treat it as raw binary data and save it to a file.
<html>
<head>...</head>
<pre style="word-wrap: break-word; white-space: pre-wrap;">1 0 1 0 1 1 1 1 1 0</pre>
</body>
</html>
Alternatively, I can get the file in one column. If I just url.openStream() and read bytes, it spits out ascii values (49 & 48). I'm also not sure how to write one bit at a time to a file. How do I go about doing this?
<pre style="word-wrap: break-word; white-space: pre-wrap;">1 0 1 0 1 1 1 1 1 0</pre>
This can be sent as two (base64) or three (hex) bytes, so I am assuming efficiency isn't an issue here. ;) Once you extract the String you can convert it with.
String s = "1 0 1 0 1 1 1 1 1 0";
long l = Long.parseLong(s.replaceAll(" ", ""), 2);
You can read bits into byte and then write bytes to a file:
int byteIndex = 0;
int currentByte = 0;
while (hasBits) {
String bit = readBit();
currentByte = currentByte << 1 | Integer.valueOf(bit);
if (++byteIndex == 8) {
writeByte(currentByte);
currentByte = 0;
byteIndex = 0;
}
}
// write the rest of bits here
Also I agree with Robert Rouhani, this is very inefficient way to transfer data.