Not able to send data to BLE Peripheral (ZL-RC04A) device - android

I am trying to write data using code snippet.
- (void)peripheral:(CBPeripheral *)peripheral1 didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
// Again, we loop through the array, just in case.
for (CBCharacteristic *characteristic in service.characteristics) {
// And check if it's the right one
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
NSString *payloadMessage = #"3N";
NSData *payload = [payloadMessage dataUsingEncoding:NSUTF8StringEncoding];
[_discoveredPeripheral discoverDescriptorsForCharacteristic:characteristic];
[_discoveredPeripheral writeValue:payload forCharacteristic:characteristic
type:CBCharacteristicWriteWithResponse];
[_discoveredPeripheral setNotifyValue:YES forCharacteristic:characteristic];
}
}
}
But getting error in
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error
{
}
As:
Error Domain=CBATTErrorDomain Code=3 "Writing is not permitted." UserInfo={NSLocalizedDescription=Writing is not permitted.}
Although same is working android.

You get that error if you use the wrong write type for the characteristic (given the characteristic is writable after all). There are two types of writing data to a characteristic:
CBCharacteristicWriteWithResponse: In this case you will get an acknowledge packet by the peripheral. You can think of this as a TCP packet.
CBCharacteristicWriteWithoutResponse: This is a "fire and forget" kind of write. You can think of this as a UDP packet.
Therefore, try to use CBCharacteristicWriteWithoutResponse instead of CBCharacteristicWriteWithResponse. If that does not work as well you might have to check if your characteristic is writable after all.

Related

How do I send/receive data using bluetooth in flutter?

I'm trying to receive and send data from and to an arduino uno. I've tried looking into flutter blue plugin and flutter bluetooth serial plugin ,flutter serial plugin
seems to be incomplete and flutter blue lacks examples or documentation, and the official github example is way too complicated and is irrelevant to what i want to do. I want a very simple method of sending or retrieving data from an arduino using a HC-05 module.
If you are working with a HC-05 module (No Low Energy Bluetooth). Use ´flutter_bluetooth_serial´ package. It is not a great package, but it should work.
This example may not work.
Scan for devices:
//Here the scan results will be saved
List<BluetoothDiscoveryResult> results = List<BluetoothDiscoveryResult>();
void startDiscovery() {
streamSubscription = FlutterBluetoothSerial.instance.startDiscovery().listen((r) {
results.add(r);
});
streamSubscription.onDone(() {
//Do something when the discovery process ends
});
}
Connect to device:
Use this function when you select a device from the result list.
BluetoothConnection connection;
connect(String address) async {
try {
connection = await BluetoothConnection.toAddress(address);
print('Connected to the device');
connection.input.listen((Uint8List data) {
//Data entry point
print(ascii.decode(data));
})
} catch (exception) {
print('Cannot connect, exception occured');
}
}
Send data:
Future send(Uint8List data) async {
connection.output.add(data);
await _connection.output.allSent;
}
Try the example app from the ´flutter_bluetooth_serial´-package now. They even included reading data from an HC-05-module! If you want something simpler, try extracting the essential code from the example and copycoding it into another app.

Web Bluetooth characteristic.writeValue break the connection automatically

I follows Google/chrome samples for Web Bluetooth. I have two writeValue operations. One is within the requestDevice promise and it works perfectly. Second one, I save the characteristic reference and writeValue when the action trigger. The message is sent but connection broke automatically. I am using Mac OSX 10.13.3 and chrome64 and modify Android BLE Peripheral Simulator (From google github)
The code segment ---
var bluetoothDevice;
var myCharacteristic;
navigator.bluetooth.requestDevice({
...
})
.then(device => {
bluetoothDevice = device;
....
})
....
.then(characteristic =>{
myCharacteristic = characteristic;
let encoder = new TextEncoder('utf-8');
let sendMsg = encoder.encode("hello");
/*
It works...
*/
myCharacteristic.writeValue(sendMsg);
})
....
function onSendMessage() {
if (!bluetoothDevice.gatt.connected) {
log("device is disconnected")
return
}
if (!myCharacteristic){
log("no characteristic defined")
return
}
let encoder = new TextEncoder('utf-8');
let sendMsg = encoder.encode("hello");
/*
message sent but auto disconnect the peripheral
*/
myCharacteristic.writeValue(sendMsg);
}
Does anyone has same experience and any suggestion for keep connection persistence for writeValue?
Your code looks good to me. A similar code can be found as well at https://googlechrome.github.io/samples/web-bluetooth/link-loss.html
However I wonder which characteristic you're trying to write to. If that is not supported, the Android device might simply disconnect.
Check out https://www.chromium.org/developers/how-tos/file-web-bluetooth-bugs#TOC-Android and grab Android adb logs if that helps.

Receiving socket information from netfilter NF_INET_PRE_ROUTING hook function in linux kernel

I wrote a netfilter hook function for incoming packets in linux kernel. Is there a way to get the receiving socket information from the hook function. The code is
register() {
hk.hook = hookfunction;
hk.hooknum = NF_INET_PRE_ROUTING;
hk.pf = PF_INET;
hk.priority = NF_IP_PRI_LAST;
}
static unsigned int hookfunction (void *priv,struct sk_buff,const struct nf_hook_state *state) {
if (skb->sk) {
printk("%d", skb->sk->sk_mark);
}
}
Lets assume I have a udp socket open at port 15000 and a udp packet arrives at port 15000. In the above written hook function how can I access the struct sock of the udp socket opened at port 15000. With the above code, the control doesnot pass the if(skb->sk) condition as if skb->sk is null. Can you please suggest me a way to get the struct sock of the socket or should I have to put the hook in some other position like NF_INET_LOCAL_IN,. I am also confused about the difference between NF_INET_XX_XX and NF_IP_XX_XX.
The kernel uses __inet_lookup_skb() internally to get sk from skb, which calls skb_steal_sock() first to check if skb->sk is NULL, if that is the case, it then calls __inet_lookup() to lookup sk.
However you might need to tweak the kernel a little bit because __inet_lookup_skb symbol is not exported and can't be called directly.
Some references from kernel source:
1 2 3
Regarding NF_INET_XX if you are talking about NF_IP_PRE_ROUTING and NF_INET_PRE_ROUTING I believe NF_IP_PRE_ROUTING is obsolete in recent kernel, as far as I know 4.4 has replaced it with NF_INET_PRE_ROUTING.
Hope that helps.

NTAG213: Android throws IOException when trying to authenticate with wrong password

I am writing an Android app which is supposed to authenticate with a write protected NTAG213 NFC tag from NXP. Using the proper password everything works fine and I get the PACK in return.
Trying to authenticate with a wrong password, my code does not behave as expected. According to the tag's description I should receive a NAK in this case but instead I get a TagLostException. Or do I get it wrong and everything behaves as expected? How can I then distinguish between a wrong password and an actual TagLostException?
I would be grateful, if anyone was able to tell me what I am doing wrong.
try {
nfcA.connect();
byte[] response = nfcA.transceive(new byte[]{
NTAG213_PWD_AUTH, mTagPassword[0], mTagPassword[1],
mTagPassword[2], mTagPassword[3]
});
// checking if response was a NAK
if (((byte) 0x00 == response[0]) ||
((byte) 0x01 == response[0]) ||
((byte) 0x04 == response[0]) ||
((byte) 0x05 == response[0])) {
nfcA.close();
result.setErrorCode(WRONG_PASSWORD);
return result;
}
}catch (TagLostException e){
result.setErrorCode(TAG_LOST_EXCEPTION);
e.printStackTrace();
return result;
}catch (IOException e){
result.setErrorCode(IO_EXCEPTION);
e.printStackTrace();
return result;
}
You are right that the tag will answer with a NACK response if the authentication command fails. This is just the same as for the case when a tag does not support a command.
Unfortunately, the various Android NFC stack implementations handle a NACK response in different ways. They either return the NACK value in the response byte array, return an empty response (?), or they generate an IOException (typically a TagLostException). Consequently, you cannot reliably distingush between cases where authentication failed, the command was not supported, or the communication with the tag as actually interrupted.
In order to detect if the tag is still there (and thus, it was just the command that failed for whatever reason), you could issue a READ command (or some other command that you would expect to succeed for your specific tag type) afterwards. If that fails as well, you can be certain that communication with the tag was lost.
Note that you need to disconnect (NfcA.close()) and reconnect (NfcA.connect()) the tag after a failed command and before you continue to send other commands. This should be done regardless of whether you received an IOException or an actual NACK response value from the transceive() method. This is usually necessary in order to reset the state of the tag after any command failure.

Receiving hexadecimal values from socket instead of strings on SocketServer

I opened a socket between an Android app and a python server. The combination is that the Server listens, and android connects to the Server.
Here is the server code. The problematic part takes place in the definition of handle :
import SocketServer
from time import sleep
import sys
HOST = '192.168.56.1'
PORT = 2000
class SingleTCPHandler(SocketServer.StreamRequestHandler):
def handle(self):
try:
while(1):
sleep(0.03)
data = self.rfile.readline().strip()
print data
except KeyboardInterrupt:
sys.exit(0)
class SimpleServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
allow_reuse_address = True
def __init__(self, server_address, RequestHandlerClass):
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)
server = SimpleServer((HOST, PORT), SingleTCPHandler)
try:
server.serve_forever()
except KeyboardInterrupt:
sys.exit(0)
The connection is established normally, and the Android app sends the following data to the socket:
'0:0'
But the data is received on the Server as:
'\x000\x00:\x000\x00'
The variable that receives the data is:
data = self.rfile.readline().strip()
and printing gives the regular format:
In [2]: print data
0:0
I didn't manage to step into the print function with pdb to see what it does.
I'm looking for a way to convert the '\x000\x00:\x000\x00' to '0:0'.
Please advise on a way to convert the variable. You are welcome to comment/criticize the whole implementation. This is my first project in dealing with sockets so i don't know the pitfalls.
Update
This was the original Android code:
String podaci = "0:0";
public void Socketic() throws IOException {
Socket mojSocket = new Socket(urlServer, port);
DataOutputStream izlazdata = new DataOutputStream(
mojSocket.getOutputStream());
while (podaci != "end") {
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
izlazdata.writeChars(podaci);
izlazdata.flush();
}
izlazdata.close();
mojSocket.close();
};
And the problem was, as you suspected in:
izlazdata.writeChars(podaci);
writeChars uses the method writeChar. The API documentation for writeChar states:
Writes a char to the underlying output stream as a 2-byte value, high byte first...
The two bytes represent the 16bits which UTF-16 uses for encoding.
When we changed it to everything started working:
izlazdata.writeBytes(podaci);
Update
Based on the answers given, here is how the unwanted string is to be interpreted in terms of characters.
This solves my concrete problem, however, if someone would give a more generic solution to what happend here so that a larger lesson can be learned.
If not, i will accept Esailijas answer in a few days.
You need to show the code happening Android but it strongly seems like it's sending data in UTF-16BE. You should specify the encoding on the Android end. The characters are not hexadecimal literally, but because the NUL character is unprintable, python shows \x00 instead.
Another option is to decode it:
self.rfile.readline().decode("utf_16_be").strip()
note that the result of this is an unicode string.

Categories

Resources