This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Unable to send notification from central

I have adopted the S120/S110 multilink example to the following: central.zip and peripheral main.c

I want to send a notification from the central to the peripheral and back (the second notification was already implemented.

I know the error is in the line below, because when I comment it the connection remains active. Otherwise the connection is dropped and the peripheral request a new one.

I think I'm not using the correct value_handle. But where can I find the correct value?

I'm using SDK8 with S110v8 and S120v2 in Keil (on two nRF51 DK's).

Update

New code (entire project). Now I can send a write command as suggested by @Nathan. But I can send a notification from the peripheral to the central and a write command from central to peripheral. But when I first send a write command followed by a notification the peripheral crashes. Why?

Also, I used the rssi as defined in the SDK, but the received data is not really realistic (higher power than received). Is there a fix that keeps the current implementation or should I change everything to something as suggested in this post

Finally, any suggestions as to why my code is already to large for de nRF51 DK? When I define TRILATERATION Keil complains there isn't enough memory on the device.

  • The concept of "Handle Value Notification" is explicitly sending an asynchronous packet of data from the BLE GATT server to the GATT client over a characteristic at the next connection interval, or in your case from the BLE peripheral to the central. What you're looking for is the equivalent version for updating the value on the server from the client (central to peripheral), which is known as "write command" or "write without response" depending on your API. See the Bluetooth core specification 4.0, write command is described on page 503 and handle value notification is described on page 509. The connection is likely being dropped because you're attempting to perform an illegal action, as handle value notifications by definition can't be sent from client to server.

    On your central's code, you'll need to enable write without response permission on the characteristic you're trying to send the data over. I'll admit that my experience is somewhat limited to writing the peripheral code and not the central, so I won't be able to help you work out the gritty details. However, if you look at the default multilink central code you can find an example of a write request being done in client_handling.c, in the notif_enable function. Hopefully you can work out what needs to be done using that example (of course remembering to change the write_op value to BLE_GATT_OP_WRITE_CMD), or someone else can chime in with more specific information if you need additional help.

    Edit: Sorry, I don't know if it needs to be done central side, but the permission for write command definitely needs to be done in the peripheral code, as that contains the gatt server and its database information. Under the characteristic add function used by the service initialization, you'll want to add the line "char_md.char_props.write_wo_resp = 1;" to that function after the structure is initialized to zero by memset.

    Edit 2: See accepted answer above as to why some parts of this answer are inaccurate.

  • You say a notification can't be sent from client to server, but the Nordic examples does exactly that, not? I have made some - failed - attempts at trying to make it work. I'll update my code to a later version in a few moments because I had to make it SDK7.1 compatible because the nRF beacons use that version.

  • I took a brief look at your code, and could not see that you guard against sending notifications before the peer has enabled them - nor could I find any trace in the peripheral where it enabled them. Are you sure that this is not what is happening? The central is calling notif_enable() during initial DB discovery, which is why the peripheral is able to notify its values. The peripheral does not do anything like this, which makes you unable to send notifications.

    When debugging things like this, you can set a breakpoint in the application error handler function and catch the errors when they happen. You should then see what errorcode that was returned and the complete callstack, which helps you search for similar problems here on DevZone - or give an even more descriptive answer.

    I am also not completely sure what you are trying to accomplish here, but it seems to me that you just want to send data back and forth every now and then? And perhaps save it? If that is the case, normal write commands or write requests might be the easiest way. Even though notifications are able to transmit data, their purpose is to notify a GATT client that a value in the GATT server has changed, while simultaneously giving (parts of) the new data. But to not spam down every device with updates, you have to explicitly subscribe to each characteristic you want notifications about, and keep track of these preferences between connections (if bonded). This is a bit overkill for just sending data.

    @Nathan's answer: Both the central and the peripheral has a GATT server and a GATT client. They are completely role-agnostic. The only differences between our central and peripheral GATT implementations are the number of packet buffers (less on the central due to many links), that PPCP only exists for peripheral, and the fact that a characteristic with a CCCD has an individual CCCD for each link on the central. This means that you have to keep track of the connection handle in addition to the state of every CCCD, and look them up before sending. Any knowledge of GATT you have from S110 should apply to S120 if you keep these differences in mind.

  • Ok. I'll keep that in mind. What I'm trying to do: send a packet from central to peripheral, measure RSSI and send packet back containing RSSI data.

Related