diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..eece76e --- /dev/null +++ b/404.html @@ -0,0 +1,407 @@ + + + +
+ + + + + + + + + + + + + +This short course on the Internet of Things is designed to give a first understanding of the main issues in developing IoT solutions. We do believe the most efficient way to learn this subject is experimenting, this is way the course encourage attendants to hands-on. No specific background is needed, even if a basic knowledge of electronics and computer science might help.
+GOAL: Quick intro to the Internet of Things.
+GOAL: Small experiment (a single sensor). Prove you can integrate sensors suitable for you monitoring purpose. Focus on effectiveness, namely doing the right things, i.e., the Maker approach.
+GOAL: Small experiment (a single sensor). Focus on efficiency, namely doing the things right, i.e., the Engineers approach. Use metrics to measure to what extent your solution satisfies the user requirements.
+GOAL: Scale-up in a realistic environment.
+I like vscode with the Remote-SSH extension to interact with the virtual machine for FreeRTOS development. However, during the class there might be many issues due to different version of the OS and vscode. To further simplify the process I use micro a modern and intuitive terminal-based text editor. Give it a try, it is very convenient. I also suggest to install the file manager plugin. The only annoying issue I'm currently facing with micro is that copy/past does not work smoothly over SSH, you have to use ctr + shift + V
+The list of material for each group
+ESP32-DevKit e.g. Available on Amazon
+A breadboard e.g. Available on Amazon
+Wires e.g. Available on Amazon
+Minimal actuator, namely a led and resistors - resistor 330 Ohm e.g. Available on Amazon
+Minimal analog sensor, namely a potentiometer 10 KOhm e.g. Available on Amazon
+Minimal digital sensor, namely a button - resistor 1 KOhm e.g. Available on Amazon
+A more interesting digital vibration sensor SW-420 e.g. Available on Amazon
+First edition of the course 19th (Session 1 and 2) and 21st (Session 3 and 4) of July 2023 in the University of Stellenbosch (South Africa) during an Erasmus+ staff mobility for teaching visit. About 40 participants selected among more the 100 candidates. Keep in touch on the discord server. A new version soon.
+ssh vitalett@saclay.iot-lab.info
+
+git clone https://github.com/FreeRTOS/FreeRTOS-LTS.git
+cd FreeRTOS-LTS/FreeRTOS
+git clone https://github.com/Lora-net/LoRaMac-node.git
+cd cd LoRaMac-node/
+
+nano src/boards/B-L072Z-LRWAN1/board.c
+
+// change the baudrate to 115200 to be compatible with iot-lab serial
+
+UartConfig( &Uart2, RX_TX, 115200, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL );
+
+nano src/peripherals/soft-se/se-identity.h
+
+// update credentials to connect to TTN
+#define STATIC_DEVICE_EUI 1
+#define LORAWAN_DEVICE_EUI LORAWAN_DEVICE_EUI_ON_TTN
+#define LORAWAN_JOIN_EUI LORAWAN_APP_EUI_ON_TTN
+#define STATIC_DEVICE_ADDRESS 1
+#define LORAWAN_DEVICE_ADDRESS DEVICE_ADDRESS_TTN
+
+.KeyID = NWK_KEY,
+.KeyValue = LORAWAN_APP_KEY_ON_TTN
+
+mkdir build
+cd build
+
+cmake -DCMAKE_BUILD_TYPE=Release -DTOOLCHAIN_PREFIX="/opt/gcc-arm-none-eabi-4_9-2015q1/" -DCMAKE_TOOLCHAIN_FILE="../cmake/toolchain-arm-none-eabi.cmake" -DAPPLICATION="LoRaMac" -DSUB_PROJECT="periodic-uplink-lpp" -DCLASSB_ENABLED="ON" -DACTIVE_REGION="LORAMAC_REGION_EU868" -DREGION_EU868="ON" -DREGION_US915="OFF" -DREGION_CN779="OFF" -DREGION_EU433="OFF" -DREGION_AU915="OFF" -DREGION_AS923="OFF" -DREGION_CN470="OFF" -DREGION_KR920="OFF" -DREGION_IN865="OFF" -DREGION_RU864="OFF" -DBOARD="B-L072Z-LRWAN1" -DSECURE_ELEMENT="SOFT_SE" -DSECURE_ELEMENT_PRE_PROVISIONED="OFF" -DUSE_RADIO_DEBUG="ON" ..
+
+make
+
+cd src/apps/LoRaMac/
+
+iotlab-experiment submit -n rtos_ttn -d 60 -l 1,archi=st-lrwan1:sx1276+site=saclay
+{
+ "id": 394774
+}
+
+iotlab-experiment get -i 394774 -s
+
+iotlab-experiment get -i 394774 -r
+
+iotlab-node --flash LoRaMac-periodic-uplink-lpp -l saclay,st-lrwan1,10
+
+nc st-lrwan1-10 20000
+
+
+
+
+
+
+
+ This short course on the Internet of Things is designed to give a first understanding of the main issues in developing IoT solutions. We do believe the most efficient way to learn this subject is experimenting, this is way the course encourage attendants to hands-on. No specific background is needed, even if a basic knowledge of electronics and computer science might help.
"},{"location":"#session-1-3-hours","title":"SESSION 1 (3 hours)","text":"GOAL: Quick intro to the Internet of Things.
GOAL: Small experiment (a single sensor). Prove you can integrate sensors suitable for you monitoring purpose. Focus on effectiveness, namely doing the right things, i.e., the Maker approach.
GOAL: Small experiment (a single sensor). Focus on efficiency, namely doing the things right, i.e., the Engineers approach. Use metrics to measure to what extent your solution satisfies the user requirements.
GOAL: Scale-up in a realistic environment.
I like vscode with the Remote-SSH extension to interact with the virtual machine for FreeRTOS development. However, during the class there might be many issues due to different version of the OS and vscode. To further simplify the process I use micro a modern and intuitive terminal-based text editor. Give it a try, it is very convenient. I also suggest to install the file manager plugin. The only annoying issue I'm currently facing with micro is that copy/past does not work smoothly over SSH, you have to use ctr + shift + V
"},{"location":"#material","title":"Material","text":"The list of material for each group
ESP32-DevKit e.g. Available on Amazon
A breadboard e.g. Available on Amazon
Wires e.g. Available on Amazon
Minimal actuator, namely a led and resistors - resistor 330 Ohm e.g. Available on Amazon
Minimal analog sensor, namely a potentiometer 10 KOhm e.g. Available on Amazon
Minimal digital sensor, namely a button - resistor 1 KOhm e.g. Available on Amazon
A more interesting digital vibration sensor SW-420 e.g. Available on Amazon
First edition of the course 19th (Session 1 and 2) and 21st (Session 3 and 4) of July 2023 in the University of Stellenbosch (South Africa) during an Erasmus+ staff mobility for teaching visit. About 40 participants selected among more the 100 candidates. Keep in touch on the discord server. A new version soon.
"},{"location":"iot-lab/","title":"IOT-LAB","text":""},{"location":"iot-lab/#run-a-lorawan-experiment","title":"Run a Lorawan experiment","text":"ssh vitalett@saclay.iot-lab.info \n
git clone https://github.com/FreeRTOS/FreeRTOS-LTS.git\ncd FreeRTOS-LTS/FreeRTOS\ngit clone https://github.com/Lora-net/LoRaMac-node.git\ncd cd LoRaMac-node/\n
nano src/boards/B-L072Z-LRWAN1/board.c\n\n// change the baudrate to 115200 to be compatible with iot-lab serial \n\nUartConfig( &Uart2, RX_TX, 115200, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL );\n
nano src/peripherals/soft-se/se-identity.h\n\n// update credentials to connect to TTN\n#define STATIC_DEVICE_EUI 1\n#define LORAWAN_DEVICE_EUI LORAWAN_DEVICE_EUI_ON_TTN\n#define LORAWAN_JOIN_EUI LORAWAN_APP_EUI_ON_TTN\n#define STATIC_DEVICE_ADDRESS 1\n#define LORAWAN_DEVICE_ADDRESS DEVICE_ADDRESS_TTN\n\n.KeyID = NWK_KEY, \n.KeyValue = LORAWAN_APP_KEY_ON_TTN\n
mkdir build\ncd build\n\ncmake -DCMAKE_BUILD_TYPE=Release -DTOOLCHAIN_PREFIX=\"/opt/gcc-arm-none-eabi-4_9-2015q1/\" -DCMAKE_TOOLCHAIN_FILE=\"../cmake/toolchain-arm-none-eabi.cmake\" -DAPPLICATION=\"LoRaMac\" -DSUB_PROJECT=\"periodic-uplink-lpp\" -DCLASSB_ENABLED=\"ON\" -DACTIVE_REGION=\"LORAMAC_REGION_EU868\" -DREGION_EU868=\"ON\" -DREGION_US915=\"OFF\" -DREGION_CN779=\"OFF\" -DREGION_EU433=\"OFF\" -DREGION_AU915=\"OFF\" -DREGION_AS923=\"OFF\" -DREGION_CN470=\"OFF\" -DREGION_KR920=\"OFF\" -DREGION_IN865=\"OFF\" -DREGION_RU864=\"OFF\" -DBOARD=\"B-L072Z-LRWAN1\" -DSECURE_ELEMENT=\"SOFT_SE\" -DSECURE_ELEMENT_PRE_PROVISIONED=\"OFF\" -DUSE_RADIO_DEBUG=\"ON\" ..\n\nmake\n
cd src/apps/LoRaMac/\n\niotlab-experiment submit -n rtos_ttn -d 60 -l 1,archi=st-lrwan1:sx1276+site=saclay\n{\n \"id\": 394774\n}\n\niotlab-experiment get -i 394774 -s\n\niotlab-experiment get -i 394774 -r\n\niotlab-node --flash LoRaMac-periodic-uplink-lpp -l saclay,st-lrwan1,10\n\nnc st-lrwan1-10 20000\n
"},{"location":"session1/","title":"SESSION 1","text":"GOAL: Quick intro to the Internet of Things.
"},{"location":"session1/#takeaway-one","title":"Takeaway ONE","text":"\"When you can measure ... you know something\". Lord Kelvin docet.
GOAL: Small experiment (a single sensor). Prove you can integrate sensors suitable for you monitoring purpose. Focus on effectiveness, namely doing the right things, i.e., the Maker approach.
"},{"location":"session2/#the-reference-hardware-esp32-devkit","title":"The reference hardware: ESP32-DevKit","text":""},{"location":"session2/#lets-start-by-simulating-it","title":"Let's start by simulating it","text":"Wokwi is an online Electronics simulator. You can use it to simulate Arduino, ESP32, STM32, and many other popular boards, parts and sensors.
mosquitto_pub -h test.mosquitto.org -t \"topicName/led\" -m \"on\"\nmosquitto_pub -h test.mosquitto.org -t \"topicName/led\" -m \"off\"\n
mosquitto_sub -h test.mosquitto.org -t \"wokwi/temperature\"\n
Another possible broker is mqtt://mqtt.eclipseprojects.io
https://thingsboard.io/docs/getting-started-guides/helloworld/?connectdevice=mqtt-linux
mosquitto_pub -d -q 1 -h \"$THINGSBOARD_HOST_NAME\" -p \"1883\" -t \"v1/devices/me/telemetry\" -u \"$ACCESS_TOKEN\" -m {\"temperature\":25}\n
NOTE: for the sake of convenience, we will use WiFi connectivity, however it should be now clear WiFi is usually not appropriate for IoT applications due to the excessive energy demand.
"},{"location":"session2/#it-is-time-to-work-with-a-real-device","title":"It is time to Work with a real device","text":"This sketch could help
// Watch video here: https://www.youtube.com/watch?v=235BLk7vk00\n\n/* Vibration sensor connected to Arduino pins as follows:\n\n ESP32 Arduino Vibration Sensor\n https://wolles-elektronikkiste.de/esp32-mit-arduino-code-programmieren\n D18 --> GPIO18 --> G18 DOut\n GND GND\n +5V --> 3.3V VCC \n*/\n\nint EP = 18;\n\nvoid setup(){\n pinMode(EP, INPUT); //set EP input for measurment\n Serial.begin(9600); //init serial 9600\n}\nvoid loop(){\n long measurement =TP_init();\n delay(50);\n Serial.println(measurement);\n}\n\nlong TP_init(){\n delay(10);\n long measurement=pulseIn (EP, HIGH); //wait for the pin to get HIGH and returns measurement\n return measurement;\n}\n\n
Through pulseIn() we can measure the duration of a vibration event exceeding the threshold, not the frequency of the vibrations themselves. Indeed, the Arduino pulseIn() function waits for a change in the binary input (Low to High in this instance) and returns the duration that the detected pulse was active (time for it to go back High to Low after going High).
QUESTION: Can we use this function to help in anomaly detection? see here for inspiration!
"},{"location":"session3/","title":"SESSION 3","text":"GOAL: Small experiment (a single sensor). Focus on efficiency, namely doing the things right, i.e., the Engineers approach. Use metrics to measure to what extent your solution satisfies the user requirements.
Well, to develop an IoT application as an engineer, we do need a Real-Time Operating System (RTOS). What is An RTOS?.
Embedded systems often have real time requirements. A real time requirements is one that specifies that the embedded system must respond to a certain event within a strictly defined time (the deadline). A guarantee to meet real time requirements can only be made if the behaviour of the operating system's scheduler can be predicted (and is therefore deterministic). FreeRTOS, achieve determinism by allowing the user to assign a priority to each thread of execution. The scheduler then uses the priority to know which thread of execution to run next. In FreeRTOS, a thread of execution is called a task.
Here there is a nice explanation of the main features provided by FreeRTOS, namely
FreeRTOS FAQ - What is This All About?
Finally a nice example of the design of a real-time application
A book on FreeRTOS.
"},{"location":"session3/#development-environment","title":"Development environment","text":"To develop our solution on our ESP32, we need to setup the environment as described here. A very convenient way is to use docker as explained here.
To further simplify the development process, a multi-platform Virtualbox image is available here. Next we will focus on this method. Credentials to work with the virtual machine are root/root and devel/devel and we will connect in ssh as explained below.
The reference folder for the code and the examples is https://github.com/espressif/esp-idf.git which is already available on the virtual machine on
ssh devel@localhost -p 2222
... the password is develget_idf
... we set up the development environmentcd ~/esp
cp -r ./esp-idf/examples/get-started/hello_world/ ./workshop/
... make a copy of a dir in the example in the workshop dir cd ./workshop/hello_world/
idf.py build
... i t takes some timeidf.py flash
... be sure the ESP32 is connected to \\dev\\ttyUSB0 and check it is visible in the virtual machineidf.py monitor
... to exit from the monitor ctrl+T ctrl+XNOTE in some cases you can configure specific parameters running idf.py menuconfig
In the virtual machine you have first to export LC_ALL=C
# Create a directory, so Git doesn't get messy, and enter it\nmkdir code_from_git && cd code_from_git\n\n# Start a Git repository\ngit init\n\n# Track repository, do not enter subdirectory\ngit remote add -f origin https://github.com/andreavitaletti/IoT_short_course\n\n# Enable the tree check feature\ngit config core.sparseCheckout true\n\n# Create a file in the path: .git/info/sparse-checkout\n# That is inside the hidden .git directory that was created\n# by running the command: git init\n# And inside it enter the name of the sub directory you only want to clone\necho 'src/freertos' >> .git/info/sparse-checkout\n\n## Download with pull, not clone\ngit pull origin main\n
"},{"location":"session3/#a-quick-introduction-to-tasks","title":"A quick introduction to tasks","text":"Based on ESP32 ESP-IDF FreeRTOS Tutorial: Learn to Create Tasks. The code is available on our github repo
"},{"location":"session3/#the-examples-of-session-2-on-freertos","title":"The examples of SESSION 2 on FreeRTOS","text":"In this section we will implement the reference examples developed in day2 into FreeRTOS. The idea is to take inspiration from the examples available at https://github.com/espressif/esp-idf/tree/master/examples and modify them to get the same behavior of the ones developed in DAY2
Nice tutorials on the same topics are also available here
"},{"location":"session3/#data-streaming-in-industrial-iot","title":"Data Streaming in Industrial IoT","text":"GOAL: Scale-up in a realistic environment.
IoT-LAB provides a very large scale infrastructure suitable for testing small wireless sensor devices and heterogeneous communicating objects.
Even if the ESP32 is not currently among the supported hardware, IoT-LAB supports FreeRTOS.
ssh vitalett@grenoble.iot-lab.info\n
Reference examples are available here. You have to download from github esp-nn and esp32-camera and place them into the relative folders under components.
Then go to examples/hello_worlds and as usual idf.py build, idf.py flash and finally idf.py monitor.
A nice explanation on how the model is generated can be found on the book TinyML by Pete Warden, Daniel Situnayake. The corresponding jupyter notebook is available here
Some other useful resources are listed below:
A very nice, rich an exhaustive source of documentation for Kalman filters is available here
The main idea is that both our prior knowledge and the measurements of our sensors are to some extent inaccurate. To model such inaccuracy we use a Gaussian with mean $$\\mu$$ and variance $$\\rho$$
At each iteration we have our prior knowledge (in blue) and a new measurement (in orange) and we account for both source of information computing an average (in green)
The final mean gets shifted which is in between the two old means, the mean of the prior, and the mean of the measurement. It\u2019s slightly further on the measurement side because the measurement was more certain as to where the vehicle is than prior. The more certain we are, the more we pull the mean on the direction of the certain answer. source
Iteration after iteration the variance decreases (the spread of the blue gaussian), providing a better estimation (in green) despite the noisy measurements (in red) source
A reference library is available here
"},{"location":"supplement3/","title":"Interact with a Mobile Phone via BLE","text":"We aim at fast prototyping and Thunkable is an excellent tool
The arduino code, adapted from https://www.instructables.com/ESP32-BLE-Android-App-Arduino-IDE-AWESOME/ is the following
/*\n Video: https://www.youtube.com/watch?v=oCMOYS71NIU\n Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp\n Ported to Arduino ESP32 by Evandro Copercini\n\n Create a BLE server that, once we receive a connection, will send periodic notifications.\n The service advertises itself as: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E\n Has a characteristic of: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E - used for receiving data with \"WRITE\" \n Has a characteristic of: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E - used to send data with \"NOTIFY\"\n\n The design of creating the BLE server is:\n 1. Create a BLE Server\n 2. Create a BLE Service\n 3. Create a BLE Characteristic on the Service\n 4. Create a BLE Descriptor on the characteristic\n 5. Start the service.\n 6. Start advertising.\n\n In this example rxValue is the data received (only accessible inside that function).\n And txValue is the data to be sent, in this example just a byte incremented every second. \n*/\n#include <BLEDevice.h>\n#include <BLEServer.h>\n#include <BLEUtils.h>\n#include <BLE2902.h>\n\n// 78:21:84:9f:24:de\n\nBLECharacteristic *pCharacteristic;\nbool deviceConnected = false;\nfloat txValue = 0;\nconst int readPin = 32; // Use GPIO number. See ESP32 board pinouts\n//const int LED = 9; // Could be different depending on the dev board. I used the DOIT ESP32 dev board.\n\n//std::string rxValue; // Could also make this a global var to access it in loop()\n\n// See the following for generating UUIDs:\n// https://www.uuidgenerator.net/\n\n#define SERVICE_UUID \"6E400001-B5A3-F393-E0A9-E50E24DCCA9E\" // UART service UUID\n#define CHARACTERISTIC_UUID_RX \"6E400002-B5A3-F393-E0A9-E50E24DCCA9E\" // Qui ricevi da EPS32\n#define CHARACTERISTIC_UUID_TX \"6E400003-B5A3-F393-E0A9-E50E24DCCA9E\" // Qui invii\n\nclass MyServerCallbacks: public BLEServerCallbacks {\n void onConnect(BLEServer* pServer) {\n deviceConnected = true;\n };\n\n void onDisconnect(BLEServer* pServer) {\n deviceConnected = false;\n }\n};\n\n\n\nclass MyCallbacks: public BLECharacteristicCallbacks {\n void onWrite(BLECharacteristic *pCharacteristic) {\n std::string rxValue = pCharacteristic->getValue();\n\n char letto[] = \" \";\n\n if (rxValue.length() > 0) {\n Serial.println(\"*********\");\n Serial.print(\"Received Value: \");\n\n for (int i = 0; i < rxValue.length(); i++) {\n Serial.print(rxValue[i]);\n letto[i]=rxValue[i];\n }\n\n Serial.println();\n\n String a = String(letto);\n\n Serial.print(a.toFloat());\n\n // Do stuff based on the command received from the app\n if (rxValue.find(\"A\") != -1) { \n Serial.print(\"Turning ON!\");\n digitalWrite(LED, HIGH);\n }\n else if (rxValue.find(\"B\") != -1) {\n Serial.print(\"Turning OFF!\");\n digitalWrite(LED, LOW);\n }\n\n Serial.println();\n Serial.println(\"*********\");\n }\n }\n};\n\nvoid setup() {\n Serial.begin(115200);\n\n pinMode(LED, OUTPUT);\n\n // Create the BLE Device\n BLEDevice::init(\"ESP32 UART Test\"); // Give it a name\n\n Serial.print(\"local BLE Address is: \");\n Serial.println(BLEDevice::getAddress().toString().c_str());\n\n // Create the BLE Server\n BLEServer *pServer = BLEDevice::createServer();\n pServer->setCallbacks(new MyServerCallbacks());\n\n // Create the BLE Service\n BLEService *pService = pServer->createService(SERVICE_UUID);\n\n\n // BleCharacteristic deviceHealthCharacteristic(\"deviceHealth\", BleCharacteristicProperty::READ, deviceHealthUuid, serviceUuid);\n // see https://community.thunkable.com/t/ble-hrm-reading-bpm/2441754/6\n\n\n // Create a BLE Characteristic\n pCharacteristic = pService->createCharacteristic(\n CHARACTERISTIC_UUID_TX,\n //BLECharacteristic::PROPERTY_NOTIFY\n BLECharacteristic::PROPERTY_READ\n );\n\n pCharacteristic->addDescriptor(new BLE2902());\n\n BLECharacteristic *pCharacteristic = pService->createCharacteristic(\n CHARACTERISTIC_UUID_RX,\n BLECharacteristic::PROPERTY_WRITE\n );\n\n pCharacteristic->setCallbacks(new MyCallbacks());\n\n // Start the service\n pService->start();\n\n // Start advertising\n pServer->getAdvertising()->start();\n Serial.println(\"Waiting a client connection to notify...\");\n}\n\nvoid loop() {\n\n if (deviceConnected) {\n // Fabricate some arbitrary junk for now...\n txValue = analogRead(readPin) / 3.456; // This could be an actual sensor reading!\n\n // Let's convert the value to a char array:\n char txString[8]; // make sure this is big enuffz\n dtostrf(txValue, 1, 2, txString); // float_val, min_width, digits_after_decimal, char_buffer\n\n// pCharacteristic->setValue(&txValue, 1); // To send the integer value\n pCharacteristic->setValue(\"Hello!\"); // Sending a test message\n //pCharacteristic->setValue(txString);\n\n pCharacteristic->notify(); // Send the value to the app!\n Serial.print(\"*** Sent Value: \");\n Serial.print(txString);\n Serial.println(\" ***\");\n\n // You can add the rxValue checks down here instead\n // if you set \"rxValue\" as a global var at the top!\n // Note you will have to delete \"std::string\" declaration\n // of \"rxValue\" in the callback function.\n// if (rxValue.find(\"A\") != -1) { \n// Serial.println(\"Turning ON!\");\n// digitalWrite(LED, HIGH);\n// }\n// else if (rxValue.find(\"B\") != -1) {\n// Serial.println(\"Turning OFF!\");\n// digitalWrite(LED, LOW);\n// }\n }\n\n delay(1000);\n}\n\n
// Adapted from https://github.com/SIMS-IOT-Devices/FreeRTOS-ESP-IDF-BLE-Server\n\n#include <stdio.h>\n#include \"freertos/FreeRTOS.h\"\n#include \"freertos/task.h\"\n#include \"freertos/event_groups.h\"\n#include \"esp_event.h\"\n#include \"nvs_flash.h\"\n#include \"esp_log.h\"\n#include \"esp_nimble_hci.h\"\n#include \"nimble/nimble_port.h\"\n#include \"nimble/nimble_port_freertos.h\"\n#include \"host/ble_hs.h\"\n#include \"services/gap/ble_svc_gap.h\"\n#include \"services/gatt/ble_svc_gatt.h\"\n#include \"sdkconfig.h\"\n\nchar *TAG = \"BLE-Server\";\nuint8_t ble_addr_type;\nvoid ble_app_advertise(void);\n\n//@_____________________Define UUIDs______________________________________\n//!! b2bbc642-46da-11ed-b878-0242ac120002\n//static const ble_uuid128_t gatt_svr_svc_uuid =\n// BLE_UUID128_INIT(0x02, 0x00, 0x12, 0xac, 0x42, 0x02, 0x78, 0xb8, 0xed, 0x11, 0xda, 0x46, 0x42, 0xc6, 0xbb, 0xb2);\n\nstatic const ble_uuid128_t gatt_svr_svc_uuid =\n BLE_UUID128_INIT(0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x01, 0x00, 0x40, 0x6e);\n\n\n//!! c9af9c76-46de-11ed-b878-0242ac120002\n//static const ble_uuid128_t gatt_svr_chr_uuid =\n// BLE_UUID128_INIT(0x02, 0x00, 0x12, 0xac, 0x42, 0x02, 0x78, 0xb8, 0xed, 0x11, 0xde, 0x46, 0x76, 0x9c, 0xaf, 0xc9);\n\n// 6E400002-B5A3-F393-E0A9-E50E24DCCA9E \n\nstatic const ble_uuid128_t gatt_svr_chr_read_uuid =\n BLE_UUID128_INIT(0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x02, 0x00, 0x40, 0x6e);\nstatic const ble_uuid128_t gatt_svr_chr_write_uuid =\n BLE_UUID128_INIT(0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x03, 0x00, 0x40, 0x6e);\n\n\n// Write data to ESP32 defined as server\nstatic int device_write(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)\n{\n printf(\"Data from the client: %.*s\\n\", ctxt->om->om_len, ctxt->om->om_data);\n return 0;\n}\n\n// Read data from ESP32 defined as server\nstatic int device_read(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)\n{\n os_mbuf_append(ctxt->om, \"Data from the server\", strlen(\"Data from the server\"));\n return 0;\n}\n\nstatic const struct ble_gatt_svc_def gatt_svcs[] = {\n {.type = BLE_GATT_SVC_TYPE_PRIMARY,\n .uuid = &gatt_svr_svc_uuid.u, // Define UUID for device type\n .characteristics = (struct ble_gatt_chr_def[]){\n {.uuid = &gatt_svr_chr_write_uuid.u, // Define UUID for reading\n .flags = BLE_GATT_CHR_F_READ,\n .access_cb = device_read},\n {.uuid = &gatt_svr_chr_read_uuid.u, // Define UUID for writing\n .flags = BLE_GATT_CHR_F_WRITE,\n .access_cb = device_write},\n {0}}},\n {0}};\n\n\n\n// BLE event handling\nstatic int ble_gap_event(struct ble_gap_event *event, void *arg)\n{\n switch (event->type)\n {\n // Advertise if connected\n case BLE_GAP_EVENT_CONNECT:\n ESP_LOGI(\"GAP\", \"BLE GAP EVENT CONNECT %s\", event->connect.status == 0 ? \"OK!\" : \"FAILED!\");\n if (event->connect.status != 0)\n {\n ble_app_advertise();\n }\n break;\n // Advertise again after completion of the event\n case BLE_GAP_EVENT_ADV_COMPLETE:\n ESP_LOGI(\"GAP\", \"BLE GAP EVENT\");\n ble_app_advertise();\n break;\n default:\n break;\n }\n return 0;\n}\n\n// Define the BLE connection\nvoid ble_app_advertise(void)\n{\n // GAP - device name definition\n struct ble_hs_adv_fields fields;\n const char *device_name;\n memset(&fields, 0, sizeof(fields));\n device_name = ble_svc_gap_device_name(); // Read the BLE device name\n fields.name = (uint8_t *)device_name;\n fields.name_len = strlen(device_name);\n fields.name_is_complete = 1;\n ble_gap_adv_set_fields(&fields);\n\n // GAP - device connectivity definition\n struct ble_gap_adv_params adv_params;\n memset(&adv_params, 0, sizeof(adv_params));\n adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; // connectable or non-connectable\n adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; // discoverable or non-discoverable\n ble_gap_adv_start(ble_addr_type, NULL, BLE_HS_FOREVER, &adv_params, ble_gap_event, NULL);\n}\n\n// The application\nvoid ble_app_on_sync(void)\n{\n ble_hs_id_infer_auto(0, &ble_addr_type); // Determines the best address type automatically\n ble_app_advertise(); // Define the BLE connection\n}\n\n// The infinite task\nvoid host_task(void *param)\n{\n nimble_port_run(); // This function will return only when nimble_port_stop() is executed\n}\n\nvoid app_main()\n{\n nvs_flash_init(); // 1 - Initialize NVS flash using\n //esp_nimble_hci_and_controller_init(); // 2 - Initialize ESP controller\n nimble_port_init(); // 3 - Initialize the host stack\n ble_svc_gap_device_name_set(\"BLE-Server\"); // 4 - Initialize NimBLE configuration - server name\n ble_svc_gap_init(); // 4 - Initialize NimBLE configuration - gap service\n ble_svc_gatt_init(); // 4 - Initialize NimBLE configuration - gatt service\n ble_gatts_count_cfg(gatt_svcs); // 4 - Initialize NimBLE configuration - config gatt services\n ble_gatts_add_svcs(gatt_svcs); // 4 - Initialize NimBLE configuration - queues gatt services.\n ble_hs_cfg.sync_cb = ble_app_on_sync; // 5 - Initialize application\n nimble_port_freertos_init(host_task); // 6 - Run the thread\n}\n
"}]}
\ No newline at end of file
diff --git a/session1/index.html b/session1/index.html
new file mode 100644
index 0000000..219e7a8
--- /dev/null
+++ b/session1/index.html
@@ -0,0 +1,518 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GOAL: Quick intro to the Internet of Things.
+++"When you can measure ... you know something". Lord Kelvin docet.
+
GOAL: Small experiment (a single sensor). Prove you can integrate sensors suitable for you monitoring purpose. Focus on effectiveness, namely doing the right things, i.e., the Maker approach.
+Wokwi is an online Electronics simulator. You can use it to simulate Arduino, ESP32, STM32, and many other popular boards, parts and sensors.
+mosquitto_pub -h test.mosquitto.org -t "topicName/led" -m "on"
+mosquitto_pub -h test.mosquitto.org -t "topicName/led" -m "off"
+
+mosquitto_sub -h test.mosquitto.org -t "wokwi/temperature"
+
+Another possible broker is mqtt://mqtt.eclipseprojects.io
+
+
https://thingsboard.io/docs/getting-started-guides/helloworld/?connectdevice=mqtt-linux
+mosquitto_pub -d -q 1 -h "$THINGSBOARD_HOST_NAME" -p "1883" -t "v1/devices/me/telemetry" -u "$ACCESS_TOKEN" -m {"temperature":25}
+
+NOTE: for the sake of convenience, we will use WiFi connectivity, however it should be now clear WiFi is usually not appropriate for IoT applications due to the excessive energy demand.
+This sketch could help
+// Watch video here: https://www.youtube.com/watch?v=235BLk7vk00
+
+/* Vibration sensor connected to Arduino pins as follows:
+
+ ESP32 Arduino Vibration Sensor
+ https://wolles-elektronikkiste.de/esp32-mit-arduino-code-programmieren
+ D18 --> GPIO18 --> G18 DOut
+ GND GND
+ +5V --> 3.3V VCC
+*/
+
+int EP = 18;
+
+void setup(){
+ pinMode(EP, INPUT); //set EP input for measurment
+ Serial.begin(9600); //init serial 9600
+}
+void loop(){
+ long measurement =TP_init();
+ delay(50);
+ Serial.println(measurement);
+}
+
+long TP_init(){
+ delay(10);
+ long measurement=pulseIn (EP, HIGH); //wait for the pin to get HIGH and returns measurement
+ return measurement;
+}
+
+
+Through pulseIn() we can measure the duration of a vibration event exceeding the threshold, not the frequency of the vibrations themselves. Indeed, the Arduino pulseIn() function waits for a change in the binary input (Low to High in this instance) and returns the duration that the detected pulse was active (time for it to go back High to Low after going High).
+QUESTION: Can we use this function to help in anomaly detection? see here for inspiration!
+GOAL: Small experiment (a single sensor). Focus on efficiency, namely doing the things right, i.e., the Engineers approach. Use metrics to measure to what extent your solution satisfies the user requirements.
+ + + + +Well, to develop an IoT application as an engineer, we do need a Real-Time Operating System (RTOS). What is An RTOS?.
+++Embedded systems often have real time requirements. A real time requirements is one that specifies that the embedded system must respond to a certain event within a strictly defined time (the deadline). A guarantee to meet real time requirements can only be made if the behaviour of the operating system's scheduler can be predicted (and is therefore deterministic). FreeRTOS, achieve determinism by allowing the user to assign a priority to each thread of execution. The scheduler then uses the priority to know which thread of execution to run next. In FreeRTOS, a thread of execution is called a task.
+
Here there is a nice explanation of the main features provided by FreeRTOS, namely
+FreeRTOS FAQ - What is This All About?
+Finally a nice example of the design of a real-time application
+A book on FreeRTOS.
+To develop our solution on our ESP32, we need to setup the environment as described here. A very convenient way is to use docker as explained here.
+To further simplify the development process, a multi-platform Virtualbox image is available here. Next we will focus on this method. Credentials to work with the virtual machine are root/root and devel/devel and we will connect in ssh as explained below.
+The reference folder for the code and the examples is https://github.com/espressif/esp-idf.git which is already available on the virtual machine on
+ssh devel@localhost -p 2222
... the password is develget_idf
... we set up the development environmentcd ~/esp
cp -r ./esp-idf/examples/get-started/hello_world/ ./workshop/
... make a copy of a dir in the example in the workshop dir cd ./workshop/hello_world/
idf.py build
... i t takes some timeidf.py flash
... be sure the ESP32 is connected to \dev\ttyUSB0 and check it is visible in the virtual machineidf.py monitor
... to exit from the monitor ctrl+T ctrl+XNOTE in some cases you can configure specific parameters running idf.py menuconfig
+In the virtual machine you have first to
+export LC_ALL=C
# Create a directory, so Git doesn't get messy, and enter it
+mkdir code_from_git && cd code_from_git
+
+# Start a Git repository
+git init
+
+# Track repository, do not enter subdirectory
+git remote add -f origin https://github.com/andreavitaletti/IoT_short_course
+
+# Enable the tree check feature
+git config core.sparseCheckout true
+
+# Create a file in the path: .git/info/sparse-checkout
+# That is inside the hidden .git directory that was created
+# by running the command: git init
+# And inside it enter the name of the sub directory you only want to clone
+echo 'src/freertos' >> .git/info/sparse-checkout
+
+## Download with pull, not clone
+git pull origin main
+
+Based on ESP32 ESP-IDF FreeRTOS Tutorial: Learn to Create Tasks. The code is available on our github repo
+In this section we will implement the reference examples developed in day2 into FreeRTOS. The idea is to take inspiration from the examples available at https://github.com/espressif/esp-idf/tree/master/examples and modify them to get the same behavior of the ones developed in DAY2
+Nice tutorials on the same topics are also available here
+GOAL: Scale-up in a realistic environment.
+ + + + +IoT-LAB provides a very large scale infrastructure suitable for testing small wireless sensor devices and heterogeneous communicating objects.
+Even if the ESP32 is not currently among the supported hardware, IoT-LAB supports FreeRTOS.
+ssh vitalett@grenoble.iot-lab.info
+
+Reference examples are available here. You have to download from github esp-nn and esp32-camera and place them into the relative folders under components.
+Then go to examples/hello_worlds and as usual idf.py build, idf.py flash and finally idf.py monitor.
+A nice explanation on how the model is generated can be found on the book TinyML by Pete Warden, Daniel Situnayake. The corresponding jupyter notebook is available here
+Some other useful resources are listed below:
+ + + + + + + +A very nice, rich an exhaustive source of documentation for Kalman filters is available here
+The main idea is that both our prior knowledge and the measurements of our sensors are to some extent inaccurate. To model such inaccuracy we use a Gaussian with mean $$\mu$$ and variance $$\rho$$
+At each iteration we have our prior knowledge (in blue) and a new measurement (in orange) and we account for both source of information computing an average (in green)
+++The final mean gets shifted which is in between the two old means, the mean of the prior, and the mean of the measurement. It’s slightly further on the measurement side because the measurement was more certain as to where the vehicle is than prior. The more certain we are, the more we pull the mean on the direction of the certain answer. source
+
Iteration after iteration the variance decreases (the spread of the blue gaussian), providing a better estimation (in green) despite the noisy measurements (in red) source
+A reference library is available here
+ + + + + + +We aim at fast prototyping and Thunkable is an excellent tool
+The arduino code, adapted from https://www.instructables.com/ESP32-BLE-Android-App-Arduino-IDE-AWESOME/ is the following
+/*
+ Video: https://www.youtube.com/watch?v=oCMOYS71NIU
+ Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
+ Ported to Arduino ESP32 by Evandro Copercini
+
+ Create a BLE server that, once we receive a connection, will send periodic notifications.
+ The service advertises itself as: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
+ Has a characteristic of: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E - used for receiving data with "WRITE"
+ Has a characteristic of: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E - used to send data with "NOTIFY"
+
+ The design of creating the BLE server is:
+ 1. Create a BLE Server
+ 2. Create a BLE Service
+ 3. Create a BLE Characteristic on the Service
+ 4. Create a BLE Descriptor on the characteristic
+ 5. Start the service.
+ 6. Start advertising.
+
+ In this example rxValue is the data received (only accessible inside that function).
+ And txValue is the data to be sent, in this example just a byte incremented every second.
+*/
+#include <BLEDevice.h>
+#include <BLEServer.h>
+#include <BLEUtils.h>
+#include <BLE2902.h>
+
+// 78:21:84:9f:24:de
+
+BLECharacteristic *pCharacteristic;
+bool deviceConnected = false;
+float txValue = 0;
+const int readPin = 32; // Use GPIO number. See ESP32 board pinouts
+//const int LED = 9; // Could be different depending on the dev board. I used the DOIT ESP32 dev board.
+
+//std::string rxValue; // Could also make this a global var to access it in loop()
+
+// See the following for generating UUIDs:
+// https://www.uuidgenerator.net/
+
+#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
+#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" // Qui ricevi da EPS32
+#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" // Qui invii
+
+class MyServerCallbacks: public BLEServerCallbacks {
+ void onConnect(BLEServer* pServer) {
+ deviceConnected = true;
+ };
+
+ void onDisconnect(BLEServer* pServer) {
+ deviceConnected = false;
+ }
+};
+
+
+
+class MyCallbacks: public BLECharacteristicCallbacks {
+ void onWrite(BLECharacteristic *pCharacteristic) {
+ std::string rxValue = pCharacteristic->getValue();
+
+ char letto[] = " ";
+
+ if (rxValue.length() > 0) {
+ Serial.println("*********");
+ Serial.print("Received Value: ");
+
+ for (int i = 0; i < rxValue.length(); i++) {
+ Serial.print(rxValue[i]);
+ letto[i]=rxValue[i];
+ }
+
+ Serial.println();
+
+ String a = String(letto);
+
+ Serial.print(a.toFloat());
+
+ // Do stuff based on the command received from the app
+ if (rxValue.find("A") != -1) {
+ Serial.print("Turning ON!");
+ digitalWrite(LED, HIGH);
+ }
+ else if (rxValue.find("B") != -1) {
+ Serial.print("Turning OFF!");
+ digitalWrite(LED, LOW);
+ }
+
+ Serial.println();
+ Serial.println("*********");
+ }
+ }
+};
+
+void setup() {
+ Serial.begin(115200);
+
+ pinMode(LED, OUTPUT);
+
+ // Create the BLE Device
+ BLEDevice::init("ESP32 UART Test"); // Give it a name
+
+ Serial.print("local BLE Address is: ");
+ Serial.println(BLEDevice::getAddress().toString().c_str());
+
+ // Create the BLE Server
+ BLEServer *pServer = BLEDevice::createServer();
+ pServer->setCallbacks(new MyServerCallbacks());
+
+ // Create the BLE Service
+ BLEService *pService = pServer->createService(SERVICE_UUID);
+
+
+ // BleCharacteristic deviceHealthCharacteristic("deviceHealth", BleCharacteristicProperty::READ, deviceHealthUuid, serviceUuid);
+ // see https://community.thunkable.com/t/ble-hrm-reading-bpm/2441754/6
+
+
+ // Create a BLE Characteristic
+ pCharacteristic = pService->createCharacteristic(
+ CHARACTERISTIC_UUID_TX,
+ //BLECharacteristic::PROPERTY_NOTIFY
+ BLECharacteristic::PROPERTY_READ
+ );
+
+ pCharacteristic->addDescriptor(new BLE2902());
+
+ BLECharacteristic *pCharacteristic = pService->createCharacteristic(
+ CHARACTERISTIC_UUID_RX,
+ BLECharacteristic::PROPERTY_WRITE
+ );
+
+ pCharacteristic->setCallbacks(new MyCallbacks());
+
+ // Start the service
+ pService->start();
+
+ // Start advertising
+ pServer->getAdvertising()->start();
+ Serial.println("Waiting a client connection to notify...");
+}
+
+void loop() {
+
+ if (deviceConnected) {
+ // Fabricate some arbitrary junk for now...
+ txValue = analogRead(readPin) / 3.456; // This could be an actual sensor reading!
+
+ // Let's convert the value to a char array:
+ char txString[8]; // make sure this is big enuffz
+ dtostrf(txValue, 1, 2, txString); // float_val, min_width, digits_after_decimal, char_buffer
+
+// pCharacteristic->setValue(&txValue, 1); // To send the integer value
+ pCharacteristic->setValue("Hello!"); // Sending a test message
+ //pCharacteristic->setValue(txString);
+
+ pCharacteristic->notify(); // Send the value to the app!
+ Serial.print("*** Sent Value: ");
+ Serial.print(txString);
+ Serial.println(" ***");
+
+ // You can add the rxValue checks down here instead
+ // if you set "rxValue" as a global var at the top!
+ // Note you will have to delete "std::string" declaration
+ // of "rxValue" in the callback function.
+// if (rxValue.find("A") != -1) {
+// Serial.println("Turning ON!");
+// digitalWrite(LED, HIGH);
+// }
+// else if (rxValue.find("B") != -1) {
+// Serial.println("Turning OFF!");
+// digitalWrite(LED, LOW);
+// }
+ }
+
+ delay(1000);
+}
+
+
+// Adapted from https://github.com/SIMS-IOT-Devices/FreeRTOS-ESP-IDF-BLE-Server
+
+#include <stdio.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/event_groups.h"
+#include "esp_event.h"
+#include "nvs_flash.h"
+#include "esp_log.h"
+#include "esp_nimble_hci.h"
+#include "nimble/nimble_port.h"
+#include "nimble/nimble_port_freertos.h"
+#include "host/ble_hs.h"
+#include "services/gap/ble_svc_gap.h"
+#include "services/gatt/ble_svc_gatt.h"
+#include "sdkconfig.h"
+
+char *TAG = "BLE-Server";
+uint8_t ble_addr_type;
+void ble_app_advertise(void);
+
+//@_____________________Define UUIDs______________________________________
+//!! b2bbc642-46da-11ed-b878-0242ac120002
+//static const ble_uuid128_t gatt_svr_svc_uuid =
+// BLE_UUID128_INIT(0x02, 0x00, 0x12, 0xac, 0x42, 0x02, 0x78, 0xb8, 0xed, 0x11, 0xda, 0x46, 0x42, 0xc6, 0xbb, 0xb2);
+
+static const ble_uuid128_t gatt_svr_svc_uuid =
+ BLE_UUID128_INIT(0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x01, 0x00, 0x40, 0x6e);
+
+
+//!! c9af9c76-46de-11ed-b878-0242ac120002
+//static const ble_uuid128_t gatt_svr_chr_uuid =
+// BLE_UUID128_INIT(0x02, 0x00, 0x12, 0xac, 0x42, 0x02, 0x78, 0xb8, 0xed, 0x11, 0xde, 0x46, 0x76, 0x9c, 0xaf, 0xc9);
+
+// 6E400002-B5A3-F393-E0A9-E50E24DCCA9E
+
+static const ble_uuid128_t gatt_svr_chr_read_uuid =
+ BLE_UUID128_INIT(0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x02, 0x00, 0x40, 0x6e);
+static const ble_uuid128_t gatt_svr_chr_write_uuid =
+ BLE_UUID128_INIT(0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x03, 0x00, 0x40, 0x6e);
+
+
+// Write data to ESP32 defined as server
+static int device_write(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
+{
+ printf("Data from the client: %.*s\n", ctxt->om->om_len, ctxt->om->om_data);
+ return 0;
+}
+
+// Read data from ESP32 defined as server
+static int device_read(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
+{
+ os_mbuf_append(ctxt->om, "Data from the server", strlen("Data from the server"));
+ return 0;
+}
+
+static const struct ble_gatt_svc_def gatt_svcs[] = {
+ {.type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = &gatt_svr_svc_uuid.u, // Define UUID for device type
+ .characteristics = (struct ble_gatt_chr_def[]){
+ {.uuid = &gatt_svr_chr_write_uuid.u, // Define UUID for reading
+ .flags = BLE_GATT_CHR_F_READ,
+ .access_cb = device_read},
+ {.uuid = &gatt_svr_chr_read_uuid.u, // Define UUID for writing
+ .flags = BLE_GATT_CHR_F_WRITE,
+ .access_cb = device_write},
+ {0}}},
+ {0}};
+
+
+
+// BLE event handling
+static int ble_gap_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type)
+ {
+ // Advertise if connected
+ case BLE_GAP_EVENT_CONNECT:
+ ESP_LOGI("GAP", "BLE GAP EVENT CONNECT %s", event->connect.status == 0 ? "OK!" : "FAILED!");
+ if (event->connect.status != 0)
+ {
+ ble_app_advertise();
+ }
+ break;
+ // Advertise again after completion of the event
+ case BLE_GAP_EVENT_ADV_COMPLETE:
+ ESP_LOGI("GAP", "BLE GAP EVENT");
+ ble_app_advertise();
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+// Define the BLE connection
+void ble_app_advertise(void)
+{
+ // GAP - device name definition
+ struct ble_hs_adv_fields fields;
+ const char *device_name;
+ memset(&fields, 0, sizeof(fields));
+ device_name = ble_svc_gap_device_name(); // Read the BLE device name
+ fields.name = (uint8_t *)device_name;
+ fields.name_len = strlen(device_name);
+ fields.name_is_complete = 1;
+ ble_gap_adv_set_fields(&fields);
+
+ // GAP - device connectivity definition
+ struct ble_gap_adv_params adv_params;
+ memset(&adv_params, 0, sizeof(adv_params));
+ adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; // connectable or non-connectable
+ adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; // discoverable or non-discoverable
+ ble_gap_adv_start(ble_addr_type, NULL, BLE_HS_FOREVER, &adv_params, ble_gap_event, NULL);
+}
+
+// The application
+void ble_app_on_sync(void)
+{
+ ble_hs_id_infer_auto(0, &ble_addr_type); // Determines the best address type automatically
+ ble_app_advertise(); // Define the BLE connection
+}
+
+// The infinite task
+void host_task(void *param)
+{
+ nimble_port_run(); // This function will return only when nimble_port_stop() is executed
+}
+
+void app_main()
+{
+ nvs_flash_init(); // 1 - Initialize NVS flash using
+ //esp_nimble_hci_and_controller_init(); // 2 - Initialize ESP controller
+ nimble_port_init(); // 3 - Initialize the host stack
+ ble_svc_gap_device_name_set("BLE-Server"); // 4 - Initialize NimBLE configuration - server name
+ ble_svc_gap_init(); // 4 - Initialize NimBLE configuration - gap service
+ ble_svc_gatt_init(); // 4 - Initialize NimBLE configuration - gatt service
+ ble_gatts_count_cfg(gatt_svcs); // 4 - Initialize NimBLE configuration - config gatt services
+ ble_gatts_add_svcs(gatt_svcs); // 4 - Initialize NimBLE configuration - queues gatt services.
+ ble_hs_cfg.sync_cb = ble_app_on_sync; // 5 - Initialize application
+ nimble_port_freertos_init(host_task); // 6 - Run the thread
+}
+
+
+
+
+
+
+
+