I am trying to send images via two ports namely COM5 and COM7.
Following code does the most. Most significant part of the code is captureAndsaveImage method.
The problem is when i use both serial ports; images are getting distorted they feel like they are getting mixed up.
My question: Is it possible to use both port simaltaneously? What should i do such that there is no mixing up?
Don't mind second image's black circle it might have happened due to some signal losses in the second camera.
public class ReadPort {
private static final char[]COMMAND = {'*', 'R', 'D', 'Y', '*'};
private static final int WIDTH = 320; //640;
private static final int HEIGHT = 240; //480;
SerialPort serialPort,serialPort2;
public int[][] rgb2 = new int[WIDTH][HEIGHT];
public static void main(String[] args) {
ReadPort reader= new ReadPort();
}
public ReadPort() {
int[][]rgb = new int[HEIGHT][WIDTH];
try {
serialPort = SerialPort.getCommPort("COM7");
serialPort.openPort();
inputStream = serialPort.getInputStream();
serialPort.setComPortParameters(1000000,
8,
SerialPort.ONE_STOP_BIT,
SerialPort.NO_PARITY);
if(serialPort.isOpen()){
System.out.println("COM5 opened");
}
serialPort2 = SerialPort.getCommPort("COM5");
serialPort2.openPort();
inputStream2 = serialPort2.getInputStream();
serialPort2.setComPortParameters(1000000,
8,
SerialPort.ONE_STOP_BIT,
SerialPort.NO_PARITY);
if(serialPort2.isOpen()){
System.out.println("COM7 opened");
}
int counter = 0;
while(true) {
captureAndsaveImage( inputStream2,counter, rgb, "COM5");
captureAndsaveImage(inputStream, counter, rgb, "COM7");
counter++;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void captureAndsaveImage(InputStream inputStream, int counter,int[][] rgb,String name) throws IOException{
while(!isImageStart(inputStream, 0)){};
System.out.print("Found image: " + counter);
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
int temp =read(inputStream);
rgb[y][x] = ((temp&0xFF) << 16) | ((temp&0xFF) << 8) | (temp&0xFF);
}
}
BMP bmp = new BMP();
bmp.saveBMP("c:/out/" +name+"images/"+ counter + ".bmp", rgb);
System.out.println(", Saved image:"+name+"images/"+counter+".bmp");
}
private static int read(InputStream inputStream) throws IOException {
int temp = (char) inputStream.read();
//System.out.print(temp);
if (temp == -1) {
throw new IllegalStateException("Exit");
}
return temp;
}
private static boolean isImageStart(InputStream inputStream, int index) throws IOException {
if (index < COMMAND.length) {
if (COMMAND[index] == read(inputStream)) {
return isImageStart(inputStream, ++index);
} else {
return false;
}
}
return true;
}
}
Edit: I used a debug statement like
if(inputStream.available()>0){
System.out.println(inputStream.toString());}
in the captureAndsaveImage method and i got output like
COM5 opened
COM7 opened
Found image:
0com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#7f31245a
, Saved image:COM5images/0.bmp
Found image:
0com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#6d6f6e28
, Saved image:COM7images/0.bmp
Found image:
1com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#7f31245a
, Saved image:COM5images/1.bmp
Found image:
1com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#6d6f6e28
, Saved image:COM7images/1.bmp
Found image: 2, Saved image:COM5images/2.bmp
Found image:
2com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#6d6f6e28
, Saved image:COM7images/2.bmp
Found image:
3com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#7f31245a
, Saved image:COM5images/3.bmp
Found image:
3com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#6d6f6e28
, Saved image:COM7images/3.bmp
Found image: 4, Saved image:COM5images/4.bmp
Found image:
4com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#6d6f6e28
, Saved image:COM7images/4.bmp
Found image:
5com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#7f31245a
, Saved image:COM5images/5.bmp
Found image:
5com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#6d6f6e28
, Saved image:COM7images/5.bmp
Found image: 6, Saved image:COM5images/6.bmp
Found image: 6, Saved image:COM7images/6.bmp
Found image:
7com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#7f31245a
, Saved image:COM5images/7.bmp
Found image:
7com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#6d6f6e28
, Saved image:COM7images/7.bmp
Found image: 8, Saved image:COM5images/8.bmp
Found image:
8com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#6d6f6e28
, Saved image:COM7images/8.bmp
Found image:
9com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#7f31245a
, Saved image:COM5images/9.bmp
Things i observe is that some lines are like
Found image: 6, Saved image:COM5images/6.bmp
and most of them are
Found image:
5com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#6d6f6e28
, Saved image:COM7images/5.bmp
What is the reason? As far as i know com.fazecast.jSerialComm.SerialPort$SerialPortInputStream#6d6f6e28 this is supposed to be address of the inputStream. But why it is not happening in some cases?
(I am beginner in Serial communication.)
Hurray! I have solved my problem. Even though solution isn't elegant.
I put a block of code in the start of captureAndsaveImage method like
while(inputStream.available()>0){
int temp=read(inputStream);
}
And now I am getting cleared image. I have some vague idea how it worked
but i would love if anyone can give logic for these.
Edit: I observe that distorted images were coming in odd frames. So the above code just skips those frames shows even frames which are not mixed up. :/
Your code seems to be very disorganized. For example, where you open COM5, your debug messages says it's opening COM7 and vice versa.
However, the bug causing the issue you raised in your question is with these lines of code:
while(true) {
captureAndsaveImage( inputStream2,counter, rgb, "COM5");
captureAndsaveImage(inputStream, counter, rgb, "COM7");
counter++;
}
As you can see, you're storing the data from both image sources into the same array, rgb. Your code has an rgb2, so I suspect you meant to use one of those with COM5 and the other for COM7, though the array declarations being at different scopes is strange. I would suggest you review your code, and perhaps focus on getting things working with one serial port/data source before introducing a second.
Edit: reading your comment and reviewing your error, I found another bug:
private static boolean isImageStart(InputStream inputStream, int index) throws IOException {
if (index < COMMAND.length) {
if (COMMAND[index] == read(inputStream)) {
return isImageStart(inputStream, ++index);
}
else {
return false;
}
}
return true;
}
Here, isImageStart() could return true if it works out that you missed the starting character in a stream. Essentially, since you recursively call isImageStart, if you start with a stream that doesn't contain the command character, you will run until you reach COMMAND.length, at which point, the next recursive call would skip the if (index < COMMAND.length) and return true. So, if you have a case where you started reading too soon (or too late), isImageStart() will still return true. Then, in CaptureAndSaveImage(), you still continue calling read on the inputstream and likely are reading stale data from the previous stream. Except by that point, the stream may be valid and depending on how fast data is coming in, you will have a mix of the previous image and the one currently being received.
I aim to use code via https://github.com/davidgyoung/ble-advert-counter/blob/master/app/src/main/java/com/radiusnetworks/blepacketcounter/MainActivity.java
to scan and read BLE device's adverting data.
The code works well. I could get the formatted adverting data via LogCat as pic shown.
But in the code I can't find the related log statement.
I didnt see BluetoothLeScanner class or onScanResult() method invoked.
And I want to obtain the String "ScanResult{mDevice=F3:E5:7F:73:4F:81, mScanRecord=ScanRecord..." to get the formatted data value.
How can I achieve this?
Thanks
I'm not sure about the logs but here's how you can get the data.
onLeScan() callback has all the information that is being printed in the logs. To get the device information you can use the device object from the call back(ex. device.getAddress()). Scan record will be in the callback's scanRecord byte array. You need to parse the array to get the information. I've used below code to parse the scan information.
public WeakHashMap<Integer, String> ParseRecord(byte[] scanRecord) {
WeakHashMap<Integer, String> ret = new WeakHashMap<>();
int index = 0;
while (index < scanRecord.length) {
int length = scanRecord[index++];
//Zero value indicates that we are done with the record now
if (length == 0) break;
int type = scanRecord[index];
//if the type is zero, then we are pass the significant section of the data,
// and we are thud done
if (type == 0) break;
byte[] data = Arrays.copyOfRange(scanRecord, index + 1, index + length);
if (data != null && data.length > 0) {
StringBuilder hex = new StringBuilder(data.length * 2);
// the data appears to be there backwards
for (int bb = data.length - 1; bb >= 0; bb--) {
hex.append(String.format("%02X", data[bb]));
}
ret.put(type, hex.toString());
}
index += length;
}
return ret;
}
Refer the below link to understand about the ble date advertisement.
BLE obtain uuid encoded in advertising packet
Hope this helps.
hello i am new with byte manipulation in java. i already have byte array with flowing format
1-> datapacketlength (length of name) (first byte)
2-> name (second byte + datapacket length)
3-> datapacketlength (length of datetime)
4-> current date and time
how can i extract the name and current date and time.should i use Arrays.copyOfRange() method.
Regards from
mcd
You can use ByteBuffer and use your current byte array, then use the methods that come with it to get the next float, int etc (such as buffer.getInt and buffer.getFloat).
You can get a portion of your byte array when you create a new bytebuffer by using the wrap method I believe. The possibilities are endless :). To get strings as you asked, you simply need to do something like:
byte[] name = new byte[nameLength];
buffer.get(name);
nameString = byteRangeToString(name);
where byteRangeToString is a method to return a new string representation of the byte[] data you pass it.
public String byteRangeToString(byte[] data)
{
try
{
return new String(data, "UTF-8");
}
catch (UnsupportedEncodingException e)
{
/* handle accordingly */
}
}
See: http://developer.android.com/reference/java/nio/ByteBuffer.html
Using copyOfRange() may run you into memory issues if used excessively.
What about something like :
int nameLength = 0;
int dateLength = 0;
byte[] nameByteArray;
byte[] dateByteArray
for(int i=0; i<bytesArray.length; i++){
if(i == 0){
nameLength = bytesArray[i] & 0xFF;
nameByteArray = new byte[nameLength];
}
else if(i == nameLength+1){
dateLength = byteArray[i] & 0xFF;
dateByteArray = new byte[dateLength];
}
else if(i < nameLength+1){
nameByteArray[i-1] = bytesArray[i];
}
else{
dateByteArray[i-(nameLength+1)] = bytesArray[i];
}
}
You want to use a DataInputStream.
In my current project I have to read a JavaScript file from the web and extract an object from it. The variable can vary from time to time, so I have to read it instead of hard coding it into my android app.
Say I want to extract the following variable (and parse the string using JSONObject after that, which is trivial):
var abc.xyz = {
"a": {"one", "two", "three"},
"b": {"four", "five"}
}
I have a problem with this. Do I have to implement some compiler-like scanner just to look for the name and get its value, or there is some existing tool I can use?
The JavaScript file is not as simple as this example. It contains a lot of other code. So a simple new JSONObject() or something will not do.
There are many libraries in Java to parse the JSON. There is a list on JSON.org
Read the file with Java
import org.json.JSONObject;
URL url = new URL("http://example.com/foo.js");
InputStream urlInputStream = url.openStream();
JSONObject json = new JSONObject(urlInputStream.toString());
Finally code it myself.
//remove comments
private String removeComment(String html){
String commentA = "/*";
String commentB = "*/";
int indexA, indexB;
indexA = html.indexOf(commentA);
indexB = html.indexOf(commentB);
while(indexA != -1 && indexB != -1 ){
html = html.substring(0, indexA) + html.substring(indexB + commentB.length());
indexA = html.indexOf(commentA);
indexB = html.indexOf(commentB);
}
return html;
}
//find variable with name varName
private String findVar(String varName, String html, char lBrace, char rBrace){
String tmp = html.substring(html.indexOf(varName));
tmp = tmp.substring(tmp.indexOf(lBrace));
int braceCount = 0;
int index = 0;
while(true){
if(tmp.charAt(index) == lBrace){
braceCount ++;
}else if(tmp.charAt(index) == rBrace){
braceCount --;
}
index ++;
if(braceCount == 0){
break;
}
}
return tmp.substring(0, index);
}
I'm translating one app from java to php and i'm finding some trouble.
I have a string like this 98191107990D0000EF050000789C65970BCCD75318C7CFEFFC ... in java there's this function where I pass this string as parameter:
private static byte[] decodeNibbleHex(String input)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
char[] chars = input.toCharArray();
for (int i = 0; i < chars.length - 1; i += 2) {
char[] bChars = new char[2];
bChars[0] = chars[i];
bChars[1] = chars[(i + 1)];
int val = Integer.decode("0x" + new String(bChars)).intValue();
baos.write((byte)val);
}
return baos.toByteArray();
}
but... i don't know to to translate this function in PHP... i tried too many times and i'm becoming crazy! i tried with a for cycle, with this eval("\$hex = 0x" . $dati[$i].$dati[$i+1] . ";"); and this $binary_string = pack("h*" , $dati[$i].$dati[$i+1]); and many many other functions...
If someone understand Java and can help me I will appreciate it!!
Thank guys!
Take a look here:
http://www.php.net/manual/de/function.hexdec.php#100578
Is this not exactly what you whrere looking for?
If my understanding is correct of your java function, it takes the string's chars in pairs, and threats them as bytes and put them in a ByteArray. In php there's no such thing as a byte array but you can represent random binary data in everyday strings. This is my take on your function (didn't tried to compare with the java code's output).
$str= '98191107990D0000EF050000789C65970BCCD75318C7CFEFFC';
$output[] = array();
for ($i=0, $c = strlen($str) - 1; $i < $c; $i+=2) {
$output[] = chr(intval($str[$i].$str[$i+1], 16));
}
print join($output); // binary string, not really useful in ascii terminal (-:
In summary this seem to be a base16_decode() function, with base16_encode() written like it follows, you get back the input string:
function base16_encode($str) {
$byteArray = str_split($str);
foreach ($byteArray as &$byte) {
$byte = sprintf('%02x', ord($byte));
}
return join($byteArray);
}
print base16_encode(join($output)); // should print back the original input.