Direct Bluetooth connection from App(No Particle Cloud)


#21

It should compile for both the root directory and the modules/ directory. The root directory will only build the user app and the bootloader, though, so you do need to compile from modules/ to get the system part.

I will have to fix this once and for all at some point, still dealing with some 4.9 issues since the Particle gulf servers use 4.8


#22

Hey @eric

Well I am able to compile and flash locally so I am getting somewhere.

I followed your instructions above and added a new data service to the registered_data_services.h file giving it a value of 3.
Then I created a header and source file for custom_data_service and then registered it in data_services.cpp However on compile I get an error undefined reference to `CustomDataService::instance() and I have absolutely no idea why. I included the header file for custom_data_service in the data_services.cpp file but it is just not working. Here is what I have:

custom_data_service.h:
#ifndef _CUSTOM_DATA_SERVICE_H
#define _CUSTOM_DATA_SERVICE_H

#ifdef __cplusplus

#include <stdint.h>
#include <stdlib.h>
#include "data_service.h"

class CustomDataService : public DataService
{
public:
    static CustomDataService* instance();

    //DataService functions
    virtual int32_t getServiceID();
    virtual int32_t DataCallback(uint8_t *data, int16_t length);

private:
    //this is a singleton class, so these all need to be private so they can't be called
    CustomDataService(){};
    CustomDataService(CustomDataService const&){};
    CustomDataService& operator=(CustomDataService const&);
    static CustomDataService* m_pInstance;
};

#endif
#endif	/* _CUSTOM_DATA_SERVICE_H */

custom_data_service.cpp:
#include <string.h>
#include “custom_data_service.h”
#include “data_management_layer.h”
#include “registered_data_services.h”
#include “deviceid_hal.h”

CustomDataService* CustomDataService::m_pInstance = NULL;

CustomDataService* CustomDataService::instance()
{
    if (!m_pInstance)   // Only allow one instance of class to be generated.
        m_pInstance = new CustomDataService;
    return m_pInstance;

}

//DataService functions
int32_t CustomDataService::getServiceID()
{
    return INFO_DATA_SERVICE;
}
int32_t CustomDataService::DataCallback(uint8_t *data, int16_t length)
{
    switch (data[0]) {
        case CUSTOM_DATA_SERVICE:
            uint8_t id[12];
            HAL_device_ID(id, 12);

            uint8_t rsp[13];
            rsp[0] = CUSTOM_DATA_SERVICE & 0xFF;
            memcpy(rsp+1, id, 12);

            DataManagementLayer::sendData(13, rsp);
            break;
    }
    return 1;
}

data_services.cpp:
#include “data_management_layer.h”
#include “info_data_service.h”
#include “socket_manager.h”
#include “custom_data_service.h”

//Data Services Functions
extern "C" {
void data_service_init(void)
{
    DataService* socketService = SocketManager::instance();
    DataManagementLayer::registerService(socketService);
    
    InfoDataService* infoService = InfoDataService::instance();
    DataManagementLayer::registerService(infoService);

    CustomDataService* dataService = CustomDataService::instance();
    DataManagementLayer::registerService(dataService);
}
}

registered_data_services.h:
#define SOCKET_DATA_SERVICE 1
#define INFO_DATA_SERVICE 2
#define CUSTOM_DATA_SERVICE 3

Error I am seeing is:
/Users/travis/GitHub/bluzDK-firmware/platform/MCU/NRF51/SPARK_Firmware_Driver/src/data_services.cpp:33: undefined reference toCustomDataService::instance()’`

Any ideas? I have no idea why it is saying undefined reference. Everything looks right to me. It is this line in data_services.cpp throwing the error:
CustomDataService* dataService = CustomDataService::instance();


#23

Sorry, forgot one step!

You need to add your course file to the list of files to compile here: https://github.com/bluzDK/bluzDK-firmware/blob/develop/platform/MCU/NRF51/SPARK_Firmware_Driver/src/sources.mk


#24

Thanks @eric

That did it. Sorry to drag this out so much :wink:


#25

Thank you for trying to make this work!


#26

@eric

What Services does the bluz module provide in the UUID? I’m trying to put together a debugging app for development here but can’t seem to discover the module by service. The UUID of the device I am coming up with in another scanner app is:
871E0223-38FF-77B1-ED41-9FB3AA142DB2

Sorry I am a little green with Bluetooth 4.0 but I’m sure I’ll get the hang of it eventually.


#27

The following are the UUID’s for the main service and characteristics:
> let BLUZ_UUID = "871E0223-38FF-77B1-ED41-9FB3AA142DB2"
let BLUZ_CHAR_RX_UUID = "871E0224-38FF-77B1-ED41-9FB3AA142DB2"
let BLUZ_CHAR_TX_UUID = “871E0225-38FF-77B1-ED41-9FB3AA142DB2”

So the first is the Service UUID and the second two are for the the characteristics that data is sent down to and then sent from. So in your app, you would receive on BLUZ_CHAR_RX_UUID and write to BLUZ_CHAR_TX_UUID when you want to transmit.

I am more than happy to give you access to our app source code if you would like, just send me over your GitHub username, it may help.


#28

@eric,

Just got back on this project again.

I am building the custom data service. I believe I need at least 3 functions to start. Here is what I had in mind:

bool CustomDataService::writeData(uint8_t *data, int16_t length);

bool CustomDataService::readData(uint8_t *buffer, int16_t length);

int16_t CustomDataService::available();

writeData seems like a no brainer, just use DataManagementLayer::sendData(data, len). However the DataManagementLayer does not appear to have a read function yet, also the ble_scs class which the DataManagementLayer uses for sending data does not appear to have any function for reading data either. I really can’t find anything that is actually writing data over bluetooth. Am I missing something or does this just need to be written from the ground up?

Thanks eric


#29

The current way it works is through a callback. So data gets handed down over BLE and the app can’t explicitly call read(). So there are two ways to do this:

  1. Offer a callback function that the user can implement at the user layer that gets called when the data is handed down. This would get called similar to our registerRadioNotifications callback (http://docs.bluz.io/reference/ble/#registerradionotifications) where the user would then have a function that gets called every time data is handed down. This would be easy, as the DataService::DataCallback function is already called, it is just a matter of exposing this at the user level

  2. Implement it as you have mentioned, where there is a read() and available() function. This would mean that the data getting handed down from BLE would have to be placed in a buffer, and then the buffer exposed to the user. This is how we handle sockets currently, you can see in Socket Manager how the DataCallback feeds it into a socket, which just gets placed into a buffer. The user could then call read and available, but this class would have to handle overflows and such and data could get lost if it isn’t polled fast enough

My personal preference was to do the first, the user can register a callback function and then act on the data in an interrupt-type fashion. This sticks closer to the framework we try and use for bluz where polling is bad and interrupts are good as it maximizes battery life.

Certainly open to other opinions though.


#30

Hi @eric

I think both are a good idea. Let the user register a call back to handle received data in an interrupt or let them poll, just leave it up to the user as I always say.

However I am still hung on how I actually read data from the bluetooth socket. I know this has something to do with the
BLE_SCS_UUID_DATA_DN_CHAR
But i just cant seem to put my finger on it. Any guidance on that?


#31

Do you mean read data on the bluz side? You don’t have to worry about the characteristics, the DatCallback function of your new DataService class will be called when data is written down. So you just need to handle the data in there, the function receives the byte array along with the length of it and you can do what you need with it.


#32

Hey @eric,

I have lost the ability to flash firmware for some reason. When I flash firmware I just get a solid Magenta LED on the Bluz module. Any insight on this?


#33

When does it go to solid magenta? When you start flashing? Or when it connects? What is the sequence of events that leads to solid magenta?

Also, what is the device ID of the troubled board?


#34

Hey @eric

Sorry for the rather generic description. Here is what I have going on.

I have the Bluz module in a breadboard along with a Particle Photon module as shown in the Talking Serial doc.

This is the code running in the Particle module:
// bluz serial transverter
void setup() {
Serial.begin(38400);
Serial1.begin(38400);
Serial.println(“Welcome to the bluz serial transverter!”);
}

void loop() {
    while (Serial.available() > 0) {
        Serial1.write(Serial.read());
    }
    while (Serial1.available() > 0) {
        Serial.write(Serial1.read());
    }
}

I downloaded the Python bootloader and am running that from the terminal. After the python script for firmware update is called I am asked for my binary file so I reference it by the full path. Immediately after i hit enter the LED on the Bluz module goes solid Magenta. I am unable to determine if this is something caused by by firmware alterations. Do you have a binary file I can try flashing to the controller so I can determine if it is just a problem with my fimrware or should I just clone another instance of the firmware from github, build, and flash that.

Thank you,


#35

That doesn’t sound like an issue with the binary file. Are you sure the serial port is hooked up properly? Have you successfully yes this setup to flashes are binaries through UART before?

Is the UART port open anywhere else? When the bootloader starts to take a new binary file, it reads it in chunks and then copies it to the external flash. After a chunk is flashed, the bootloader responds so that the python script knows to send the next chink. It sounds like the python script isn’t getting the notification back from he bootloader which would indicate something is wrong with the setup.

Can you flash firmware OTA?


#36

Hey @eric

Here is a photo of how the modules are wired:

Here is what I am seeing in the terminal when attempting to flash right after this the LED on the Bluz module goes solid magenta:

Traviss-MacBook-Pro:platform-103-m travis$ python ~/GitHub/bootloader_scripts/update_fw.py -s /dev/tty.usbmodem1A1221
Namespace(port='/dev/tty.usbmodem1A1221')
Welcome to bluz serial programmer!
Enter the firmware filename: myapp.bin
Writing file contents to serial
Wrote size
Got size back: 3116

I was previously able to flash. Not real sure what has gone wrong. I am not getting any build errors when compiling the code to the binary.


#37

Things I have tried:

Factory reset Bluz module.
New Particle module.
New Bluz module.
Updating OTA(works).
There is something wrong with my setup but for the life of me I have not been able to figure it out over the past 3.5 hours.


#38

Does the python script finish or does it just sit there like it is stuck?

If it is stuck, then for some reason the python script isn’t getting back the notification from the bootloader that the chunk has been received and processed. Not sure why that would be the case, let me try and set it up and see if I can reproduce.


#39

Here is my binary file you can try:
https://drive.google.com/file/d/0B5fTLsGWqbCBNXNZWVo5VERvUWM/view?usp=sharing

Python script just stops at Got size back: 3116 I let it sit there for about 30 minutes, nothing.

Also just checked all connections with a meter. I tested on the Bluz module and Photon module pins directly and everything is getting continuity as it should so the connections are definitely good.


#41

Ok, I am able to reproduce. I have a bluz board that I try to flash with a Photon and I can get in stuck in magenta state pretty easily. However, doing the same thing with my USB to Serial converter (this one) seems to work just fine.

I think it has to do with transferring large data through the Photon. I never actually tested FW updates through this method, it was originally a sort of cheap way for quick debugging.

Off the top of my head, my guess is that the Photon isn’t getting data pushed through fast enough, and that is causing the issue. The bootloader is expecting a 1024 byte chunk, and if the Photon can’t get things through fast enough and bytes get lost, that would cause this issue. I am trying to tweak the Photon sketch to get it to work, I have a few ideas.

Do you have access to a USB to Serial converter?