Opportunistic Networking (OppNets) is a type of wireless networking acrchitecture where nodes communicate directly with other nodes to exchange information, without using any networking infrastructure such as wireless base stations or access points. This repository, OppNets-on-LoPy provides a collection of source code that implements the functionality to operate OppNets nodes for LoPy4 (PyCom) devices.
A node implementation consist of a 3-layer protocol stack architecture.
- Application layer - implements an application that generates and receives data
- Forwarding layer - implements the forwarding protocol to disseminate data
- Link layer - implements direct communications over an available link technology and neighbourhood management
Depending on the requirement, each layer can be configured to use different implementations.
The Atom IDE
, one of the IDEs recommnded (link) by the makers of the LoPy4 device, was used to develop this implementation and to load it to the LoPy device. To load, configure and run, follow the instructions below.
- Download this repository to a computer where the
Atom IDE
is installed - Open the
./node
folder as a project (Add Project Folder
) in theAtom IDE
- Setup the protocol stack (
APP_LAYER
,FWD_LAYER
,LINK_LAYER
) and the parmeters in thelib/settings.py
(or leave as is to use the default settings) - Press the
Upload project to device
button to upload the code into the LoPy4 device
There are also other code available to perform different tasks related to the implementation. They could be code to run on LoPy devices (like manage the the SD card) or parsers run on your computer to parse a log. All these are made available under ./tools
or ./parsers
This is an on-going work. Below is a list of the status of the current implementation.
- Uses LoRa for direct communications between nodes (in
./node/lib/lora.py
module) - Uses the Randomized Rumour Spreading (RRS) forwarding protocol (in
./node/lib/rrs.py
module) - Has a simple application that generates periodic data (in
./node/lib/simpleapp.py
module)
The implementation is distributed in multiple source files. The following high-level folders contain spacific parts of the implementation.
./node
- contains micro-python code implementing a LoPy4 based OppNets node./tools
- contains micro-python or other code that manages different aspects (e.g., manage SD card in a LoPy)./parsers
- contains parsers written to extract information (e.g., from the log created by the LoPy)
A brief description of each of these high-level folders are given below.
The following source files (in ./node
folder) implements the functionality of an OppNets node that is configured based on the diferent protocol layer implementations required.
main.py
- initiates all operationslib/settings.py
- contains the protocol layer configurations and all the parameters usedlib/common.py
- contains all the common variables (e.g., queues) used by other source fileslib/simpleapp.py
- contains code that implements a simple data injection applicationlib/rrs.py
- contains the code that implements the RRS based forwarding functionalitylib/lora.py
- contains the code that implements LoRa based communications
This folder (./parsers
) holds all the parsers to extract data from the log. Currently contains only a place holder file.
This folder (./tools
) contains programs required for managing different components of the environment.
The sd-check
tool is to manage the contents of an SD card plugged in to a LoPy (e.g., remove the log, dump the log).
Protocol layers exchange information using messages. Here are the formats of those messages. Information in each message is separated by a colon (:
)
Application Layer <-> Forwarding Layer
-D:3B0C-9187043:10950513
D
- a data message3B0C-9187043
- data name10950513
- data
Forwarding Layer -> Link Layer
-E820:D:3B0C-16336283:10330829
E820
- destination node (FFFF if broadcast RRS)D
- a data message3B0C-16336283
- data name10330829
- data
Link Layer -> Forwarding Layer
-D:E820-9162187:10807013
D
- a data messageE820-9162187
- data name10807013
- data
Link Layer -> Forwarding Layer
-H:E820:F213
H
- neighbour list messageE820:F213
2 neighbours
-
Link Layer <-> LoRa
-E820:FFFF:H:E820
E820
- source addressFFFF
- destination address (FFFF is broadcast)H
- neighbour (hello) alive messageE820
- neighbour whose alive
-
Link layer <-> LoRa
-3B0C:E820:D:3B0C-2925294:1462647
3B0C
- source addressE820
- destination address (FFFF is broadcast)D
- a data message3B0C-2925294
- data name1462647
- data
Here is a description of the different protocol layers currently available in the implementation. We are updating this reqpository with new protocll layers when they become available.
This application generates data with random values and passes it on to the forwarding layer to inject to the network.
The Randomized Rumour Spreading (RRS) is a forwarding protocol that selects data randomly from a cache and sends to nodes in the communication range of that node. When sending, it can decide either to broadcast (for every neighbour to receive) or send it to a specific node.
This link protocol uses LoRa to perform direct communications with nodes in a neighbourhood. Using a HELLO
message mechanism, it keeps track of the neighbours in a node's neighbourhood.
All activities can be looged to the console and/or the log file. These have to be configured in the lib/settings.py
file. If the log file writing is enabled, a Micro SD card must be inserted in the LoPy4. Below is a sample of a log.
1536792 3B0C link > LoRa | 3B0C:FFFF:H:3B0C
1537327 3B0C rss > link | E820:D:3B0C-9895291:11173565
1537361 3B0C link < rrs | E820:D:3B0C-9895291:11173565
1537370 3B0C link > LoRa | 3B0C:E820:D:3B0C-9895291:11173565
1539026 3B0C link < LoRa | E820:FFFF:H:E820
1540267 3B0C rrs < link | H:E820
All configurable parameters are listed in the lib/settings.py
file. The current settings are as follows.
BROADCAST_ADDRESS = 'FFFF'
MAX_QUEUE_SIZE = 50
MAINTAIN_CONSOLE_LOG = True
MAINTAIN_WRITTEN_LOG = True
LOG_FILE_NAME = '/sd/log.txt'
APP_LAYER = 'simpleapp'
DATA_GEN_INTERVAL_SEC = 13
FWD_LAYER = 'rrs'
CACHE_ITEM_LIMIT = 50
BROADCAST_RRS = False
DATA_SEND_INTERVAL_SEC = 8
LINK_LAYER = 'lora'
HELLO_INTERVAL_SEC = 5
MISSED_HELLOS = 3
SEND_BLINK_COLOUR = 'blue'
RECV_BLINK_COLOUR = 'green'
This version of the modules has been tested on the following LoPy4 firmware versions.
Pycom MicroPython 1.20.0.rc13 [v1.9.4-94bb382] on 2019-08-22; LoPy4 with ESP32
Pycom MicroPython 1.20.2.rc9 [v1.11-1a257d8] on 2020-06-10; LoPy4 with ESP32
The implementation architecture allows other protocol layers to be added to the implementation. When implementing, the following aspects have to be strictly observed.
Every protocol layer MUST implement the following 2 functions in one single module, in addition to other functions that may be required for the operation of the layer.
def initialize():
- function that initializes the protocol layerdef start():
- function that starts the oprotocol layer, which may involve starting a number of threads to perform tasks
The module that implements these functions must be specified in one of the following variables (depending on the layer implemented) in the lib/settings.py
module.
APP_LAYER = 'simpleapp'
FWD_LAYER = 'rrs'
LINK_LAYER = 'lora'
The lib/common.py
has a set of queues and threading locks to exchange messages between layers. All messages exchanges must be done using these queues and before using any of these queues (i.e., inserting or popping out messages), the corresponsing lock must be acquired. Following are those queues and locks.
fwd_upper_in_q
app_lower_in_q
fwd_upper_in_lock
app_lower_in_lock
link_upper_in_q
fwd_lower_in_q
link_upper_in_lock
fwd_lower_in_lock
Exchanging information between the layers is done using a set of messages. The formats of these messages are given in the Message Formats section. Of course, if a new protocol layer has other messages to exchange, they will have to be added in appropriate modules.
When performing activity logging in the new protocol layer implementation, the following lock must be held before calling the common.log_activity(info)
function.
logging_lock
Here are some suggestions to follow when developing protocol layers.
- Try to develop all layer functionality in one module to prevent the cluttering of the
lib
folder - Name modules so that the functionality is obvious from the name
- Place all user configurable settings in the
lib/settings.py
file - Place functions used by more than one layer (i.e., common functions) in the
lib/common.py
file (e.g.,def pick_item(sequence):
) - Where ever required, use exception handling (i.e.,
try:
andexcept
) to avoid crashing the layer completely when errors occur
If you have any questions or comments, please write to us using ops@comnets.uni-bremen.de
- Asanga Udugama
- Jens Dede
- Vishnupriya Parimalam
- Anna Förster