I am sending this command AE A7 04 00 05 09 BC B7 to BLE, onCharacteristicWrite returns status=0, but BLE device does not send any data ( I mean I do not get any response ). So what is wrong ? Maybe I am sending in a wrong format ?
public void WriteValue()
{
mNotifyCharacteristic.setValue("AE A7 04 00 05 09 BC B7".getBytes());
mBluetoothGatt.writeCharacteristic(mNotifyCharacteristic);
}
On Android try set write type to WRITE_TYPE_NO_RESPONSE
Btw, you should use LightBlue to test first https://itunes.apple.com/us/app/lightblue-explorer-bluetooth-low-energy/id557428110?mt=8
Try to replace the third line with mNotifyCharacteristic.setValue(new byte[]{(byte)0xAE, (byte)0xA7, 4, 0, 5, 9, (byte)0xBC, (byte)0xB7});
Test use byte[ ]
I think it good then use getbyte
I use byte[ ] can write successful
You can try it
Byte[] data = new byte[5];
data[0]=xx;
data[1]=xx;
........
Characteristic.Setvalue(data);
If not work try use other road
Not the same characteristic
Related
I am getting raw data from OBD adapter, It is getting parsed for single line but for multiline response I am not able to parse.
I used below code to parse
String hexaData = getResult(); // getResult is here the raw data("4904014A4D422A490402333637364904033135303049040400000000") after parsing I am getting parsed value(JMB*36761500) which is correct and only working for single line
Log.i("CalID_hexa", hexaData);
final String result = getResult();
String workingData;
if (result.contains(":")) {//CAN(ISO-15765) protocol.
workingData = result.replaceAll(".:", "").substring(9);//9 is xxx49040701, xxx is bytes of information to follow.
Matcher m = Pattern.compile("[^a-z0-9 ]", Pattern.CASE_INSENSITIVE).matcher(convertHexToString(workingData));
if(m.find()) workingData = result.replaceAll("0:49", "").replaceAll(".:", "");
} else {//ISO9141-2, KWP2000 Fast and KWP2000 5Kbps (ISO15031) protocols.
workingData = result.replaceAll("49040.", "");
}
calId = convertHexToString(workingData).replaceAll("[\u0000-\u001f]", "");
L.stringStringHashMap.put("CAL_ID",calId);
public String convertHexToString(String hex) {
StringBuilder sb = new StringBuilder();
//49204c6f7665204a617661 split into two characters 49, 20, 4c...
for (int i = 0; i < hex.length() - 1; i += 2) {
//grab the hex in pairs
String output = hex.substring(i, (i + 2));
//convert hex to decimal
int decimal = Integer.parseInt(output, 16);
//convert the decimal to character
sb.append((char) decimal);
}
return sb.toString();
}
How to parse multiline response like below response on PID 09 04 from OBD Adapter:
18 DA F1 11 10 13 49 04 01 33 37 38
18 DA F1 1D 10 13 49 04 01 33 37 38
18 DA F1 11 21 30 35 2D 52 59 45 2D
18 DA F1 11 22 41 37 34 30 00 00 55
18 DA F1 1D 21 30 36 2D 52 59 45 2D
18 DA F1 1D 22 41 37 37 30 00 00 55
How can I parse the above?
If you want to parse multiple line responses as single line responses then you can first form the array from the multiple line response separating the lines by character \n. After forming the array of responses, you can join the strings in one single line.
You have two issues here. The first is that you sent your request using a broadcast address, that's why two ECUs (namely, 18 DA F1 11 and 18 DA F1 1D) answered to your request. You either have to sort these out or ask only one ECU directly.
The second is you should learn about ISO 15765-2 (also named ISO-TP), which is a transport protocol, much like TCP (or rather IP) is for Ethernet. https://en.wikipedia.org/wiki/ISO_15765-2 contains a rough outline.
A general notice: If you're serious about implementing OBD2 communication, write a layered architecture, in which the communication layer (BLE, TTY, TCP, etc.) sits below the vehicle protocol which ISO-TP sits on top of. On the actual application layer you can then decode the individual PIDs and their measurements.
I use client.screencap method from adbkit to get the PNG stream and save the image like this:
let stream = await client.screencap(deviceId);
stream.pipe(fs.createWriteStream('output.png'));
Rather, I want to resize it first because the output image is so big ( around 2 - 3 Mb ). So I try to get the buffer of the stream and resize it by reducing width, height (use Jimp library) and save the image.
let stream = await client.screencap(deviceId);
let chunks = [];
for await (const chunk of stream) {
chunks.push(chunk);
}
let buffer = Buffer.concat(chunks);
console.log(buffer);
// resize and save (Use Jimp library to read the buffer and resize)
...
in console.log(buffer), I got
<Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 00 00 01 73 ae ce 1c e9 00 00 00 04 ... 159002 more bytes>
But sometime I got empty buffer like this:
<Buffer >
I don't know why the buffer is empty. Because of client.screencap method is not stable?
Or they are an any better solution to do a thing like this?
I'm writing an app for reading binary infos of NFC tags. Here's the code of the NFC intent handler function:
protected void onNewIntent(#NonNull Intent intent)
{
try
{
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
NfcV nfcV = NfcV.get(tag);
byte[] cmdInfo = new byte[]{(byte) 0x02, (byte) 0x2b}; // 'Get info' command
byte[] answer = nfcV.transceive(cmdInfo); // Read info from tag.
...
}
catch(IOException e)
{
...
}
}
If I run this function reading an NFC tag on a Samsung S3 Neo everything works fine, the answer variable is filled with the expected data:
00 04 4B A0 14 01 00 A0 07 E0 F3 07
Howewer if I run the same function reading the same NFC tag on a Huawei P8lite the answer variable is filled with only one byte:
03
In case of an error, the ISO 15693-3 standard says that I should receive something like
01 03
I.e. at least two bytes, where the second byte is the error code. So the answer I'm actually getting is theoretically not possible.
What am I doing wrong? Does it depend on the mobile hardware? And how can I fix it?
Since you are not using an addressed command (Address_flag not set, no UID field in request). You should not receive any resonse at all if an optional command is not supported by the tag (not even an error code). Hence you should neither receive 03 nor 01 03 according to the standard.
Note that NFC chipsets in Android devices often have limitations when it comes to ISO/IEC 15693 and do not support the complete standard. For instance, some chipsets are known to have issues with non-addressed commands. You could work around that by using the addressed version of the command:
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
NfcV nfcV = NfcV.get(tag);
byte[] cmdInfo = new byte[]{
(byte)0x20,
(byte)0x2B,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 };
System.arraycopy(tag.getId(), 0, cmdInfo, 2, 8);
byte[] answer = nfcV.transceive(cmdInfo);
You might also want to test with different settings for the Data_rate_flag since the NFC chipset on your device might have problems with VICCs responding with at high data rate.
I'm trying to read the content of a Mifare Ultralight card using the NFC contactless reader ACR122U Android SDK.
I am able to get following hex values
01 03 A0 0C 44 03 15 D1 01 11 54 02 65 6E 33 34
But I am unable to get my actual data. Please guide me how to extract byte array from above hex values.
So it seems that you read 4 pages starting at page 4 from this MIFARE Ultralight tag. Moreover, the tag seems to be formatted according to the NFC Forum Type 2 Tag Operation specification (available from the NFC Forum website).
A Type 2 Tag contains a series of tag-length-value (TLV) structures:
01 (Tag: Lock Control TLV)
03 (Length: 3 bytes)
A0 0C 44 (Value: Information on position and function of lock bytes)
03 (Tag: NDEF Message TLV)
15 (Length: 21 bytes)
D101115402656E3334... (Value: NDEF message)
You would have to issue a read command for the next 4 pages to obtain the remaining data of the NDEF message.
For now, we know, that the tag contains an NDEF message starting with
D101115402656E3334
This translates to
D1 (Header byte of record 1)
- Message begin is set (= first record of an NDEF message)
- Message end is set (= last record of an NDEF message)
- Short record flag is set (= Payload length field consists of 1 byte only)
- Type Name Format = 0x1 (= Type field contains an NFC Forum well-known type)
01 (Type length: 1 byte)
11 (Payload length: 17 bytes)
54 (Type: "T")
02656E3334... (Payload field)
The payload field of an NFC Forum Text record decodes like this:
02 (Status byte: Text is UTF-8 encoded, Language code has a length of 2 bytes)
656E (Language code: "en")
3334... (Text: "34"...)
i am building android application which connect to nfc secure element and get data to the android device.for building secure element i used java card API.In the jcop tools send ATR command to reset the java card.This is the sending commands.
/card -a a000000003000000 -c com.ibm.jc.CardManager
resetCard with timeout: 0 (ms)
--Waiting for card...
ATR=3B F8 18 00 FF 81 31 FE 45 4A 43 4F 50 76 32 34 ;.....1.EJCOPv24
31 43 1C
ATR: T=1, FI=1/DI=8 (31clk/etu), N=-1, IFSC=254, BWI=4/CWI=5, Hist="JCOPv241"
=> 00 A4 04 00 08 A0 00 00 00 03 00 00 00 00
i am using jcop tools for that.Secure element part is complete.but my android application need to send more request to secure element at one second.I used create a tag and send data this way.
byte[] GET_STRING = {
(byte) 0x80, // CLA Class
0x04, // INS Instruction
0x00, // P1 Parameter 1
0x00, // P2 Parameter 2
0x10 // LE maximal number of bytes expected in result
};
result = tag.transceive(GET_STRING);
int len = result.length;
if (!(result[len-2]==(byte)0x90&&result[len-1]==(byte) 0x00))
throw new RuntimeException("could not retrieve msisdn");
byte[] data = new byte[len-2];
System.arraycopy(result, 0, data, 0, len-2);
String str = new String(data).trim();
tag.close()
But I need to know how to send ATR command using android isoDep connection. if it is not possible how to reset the java card after getting data.
Thanks
Sajith
Regarding your terminology:
On the contactless interface, you card does not have a reset sequence that produces an ATR. However, there is two comparable events on the contactless interface. One is turning the HF field off ann on. This causes a power-loss and consequently a hard reset of the card. The second one is to put the contactless card in HALT state and re-activate the card through the activation & selection procedure as specified in ISO/IEC 14443-3. This would typically also cause a card to reset its internal state.
Regarding your question of how to reset a contactless card that is connected through Android's IsoDep:
Hard reset: That's only possible through bringing the card out of the NFC device's read range and then scanning it again.
"Soft reset": On most devices this should be possible through closing and re-opening the connection using the IsoDep instance:
IsoDep isoDepTag = IsoDep.get(tag);
[...]
isoDepTag.close();
isoDepTag.connect();
[...]
However, you should be avare that some device (e.g. the Galaxy S4 in combination with certain Android versions) will not properly perform a soft reset (HALT + reactivation/selection) and, instead, just continue the previous connection.