This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Button State after connection

We are testing the SensorTag and found and issue which can probably only be solved by changing the SensorTag software itself.

The state of the 2 buttons can only be aquired with a notification.

This notification is only sent when the state of a button changes!

Because of this, the state after connecting to a SensorTag is wrong whenever a button is already pressed.

Since you aren't allowed to read the buttons state, there is no way to solve this.

Any suggestions??

  • Actually, you can read key status from SensorTag. You can read the value of P0_0, P1_6, and P1_7 to check the key status anytime you like.

  • Can you explain how we can do this since the sensortag return that the keys can only be used with notify and reading them returns an error.

  • For example, SW_1 is trigger by GPI P0.0 so you can use the following line to check whether SW_1 is pressed.

    if (P0_0==0x0){

    //SW_1 pressed!!

    } else {

    //SW_1 released.

    }

  • I understand how I can read the status in the SensorTag itself but my problem is that you can't read the button status over Bluetooth. The Bluetooth Simple Key Service (0xFFE0) only support notifications not reading!

    My question is how can we change the SensorTag program in a way so that we can read the button status instead of having to wait for a change. When you press 1 of the buttons and then run the demo app on a phone, you'll see that the buttons are shown as unpressed. It's only after you make a state change that they update. This is due to the fact that the program subscribes to change notifications, but can't read the initial state when the connection opens.

    Another solution would be to send a notification as soon as the connection is opened, but I haven't located the SensorTag code yet where the connection is actually fully established. Because calling the key notification routine there would also suffice.

  • There is no way to initially read the characteristics without changing the firmware

    But there is some good news too! All the code to read the button state is already there, but the permissions are hard coded not to let you read the data. The first thing to change is the permissions. Find the attribute table in simplekeys.c. The table's name is simplekeysAttrTbl.  Find the struct that contains a pointer to skKeyPressed,  and put "GATT_PERMIT_READ" in the second field. No quotes

    Also you need to change the description of the data's permission or your app likely won't work right.  

    Set skCharProps = GATT_PROP_NOTIFY | GATT_PROP_READ; It should already have the notify discriptor, you just need to add the read discriptor.

    If you have trouble finding the variables. use Ctrl + Shift + f to find stuff

    I described all this assuming you own a CCdebugger and IAR. If you don't (and therefor can't flash the sensor tag), you will need to do an OAD. 


    Don't forget to hit that verified answer button!

  • Thank you for your comment Peter.

    I had already downloaded the eval version of IAR and in the source code I saw that the read permission was missing.

    I knew that beforehand because in my iPhone App it showed for the simplekey characteristic that it only supported notify.

    So I added the read permission as you wrote, compiled the project and did and OAD.

    Now in my iPhone App I get not only the notify but also the read permission. But the initial values returned are bogus - they are random and wrong! Since I don't have a JTAG probe I can't remote debug the firmware. But i did several changes to see if I can read in the right key value in the SK_GetParameter routine, but the values I get returned in my iPhone App stay bogus. Once I press or release a button, the state updates to the right value.

    I change the case SK_KEY_ATTR to do this:

    case SK_KEY_ATTR:

    // *((uint8*)pValue) = skKeyPressed;

    if (!(HAL_KEY_SW_1_PORT & HAL_KEY_SW_1_BIT)) /* Key is active low */ { keys |= HAL_KEY_SW_1; }

    if (!(HAL_KEY_SW_2_PORT & HAL_KEY_SW_2_BIT)) /* Key is active low */ { keys |= HAL_KEY_SW_2; }

    if (!(HAL_KEY_SW_3_PORT & HAL_KEY_SW_3_BIT)) /* Key is active low */ { keys |= HAL_KEY_SW_3; } *((uint8*)pValue) = keys;

    skKeyPressed = keys; // See if Notification/Indication has been enabled

    GATTServApp_ProcessCharCfg( skConfig, &skKeyPressed, FALSE, simplekeysAttrTbl, GATT_NUM_ATTRS( simplekeysAttrTbl ), INVALID_TASK_ID );

    break;

    I wonder if this gets called....

    Especially since the initial returned value is random!

    Gr. Joshua

  • I think you are editing the wrong callback function. The BLE read function (callback) should have a case statement based on the UUID i.e. you are given a UUID in the read request, therefor should case statement should look like "case SK_KEYPRESSED_UUID:" Thins makes me thing you are editing the Get/Set functions which are used by other parts of the firmware to set the values. You are interested in editing sk_ReadAttrCB, not SK_GetParameter.

    other things to try:

    Edit permissions on an unedited version of the source code

    Download light blue (iOS only). It is my go to authoritative for on basic BLE functions when apps don't seem to be working right.

  • Ok, I've started with a clean version of the code.
    It could very well be that I was editing the wrong routine as I have no experience with BLE).
    Strange thing is that I've changed the sk_ReadAttrCB routine to return a fixed value:
    pValue[0] = 0xAA;

    But when reading 0xFFE1 I never get this value back... :-(
    So I still wonder where the key value is requested.

    Gr. Joshua

  • A little more info.

    I've downloaded the Lite Blue App.

    The keys return read and notify properties as they should so that change went fine.

    When reading, I get a (null) returned.

    When I turn on listen to changes, I continuously receive 0xAA when pressing keys, so the change does something...

    But it is not the place where the read command is handled from.

  • skKeyPressed stores the value of the keys. When you hit a key an ISR is triggered and the signal eventually sets skKeyPressed after going through a few layers of the stack. 

    The wireless read request is handled in sk_ReadAttrCB. pValue is a pointer to where you should store the data you want to send (where send = reply to read request). pLen is a pointer to where the length is specified. Basically the goal of sk_ReadAttrCB is to set *pLen = X and to write X bytes starting at address pValue.

    You left "*pLen = 1;" right? And edited the permissions? It works for me :(

    Though my senor tag is really buggy and it drops connections when I press the buttons.

  • Ok, I've found the problem!!!

    I only added the read permission here:

    // Keys Pressed Characteristic Properties

    static uint8 skCharProps = GATT_PROP_READ | GATT_PROP_NOTIFY;

    but should also have added it in the 

    static gattAttribute_t simplekeysAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] declaration for the simplekeys like this:

    // Characteristic Value- Key Pressed { { ATT_BT_UUID_SIZE, keyPressedUUID }, GATT_PERMIT_READ,0, &skKeyPressed },

    and now it works!

    thanks a lot Peter for the help and pointers in the right direction.

  • That was literally the first step of my first post in this thread.... Perhaps I should write clearer directions.

    But anyways, ヽ༼ຈل͜ຈ༽ノ HOORAY ヽ༼ຈل͜ຈ༽ノ

  • Reading your post back, I must conclude that was totally my error!

    I must have missed it for some reason.

    Anyway thanks again for the help.