The project aims to develop a system to monitor the stress of apples during the grading process in industrial plants. The system is composed of three main components: the Smart Apple, the IoT Gateway, and the IoT Server. The Smart Apple is a low-cost IoT device placed inside a real apple that measures the accelerations and angular velocities of the fruit and sends the data to the IoT Gateway. The IoT Gateway is a Raspberry Pi that collects the data from the Smart Apples and sends it to the IoT Server. The IoT Server is a Raspberry Pi that stores the data in a InfluxDB database and provides a web interface to visualize the data with some impact analyses. The system is designed to be scalable and easy to deploy in industrial environments.
- Run directly the script located in data-analysis/acquisition_app.py
- It will start looking for Smart Apples (Arduino Nicla) with a known MAC address and start the streaming of the BLE packets
- We can save the data in a local csv (by setting the save2local flag), send it to a MQTT server (by setting the send2mqtt flag) or save it directly in the InfluxDB database (by setting the send2influxdb flag). You can also decide to activate all of them at the same time
- The data saved in InfluxDB can be retrieve using the master-raspberry/test/pull_influxdb.py script (be careful of the timestamp since there is no RTC module in the Raspberry Pi and therefore it would be the best to take the last few hours or minutes instead of specifying a range).
- Raspberry Pi Master
- Run the script located in master-raspberry/app/main.py
- It will start listening to the MQTT topic and when some data is received, it will push them to the InfluxDB database
- Raspberry Pi Slave
- Run the script located in slave-raspberry/app/main.py
- It will start looking for Smart Apples (Arduino Nicla) with a known MAC address and start the streaming of the BLE packets
- After receiving some packets, it will write them on the MQTT topic
- The data saved in InfluxDB can be retrieve using the master-raspberry/test/pull_influxdb.py script (be careful of the timestamp since there is no RTC module in the Raspberry Pi and therefore it would be the best to take the last few hours or minutes instead of specifying a range)
- Enable only 2.4 GHz with a 20MHz bandwidth (disable automatic switching from 20MHz to 40MHz)
- Fix the wifi channel and disable the automatic switching
-
Install Raspberry Pi Imager and open it
-
Press CTRL+Shift+X and modify the preferences enabling the WI-FI options
-
If using the modem provided by the lab the credentials are:
ssid: UNITN-SHIELD4US-WIFI password:
-
Enable SSH options and give a username and password, such as:
user: pi hostname: raspPi01 password: raspberry
-
Select RASPBERRY PI OS (64-BIT)
-
Press WRITE to flash the micro-SD
-
If you want to add new wifi credentials, you can create a wpa_supplicant.conf file and place it in the root of the sd, with this content:
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 network={ ssid="UNITN-SHIELD4US-WIFI" psk="" id_str="portable_router" } network={ ssid="PROVA-SSID" psk="PASSWORD" id_str="prova_access_point" }
-
I have found that the bluez version 5.66 works better than others, so let’s update it (my current raspberry kernel is 6.1.21-v8+, Troubleshooting — bleak 0.21.1 documentation)
# download new version wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.66.tar.xz # extract it and go inside the folder tar xvf bluez-5.66.tar.xz cd bluez-5.66 # install or update necessary dependencies sudo apt-get install libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev # configure, compile and install ./configure --prefix=/usr --mandir=/usr/share/man --sysconfdir=/etc --localstatedir=/var --enable-experimental make sudo make install # restart the bluetooth services sudo systemctl daemon-reload sudo systemctl restart bluetooth # check bluez version bluetoothd -v # check kernel version uname -r # remove tar and folder cd .. rm bluez-5.66 -r && rm bluez-5.66.tar.xz
Sometimes the Raspberry disconnects on its own from the network when it is in idle. To avoid this problem we can disable the wifi power management.
-
Disable it temporally
# check if it is on iwconfig wlan0 | grep "Power Management" # disable it sudo iwconfig wlan0 power off
-
To disable it every time on start-up set-up a systemctl daemon
# create a file sudo nano /etc/systemd/system/wifi-power-management.service # content of file [Unit] Description=Disable power management for wifi [Service] ExecStart=/sbin/iwconfig wlan0 power off Type=oneshot [Install] WantedBy=multi-user.target # save the file and enable the service sudo systemctl enable wifi-power-management.service # if you want to start it right away sudo systemctl start wifi-power-management.service
-
update and upgrade packages
sudo apt-get update sudo apt-get upgrade
-
clone github repo and install the dependencies
# clone repo # insert github username and password (public token) if requested git clone https://github.com/PeriniM/SmartApple-Thesis.git # run bash to install everything and select whether the device is a Gateway or Server cd ./SmartApple-Thesis sudo chmod +x setup.sh ./setup.sh
-
to discard local changes and fetch updated github repo
git fetch --all git reset --hard origin/main
-
the antenna must be compatible with bluetooth 5.0 to support BLE
-
disable built-in interface to use the external antenna
# check built-in interface name hciconfig # disable it to use new one sudo hciconfig hci0 down
The following commands will set-up influxdb and grafana to run on boot inside a docker container
-
install docker
# install docker curl -sSL https://get.docker.com | sh sudo usermod -aG docker pi # reboot sudo reboot # install docker compose # sudo apt-get install libffi-dev libssl-dev # sudo apt-get install -y python python-pip sudo pip install docker-compose
-
create the container
# go inside the project folder and create the containers docker-compose up -d --build # stop the running containers docker-compose down
-
if you get errors while installing, you need to set up the DNS properly
# Open the systemd-resolved configuration file sudo nano /etc/systemd/resolved.conf # uncomment the DNS line and add the google ip DNS=8.8.8.8 8.8.4.4 # restart the service sudo systemctl restart systemd-resolved # to verify the new DNS conf systemd-resolve --status
-
to run on boot
# create a systemd service file sudo nano /etc/systemd/system/docker-compose-app.service # content of the file [Unit] Description=Docker Compose Application Service Requires=docker.service After=docker.service [Service] WorkingDirectory=/home/pi/Desktop/SmartApple-Thesis ExecStart=/usr/local/bin/docker-compose up ExecStop=/usr/local/bin/docker-compose down TimeoutStartSec=0 Restart=always RemainAfterExit=yes [Install] WantedBy=multi-user.target # reload systemd to read the new service sudo systemctl daemon-reload # enable the service to run on boot sudo systemctl enable docker-compose-app.service # start, stop, status service command sudo systemctl start docker-compose-app.service sudo systemctl stop docker-compose-app.service sudo systemctl status docker-compose-app.service
-
if you make some changes to the docker-compose.yml
# before making changes stop the service sudo systemctl stop docker-compose-app.service # apply changes to docker-compose file and run docker-compose up -d # restart systemctl service sudo systemctl restart docker-compose-app.service # to see if everything is good docker-compose logs
-
to stop and remove all the containers
docker container stop $(docker container ls -aq) docker container prune -f
-
If not accessed to internet to set manually the time we can use:
sudo date -s '2024-01-26 13:04:00’
-
Connect through SSH using a terminal or Putty
ssh pi@raspberrypi.local password: raspberry
-
Update the dependencies, create a folder for autoboot applications and install LXSession
sudo apt-get update sudo mkdir -p /etc/xdg/autostart/ sudo apt-get install lxsession
-
Open the options interface using sudo raspi-config and set the following to enable the GUI remote control:
- System Options > Boot / Auto Login > Desktop Autologin
- Display Options > VNC Resolution > 1920x1080
- Interface Options > VNC
-
Reboot with sudo reboot
-
Download VNC Viewer, create an account and use the IP address of the raspberry to connect remotely to the GUI. To discover your device IP use the following command:
ifconfig --OR-- hostname -I
bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
# to start local server
node-red-pi --max-old-space-size=256
-
Install the OS
-
Check if the bluetooth interface is available and enable BLE features
# install bluetooth dependencies ([here](https://github.com/noble/noble)) sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev # check if hci is available hcitool dev # check if bluetooth service is active sudo systemctl status bluetooth # if not, active it with sudo systemctl start bluetooth # open bluetooth.service file and add the --experimental flag for BLE sudo nano /lib/systemd/system/bluetooth.service 'ExecStart=/usr/local/libexec/bluetooth/bluetoothd --experimental' # reload the configuration and restart the service sudo systemctl daemon-reload sudo systemctl restart bluetooth # set bluetoothd permission (found [here](https://flows.nodered.org/node/node-red-contrib-generic-ble)) sudo usermod -G bluetooth -a pi # start/stop BLE advertising without sudo (found [here](https://flows.nodered.org/node/node-red-contrib-ble-sense)) sudo setcap cap_net_raw+eip $(eval readlink -f `which node`) # reboot sudo reboot
-
Install Node-RED
-
Install node-red-contrib-ble-sense module and dashboard
-
To upgrade or downgrade bluez package (guide here):
# install latest bluez version (check [here](http://www.bluez.org/download/)) cd ~ wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.66.tar.xz tar xvf bluez-5.66.tar.xz && cd bluez-5.66 # install dependencies sudo apt-get update sudo apt-get install -y libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev # set configure method ./configure --enable-library # compile make # install package sudo make install # reboot sudo reboot # make the service start from boot sudo systemctl enable bluetooth # open bluetooth.service file and add the --experimental flag for BLE sudo nano /lib/systemd/system/bluetooth.service 'ExecStart=/usr/local/libexec/bluetooth/bluetoothd --experimental' # reload the configuration and restart the service sudo systemctl daemon-reload sudo systemctl restart bluetooth # reboot sudo reboot
-
To enable bluetooth:
# set bluetoothd permission (found [here](https://flows.nodered.org/node/node-red-contrib-generic-ble)) sudo usermod -G bluetooth -a pi sudo reboot # start/stop BLE advertising without sudo (found [here](https://flows.nodered.org/node/node-red-contrib-ble-sense)) sudo setcap cap_net_raw+eip $(eval readlink -f `which node`) # install bluetooth dependencies sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev # check if bluetooth service is active sudo systemctl status bluetooth # if not, active it with sudo systemctl start bluetooth
-
Install bleak (in a virtual environment or globally with sudo)
-
When I run the python script with the bleak test it works only one time
-
From the second time a get this error
(env) pi@raspberrypi4:~/Desktop/Smart-Apple $ python test-ble.py Traceback (most recent call last): File "/home/pi/Desktop/Smart-Apple/test-ble.py", line 42, in <module> asyncio.run(run(address)) File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run return loop.run_until_complete(main) File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete return future.result() File "/home/pi/Desktop/Smart-Apple/test-ble.py", line 36, in run async with BleakClient(address) as client: File "/home/pi/Desktop/Smart-Apple/env/lib/python3.9/site-packages/bleak/__init__.py", line 565, in __aenter__ await self.connect() File "/home/pi/Desktop/Smart-Apple/env/lib/python3.9/site-packages/bleak/__init__.py", line 605, in connect return await self._backend.connect(**kwargs) File "/home/pi/Desktop/Smart-Apple/env/lib/python3.9/site-packages/bleak/backends/bluezdbus/client.py", line 249, in connect assert_reply(reply) File "/home/pi/Desktop/Smart-Apple/env/lib/python3.9/site-packages/bleak/backends/bluezdbus/utils.py", line 22, in assert_reply raise BleakDBusError(reply.error_name, reply.body) bleak.exc.BleakDBusError: [org.bluez.Error.Failed] Software caused connection abort
-
if I create a new virtual environment and run the script it works the first time and then stops working the following times
-
I tried removing the /var/lib/bluetooth directory but without success
-
Reinstalling bleak didnt work
Installing bluepy with libglib fixes the dependencies
sudo apt-get install libglib2.0-dev sudo pip install bluepy