opendroneid / opendroneid-core-c

Open Drone ID Core C Library
Apache License 2.0
178 stars 64 forks source link

Can we use raspberry pi 3 b+ and simulate the drone through bluetooth #42

Closed punithbm closed 3 years ago

punithbm commented 3 years ago

I was trying to simulate the drone by using raspberry pi 3 b+ to run this application. I was able to successfully run the test application inside the Raspberry Pi OS. (have attached the screenshot for the same) IMG_7288 (1)

Now I am trying to figure out how can we connect this stream to get emitted in raspberry pi device Bluetooth. If anyone can help here, is very much appreciated

friissoren commented 3 years ago

I unfortunately personally don't have time at the moment to help with this kind of task. However, if you do manage to figure out how to do this, I would be very interested in hearing the results of it.

If you are willing to provide this kind of code, that could even be something we add to this or another repository here. It would be very useful to have example transmit code for BT4 and/or WiFi NaN/Beacon transmission on Raspberry PI HW.

Just FYI: For BT, if you run into problems with the fixed header values and the filter in the Android receiver app, the discussion here might be of use.

gabrielcox commented 3 years ago

Since you're using a RPi I think the best approach would be to try to leverage Bluetooth libraries for Linux. Have you looked at BlueZ (bluez link) ? I think if bluez works on the RPi and you follow the sample code here: example-advertisement link , you may able to get it (signs of life) to work. I would start with substituting the following:

class TestAdvertisement(Advertisement):

        Advertisement.__init__(self, bus, index, 'peripheral')
        self.add_service_uuid('FFFA')  // notice substitution
        self.add_service_data('FFFA', [<counter>, <msg type/version>, <data byte>, <data byte>,...])  // replace your data here
        self.add_local_name('OpenDroneID')
        self.include_tx_power = True

I found this interesting as well: https://stackoverflow.com/questions/47427913/advertise-custom-service-uuid-with-bluez-5-4x The opendroneid service id is 0xFFFA

I haven't tried any of this above, but this would be my starting place if attempting to make this work under linux.

Let us know how it goes. As Soren said, we would be happy to embrace this dev effort and add an additional repository under opendroneid called "transmitter-linux".

Also, I would certainly recommend debugging with some some Bluetooth scanner like NRF Connect,

friissoren commented 3 years ago

Possibly the discussion here might be of some use also?

If you manage to get bluez to output something, it should be possible to pick it up in the Android nRF Connect application and you can then start comparing against the example binary strings given in the issue, to ensure you send out the data in the correct format?

friissoren commented 3 years ago

One very delayed addition to this discussion. I managed to get at least legacy advertising to transmit something from an Ubuntu desktop machine to the Android receiver application. This only worked for me on Ubuntu 20.04.2 with kernel 5.8.0-63-generic. I tried also on 18.04.5 with kernel 5.4.0-77-generic but that would always fail with an advertising timeout (probably some kernel/driver/something mismatch). This was on a CometLake Z490 desktop with built in WiFi/BT.

I did get it running also on a RaspberryPi4 running Debian/GNU 10 with RaspberryPi kernel 5.10.17-v8+.

wget www.kernel.org/pub/linux/bluetooth/bluez-5.60.tar.xz tar xvf bluez-5.60.tar.xz gedit bluez-5.60/test/example-advertisement

Find the TestAdvertisement class and change the init function to contain only the following:

    def __init__(self, bus, index):
        Advertisement.__init__(self, bus, index, 'peripheral')
        self.add_service_data('FFFA', [0x0D, 0x00, 0x10, 0x20, 0x38, 0x00, 0x00, 0x58, 0xD6, 0xDF, 0x1D, 0x90, 0x55,
                                       0xA3, 0x08, 0x82, 0x0D, 0xC1, 0x0A, 0xCF, 0x07, 0x28, 0x03, 0xD2, 0x0F, 0x01, 0x00])

Then execute with “python3 example-advertisement”. I found it useful to have “sudo btmon” running in a separate shell to get a bit more debug output.

The above just sends out a hard-coded location message and nothing else but is at least enough to prove that data is flowing. I pulled the example data from this discussion (which gives some instructions on how to configure the Android app nRF Connect to simulate the same).

Despite btmon talking about Extended Advertising, it clearly cannot be using that (or then there is some other limitation somewhere) since whenever I tried to add more data than what fit in legacy advertising, it would throw an error at me. I don’t know if it is possible to get this example code to use the Long Range and Extended Advertising features.

friissoren commented 3 years ago

For WiFi Beacon, I found out the following. When using hostapd on Linux, it is possible to update the Information Element content of the beacon data by using the hostapd_cli interface. I got the following working on a RaspberryPi 4 (would probably work on Ubuntu also). The Pi cannot be connected to any WiFi networks: that seems to prevent it from going properly into the Access Point mode. The version of hostapd that by default gets installed by apt on Raspbian GNU/Linux 10 (buster) is too old (2.8-devel). I had to fetch the source code and compile it to get a version that supported the update beacon command.

sudo apt install libssl-dev libnl-3-dev
git clone git://w1.fi/hostap.git
cd hostap/hostapd
cp defconfig .config
make -j4

(If some dependency is still missing, the full set seems to be: sudo apt install build-essential git libpcap-dev libsqlite3-dev binutils-dev bc pkg-config libssl-dev libiberty-dev libdbus-1-dev libnl-3-dev libnl-genl-3-dev libnl-route-3-dev )

Create a configuration file with this content:

country_code=GB
interface=wlan0
ssid=DroneIDTest
hw_mode=g
channel=6
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=thisisaverylongpassword
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
ctrl_interface=/var/run/hostapd

#This is an empty information element. dd indicates hex. 01 is the length of the data and 00 the actual data:
vendor_elements=dd0100

#This information element has one fixed Location message:
#vendor_elements=dd1EFA0BBC0D00102038000058D6DF1D9055A308820DC10ACF072803D20F0100

For testing purposes, it is enough to start the access point using the configuration file: sudo ./hostapd beacon.conf

In a separate shell, then start: sudo ./hostapd_cli And type in the two following commands: set vendor_elements dd1EFA0BBC0D00102038000058D6DF1D9055A308820DC10ACF072803D20F0100 update beacon

That made the beacon visible in the Android receiver application.

Clearly this is a very clumsy way of doing things and only servers to prove that it is possible to create a functional beacon and update the data that it is sending. An actual program of some kind would have to be written. There are C APIs for the set and update commands and when looking at the test code for hostapd, there is apparently also a Python interface: https://w1.fi/cgit/hostap/tree/tests/hwsim/test_ap_params.py#n81

I probably won’t have the bandwidth any time soon to look further into that, but it would certainly be an interesting exercise at some point.

friissoren commented 3 years ago

There is now a simple application example available for Linux for transmitting Wi-Fi Beacon and Bluetooth 4 and Bluetooth 5 drone ID signals: https://github.com/opendroneid/transmitter-linux