Snap4All TechnicalManual 2022
Snap4All TechnicalManual 2022
2022 November
Contents
1 Introduction 2
3 New features 8
3.1 Restart not required . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.2 Installation speed . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.2.1 Full bootstrap build via Linode . . . . . . . . . . . . . . . 9
3.3 User interface remake . . . . . . . . . . . . . . . . . . . . . . . . 9
1
1 Introduction
For each chapter that requires it, blocks of code will be proposed as an example
of the work described in the same. Each resource used will be included as a
footnote corresponding to its use. The previous application was developed in
2018 by Steven Salazar1 , whose report we attach here2 . This version has been
developed by Alberto Del Buono Paolini - Federico Marra with the support of
DISIT lab, Snap4City team and experts.
To solve the first and most important problem, we had to completely update
the application starting from a fork of the latest version of Termux, available
on GitHub3 . As a Termux fork we also inherited4 their GPLv3 license for the ap-
plication and the Apache 2.0 licenses for the terminal-view and terminal-
emulator subpackages.
We have reported all the code snippets reported with the TERMUX MERGE com-
ment from the previous codebase to the new fork5 just created. Unfortunately
this was not enough since not all code changes of original Termux had been
reported with that comment. Moreover, some modified files were no longer
present in the same form since the code or Termux had been updated. Now
all changes to the original Termux repository are marked with TERMUX MERGE
and easily traceable by searching for MERGE across the codebase.
1
https://github.com/StevenSalazarM
2
https://github.com/albbus-stack/snap4all/blob/master/old-relation/
StevenSalazarOldRelation.pdf
3
https://github.com/termux/termux-app
4
https://github.com/termux/termux-app/blob/master/LICENSE.md
5
https://github.com/albbus-stack/snap4all
2
TermuxActivity.java - Esempio di commento di merge
Clearly, the subpackage of Termux responsible for interactions with the An-
droid system, i.e. termux-api-package, had also been updated very fre-
quently in the recent years. We have therefore made a fork6 of this package,
including also the changes necessary for the operation of the custom com-
mands termux-enable-buttons, termux-bluetooth-scaninfo and termux-
bluetooth-connect. The latter call the corresponding Java functions local-
ized in the termux-api module that implement their functionality.
termux-enable-buttons.sh
#!/data/data/com.termux/files/usr/bin/sh
set -e -u
SCRIPTNAME=termux-enable-buttons
show_usage () {
echo "Usage: \$SCRIPTNAME"
echo "Enables the node-red button."
exit 0
}
...
/data/data/com.termux/files/usr/libexec/termux-api EnableButtons
6
https://github.com/albbus-stack/snap4all-termux-api-package
3
2.3 Updating bootstrap packages
shell
> ./run-docker.sh
> ./generate-bootstrap.sh -a git, make, cmake, clang, coreutils, nano,
nodejs, openssh
Several errors occurred while testing the application, including one related to
node-red-contrib-termux-apipackage. This error occurred using the Cam-
era Photo node and was due to the incorrect call of the fs.unlink function,
7
https://github.com/termux/termux-packages/blob/master/scripts/
generate-bootstraps.sh
8
https://github.com/termux/termux-packages
4
whose task is to delete the temporary photo that was taken by the Termux api.
We then made a fork9 of that package by changing the call to unlink, adding as
a second argument a callback that runs at the end of this function. Checking
the other nodes of this package, we did not find any other function that had a
deprecated signature.
index.js
// This is where the live npm package fails, the signature of the
unlink function used was incorrect, having no callback as the second
argument
fs.unlink(photoFile, (err) => {
if (err) throw err;
});
});
TermuxService.java
String setupScript =
"#!/data/data/com.termux/files/usr/bin/sh\n" +
9
https://github.com/albbus-stack/node-red-contrib-termux-api
5
// Acquire wakelock
"termux-wake-lock\n"+
// Npm executable setup for termux
"[ -f "+isInstalled+" ] || chmod +x "+PREFIX_PATH+"/bin/npm\n"+
// Installs a custom termux-api package
"[ -d "+apiPackagePath+" ] || pkg install clang -o
. DPkg::Options::=\"--force-confold\" --no-upgrade -y\n"+
"[ -d "+apiPackagePath+" ] || git clone
. https://github.com/albbus-stack/snap4all-termux-api-package\n"+
"[ -f "+apiPackagePath+"/Makefile ] || ( cd snap4all-termux-api-package
. && cmake CMakeLists.txt )\n"+
"[ -f "+apiPackagePath+"/libtermux-api.so ] || make\n"+
"[ -f "+apiPackageInstallPath+" ] || make install\n"+
// Installs node-red
...
// Installs node-red-contrib-termux-api
...
// Changing index.js of node-red-contrib-termux-api to an updated one
. with the new node.js function signatures
"[ -f "+isInstalled+" ] || cd $HOME\n"+
"[ -f "+isInstalled+" ] || curl
. https://raw.githubusercontent.com/albbus-stack/node-red-contrib-
. termux-api/master/index.js >
. index.js\n"+
"[ -f "+isInstalled+" ] || mv index.js ../usr/lib/node_modules/node-
. red/node_modules/node-red-contrib-termux-api/\n"+
// Installs node-red-dashboard
...
// Installs node-red-contrib-snap4city-user
...
// Installs node-red-contrib-snap4city-developer
...
// Downloads and moves the node-red flows example to the node-red folder
"[ -f "+isInstalled+" ] || cd $HOME\n"+
6
"[ -f "+isInstalled+" ] || curl
. https://raw.githubusercontent.com/albbus-
. stack/snap4all/master/flows.json >
. flows.json\n"+
"[ -f "+isInstalled+" ] || mv -f flows.json .node-red/\n"+
// Enables the buttons on the main page and starts the node-red server,
. this part executes every time on boot since it has no modifiers
"[ -f "+isInstalled+" ] || touch $HOME/installed\n"+
"termux-toast \"starting node-red\" && "+vibration+"\n"+
"termux-enable-buttons\n"+
// Runs node-red and, if it terminates with an error, will run this
. script again
"node "+nodeRedPath+" || $HOME/.termux/boot/start\n";
Esempi di documentazione
7
// Set pending intent, pointing to the MainActivity, to be launched when
. notification is clicked
TermuxActivity.MainOptions.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
. TermuxActivity.MainOptions, 0);
...
// Enables the console button on the MainActivity if the setup was
. successful
MainActivity.activity.btnConsole.setEnabled(true);
3 New features
TermuxService.java
The old bootstrap archives that were used in the Termux installation did not
contain any additional apt packages, thus making the subsequent installation
process much longer than necessary. By directly adding the packages we need
in the Termux filesystem we are only going to increase the weight of the final
application, drastically reducing waiting times during the setup of Snap4All.
8
3.2.1 Full bootstrap build via Linode
10
https://github.com/albbus-stack/snap4all/blob/compile-branch/
generate-and-build.sh
11
https://github.com/material-components/material-components-android
9
Information page and console layouts (InfoActivity and MainActiv-
ity)
We later modified the old application information page, consisting of a Web-
View showing the info.html12 file. So, we have rewritten the documentation
that explains how Snap4All works and directs the user to other sources to
deepen his use of the individual packages included in the application. To
make the design consistent with the home page we inserted CSS inside the file
quoted above. Figure (b) on page 11.
In the old version there was a problem with the Termux sidebar (where the
various active sessions of the console are listed): the icons were not shown and
the background was completely transparent, thus making the use impossible.
Figure (c) on page 11.
We then created two sample flows that make use of the node-red-contrib-
snap4city-user15 and node-red-contrib-snap4city-developer16 , which
are part of the Snap4City node suite. These are added automatically during
installation, always in the setup script, going to copy into the folder .node-red
12
https://github.com/albbus-stack/snap4all/blob/master/app/src/main/assets/
info.html
13
https://www.snap4city.org/
14
https://github.com/albbus-stack/snap4all/tree/master/logos
15
https://github.com/disit/node-red-contrib-snap4city-user
16
https://github.com/disit/node-red-contrib-snap4city-developer
10
(a) Home (b) Info (c) Console
11
the flows.json17 file so that Node-RED loads these flows when initializing the
local server. To correctly use the first two example flows you need to configure
the credentials to Snap4City by following the tutorial on the information page.
The flow extracts the battery percentage of the device via termux-battery-
status18 node. This string is then converted to a float in the function node.
Subsequently, the msg.payload is transformed into a string and passed to the
fiware orion out node that will send it to the Snap4City broker, containing
an IOT device with a certain name corresponding to the two fields key_1 e
key_2 compilati filled in during the node setup.
Nodo batteryPayload
msg.payload = {
"name": "battery",
"value": parseFloat(msg.payload.percentage),
"type": "float"
};
17
https://github.com/albbus-stack/snap4all/blob/master/app/src/main/java/
com/termux/app/flows-example.json
18
https://wiki.termux.com/wiki/Termux-battery-status
12
msg.payload = JSON.stringify(msg.payload);
return msg;
When the flow starts the Wifi Info node node calls the API termux-wifi-
connectioninfo19 that retrieves the connection status, the SSID, and the
IP address. This information enters the three function nodes conncection-
StatePayload, ssidPayload and ipPayload, which manipulate the informa-
tion received and convert the resulting object into a string. As in the first
example flow, information will be sent through the fiware orion out node.
Nodo ipPayload
msg.payload = {
"name": "ip",
"value": msg.payload.ip,
19
https://wiki.termux.com/wiki/Termux-wifi-connectioninfo
13
"type": "string"
};
msg.payload = JSON.stringify(msg.payload);
return msg;
14
Nodi numbersPayload e tplAgenciesPayload
msg.payload = msg.payload.text
msg.topic = "numbers"
return msg;
---
msg.payload = JSON.stringify(msg.payload)
msg.topic = "tplagencies"
return msg;
In the join node the two subflows are joined in a unique msg.payload, in-
dexed according to the names of the topic, which waits for the arrival of both
messages before continuing the execution of the flow (through the setting Send
the message after 2 message parts and every subsequent message).
The information enters the textPayload function node which:
1. Assigns msg.numbers to the msg.payload of the first subflow that contains
user input.
2. It cycles on all JSON objects contained in the msg.payload.tplagencies
(corresponding to the second subflow) and sets a string with all the names
of the transport agencies that will then be assigned to the final message.
In the end, the SMS Send node calls the termux-sms-send22 API which sends
an SMS to the number corresponding to msg.numbers containing the just set
string.
Nodo textPayload
msg.numbers = msg.payload.numbers
let s = "All Snap4City TPL Agencies:\n"
for (let x of (JSON.parse(msg.payload.tplagencies))) {
s += x.name + "\n";
}
22
https://wiki.termux.com/wiki/Termux-sms-send
15
msg.payload = s
return msg;
16