Browse files

Release 1.0.18

Feature - Added SD card generator - PiNet will now generate an SD card image as well as a folder of boot files
Feature - Gpiozero and Pygame Zero are now installed by default
Feature - Added new secure PiNet metrics system (explained here -
Bugfix - Switched Chromium to a separate apt-get command in prep for Jessie
Bugfix - Fixed raspberrypi-ui-mods package upgrade issue
  • Loading branch information...
gbaman committed Oct 21, 2015
1 parent e7cdcf1 commit f1aa7198a68228a5c352fb3736a884bbdb76b5a6
Showing with 148 additions and 12 deletions.
  1. +103 −3 Scripts/
  2. +45 −9 pinet
@@ -19,6 +19,7 @@
import shutil
import pwd, grp
from copy import deepcopy
import random
#from gettext import gettext as _
import gettext
@@ -124,7 +125,6 @@ def customAptPip(self):
done = True
debug(self.marked, self.installType, self.installCommands,
def runBash(command):
if type(command) == str:
p = Popen("sudo " + command, shell=True)
@@ -581,9 +581,9 @@ def checkUpdate2():
def GetVersionNum(data):
for i in range(0, len(data)):
bob = data[i][0:8]
line = data[i][0:8]
if data[i][0:7] == "Release":
bob = data[i]
line = data[i]
version = str(data[i][8:len(data[i])]).rstrip()
return version
@@ -989,6 +989,102 @@ def nbdRun():
whiptailBox("msgbox", _("WARNING"), _("Auto NBD compressing is disabled, for your changes to push to the Raspberry Pis, run NBD-recompress from main menu."), False)
def generateServerID():
Generates random server ID for use with stats system.
ID = random.randint(10000000000,99999999999)
setConfigParameter("ServerID", str(ID))
def getIPAddress():
Get the PiNet server external IP address using the IP address checker.
If there is any issues, defaults to returning
import urllib.request
import socket
with urllib.request.urlopen("") as url:
IP =
IP = ""
return IP
def sendStats():
Upload anonymous stats to the secure PiNet server (over encrypted SSL).
DisableMetrics = str(getConfigParameter("/etc/pinet", "DisableMetrics="))
ServerID = str(getConfigParameter("/etc/pinet", "ServerID="))
if ServerID == "None":
ServerID = str(getConfigParameter("/etc/pinet", "ServerID="))
if DisableMetrics.lower() == "true":
KernelVersion = "000"
ReleaseChannel = "0"
City = "Blank"
OrganisationType = "Blank"
OrganisationName = "Blank"
PiNetVersion = str(getConfigParameter("/usr/local/bin/pinet", "version="))
Users = str(len(getUsers()))
if os.path.exists("/home/"+os.environ['SUDO_USER']+"/PiBoot/version.txt"):
KernelVersion = str(getCleanList("/home/"+os.environ['SUDO_USER']+"/PiBoot/version.txt")[0])
KernelVersion = "000"
City = str(getConfigParameter("/etc/pinet", "City="))
OrganisationType = str(getConfigParameter("/etc/pinet", "OrganisationType="))
OrganisationName = str(getConfigParameter("/etc/pinet", "OrganisationName="))
ReleaseChannel = str(getConfigParameter("/etc/pinet", "ReleaseChannel="))
IPAddress = getIPAddress()
command = 'curl --connect-timeout 2 --data "ServerID='+ ServerID + "&" + "PiNetVersion=" + PiNetVersion + "&" + "Users=" + Users + "&" + "KernelVersion=" + KernelVersion + "&" + "ReleaseChannel=" + ReleaseChannel + "&" + "IPAddress=" + IPAddress + "&" + "City=" + City + "&" + "OrganisationType=" + OrganisationType + "&" + "OrganisationName=" + OrganisationName + '" -s -o /dev/null 2>&1'
def checkStatsNotification():
Displays a one time notification to the user only once on the metrics.
ShownStatsNotification = str(getConfigParameter("/etc/pinet", "ShownStatsNotification="))
if ShownStatsNotification == "true":
pass #Don't display anything
whiptailBox("msgbox", _("Stats"), _("Please be aware PiNet now collects very basic usage stats. These stats are uploaded to the secure PiNet metrics server over an encrypted 2048 bit SSL/TLS connection. The stats logged are PiNet version, Raspbian kernel version, number of users, development channel (stable or dev), external IP address, a randomly generated unique ID and any additional information you choose to add. These stats are uploaded in the background when PiNet checks for updates. Should you wish to disable the stats, see -"), False, height="14")
setConfigParameter("ShownStatsNotification", "true", "/etc/pinet")
def askExtraStatsInfo():
import re
Ask the user for additional stats information.
whiptailBox("msgbox", _("Additional information"), _("It is really awesome to see and hear from users across the world using PiNet. So we can start plotting schools/organisations using PiNet on a map, feel free to add any extra information to your PiNet server. It hugely helps us out also for internationalisation/localisation of PiNet. If you do not want to attach any extra information, please simply leave the following prompts blank."), False, height="13")
city = whiptailBox("inputbox", _("Nearest major city"), _("To help with putting a dot on the map for your server, what is your nearest major town or city? Leave blank if you don't want to answer."), False, returnErr = True)
organisationType = whiptailSelectMenu(_("Organisation type"), _("What type of organisation are you setting PiNet up for? Leave on blank if you don't want to answer."), ["Blank", "School", "Non Commercial Organisation", "Commercial Organisation", "Raspberry Jam/Club", "N/A"])
organisationName = whiptailBox("inputbox", _("School/organisation name"), _("What is the name of your organisation? Leave blank if you don't want to answer."), False, returnErr = True)
whiptailBox("msgbox", _("Additional information"), _('Thanks for taking the time to read through (and if possible fill in) additional information. If you ever want to edit your information supplied, you can do so by selecting the "Other" menu and selecting "Edit-Information".'), False, height="11")
organisationType = organisationType.decode("utf-8")
organisationType = "Blank"
if city == "":
city = "Blank"
if organisationType == "":
organisationType = "Blank"
if organisationName == "":
organisationName = "Blank"
city = re.sub('[^0-9a-zA-Z]+', '_', city)
organisationType = re.sub('[^0-9a-zA-Z]+', '_', organisationType)
organisationName = re.sub('[^0-9a-zA-Z]+', '_', organisationName)
setConfigParameter("City", city)
setConfigParameter("OrganisationType", organisationType)
setConfigParameter("OrganisationName", organisationName)
#------------------------------Main program-------------------------
@@ -1029,3 +1125,7 @@ def nbdRun():
elif sys.argv[1] == "installSoftwareFromFile":
elif sys.argv[1] == "sendStats":
elif sys.argv[1] == "checkStatsNotification":
54 pinet
@@ -3,7 +3,7 @@
# See LICENSE file for copyright and license details
#PiNet (Previously RaspberryPi-LTSP)
@@ -88,6 +88,7 @@ LegacyFixes() {
echo $"A required system update has been found. I will now compress the operating system again to apply this update"
$p "checkStatsNotification"
@@ -333,7 +334,7 @@ UpdateIP(){
IP=`ifconfig | grep 'inet addr:'| grep -v '' | cut -d: -f2 | awk '{ print $1}'`; #Get the current main IP address
whiptail --title $"IP address" --yesno $"Would you like to stick with your current IP address for the SD cards? (Recommended)" 8 78 #Check with this use that the IP address is correct
whiptail --title $"IP address" --yesno $"I have detected your current IP address is $IP. Would you like to setup the SD card image with it? (Recommended)" 8 78 #Check with this use that the IP address is correct
if [ ! $exitstatus = 0 ]; then
@@ -369,7 +370,7 @@ else
sudo sed -i 's/'$IP'/g' "/home/$SUDO_USER/PiBoot/cmdline.txt"
nautilus "/home/$SUDO_USER/PiBoot" > /dev/null 2>&1 &
@@ -662,7 +663,7 @@ AddSoftware(){
# To add more software, just add it to the end of the list below taking a space after each program
ltsp-chroot --arch armhf apt-get install -y idle idle3 python-dev nano python3-dev scratch python3-tk git debian-reference-en dillo python python-pygame python3-pygame python-tk sudo sshpass pcmanfm chromium python3-numpy wget xpdf gtk2-engines alsa-utils wpagui omxplayer lxde net-tools mpg123
ltsp-chroot --arch armhf apt-get install -y idle idle3 python-dev nano python3-dev scratch python3-tk git debian-reference-en dillo python python-pygame python3-pygame python-tk sudo sshpass pcmanfm python3-numpy wget xpdf gtk2-engines alsa-utils wpagui omxplayer lxde net-tools mpg123
ltsp-chroot --arch armhf apt-get install -y ssh locales less fbset sudo psmisc strace module-init-tools ifplugd ed ncdu console-setup keyboard-configuration debconf-utils parted unzip build-essential manpages-dev python bash-completion gdb pkg-config python-rpi.gpio v4l-utils lua5.1 luajit hardlink ca-certificates curl fake-hwclock ntp nfs-common usbutils libraspberrypi-dev libraspberrypi-doc libfreetype6-dev
ltsp-chroot --arch armhf apt-get install -y python3-rpi.gpio python-rpi.gpio python-pip python3-pip python-picamera python3-picamera x2x wolfram-engine xserver-xorg-video-fbturbo netsurf-common netsurf-gtk rpi-update
ltsp-chroot --arch armhf apt-get install -y ftp libraspberrypi-bin python3-pifacecommon python3-pifacedigitalio python3-pifacedigital-scratch-handler python-pifacecommon python-pifacedigitalio i2c-tools man-db
@@ -675,6 +676,7 @@ ltsp-chroot --arch armhf apt-get install -y java-common oracle-java8-jdk apt-uti
ltsp-chroot --arch armhf update-rc.d nfs-common disable
ltsp-chroot --arch armhf update-rc.d rpcbind disable
ltsp-chroot --arch armhf apt-get install -y linux-image-3.18.0-trunk-rpi linux-image-3.18.0-trunk-rpi2 linux-image-3.12-1-rpi linux-image-3.10-3-rpi linux-image-3.2.0-4-rpi linux-image-rpi-rpfv linux-image-rpi2-rpfv
ltsp-chroot --arch armhf apt-get install -y chromium
ltsp-chroot --arch armhf touch /boot/config.txt #Required due to bug in sense-hat package installer
ltsp-chroot --arch armhf apt-get install -y sense-hat
@@ -690,7 +692,11 @@ if [ ! -f /opt/ltsp/armhf/usr/local/bin/raspi2png ]; then
#Install pillow which is required for Raspberry Pi Sense HAT.
sudo ltsp-chroot sudo pip-3.2 install pillow
sudo ltsp-chroot --arch armhf sudo pip-3.2 install pillow
#Install Pygame Zero and gpiozero
sudo ltsp-chroot --arch armhf pip install gpiozero
sudo ltsp-chroot --arch armhf pip-3.2 install pgzero gpiozero
#Server software
apt-get install -y bindfs python3-feedparser ntp
@@ -1243,8 +1249,9 @@ Updater(){
#Checks if there is a new software release. Mainly uses CheckUpdate on Python side
#Checks if there is a new software release. Mainly uses CheckUpdate on Python side. Also runs sendStats.
$PythonStart -c 'import feedparser' 2>/dev/null || (sudo apt-get install python3-feedparser )
$p sendStats
$p CheckUpdate $version
#echo $exitstatus
@@ -2061,14 +2068,14 @@ CheckRaspberryPiUIModsAllUsers(){
#Installs the new Raspberry Pi UI mods, but fixes the mistakes made in the wallpaper setting
ltsp-chroot apt-get update
ltsp-chroot apt-get -o Dpkg::Options::="--force-overwrite --force-confnew" install -y raspberrypi-ui-mods
ltsp-chroot apt-get -o Dpkg::Options::="--force-confnew" install -y raspberrypi-ui-mods
FixUIConfigFile "System" "pcmanfm.conf"
FixUIConfigFile "System" "desktop-items-0.conf"
whiptail --title $"Release channels" --yesno --yes-button $"Stable" --no-button $"Bleeding edge" $"Would you like to use the stable or bleeding edge (developer) software update channels? Stable is recommended." 8 78
whiptail --title $"Release channels" --yesno --yes-button $"Stable" --no-button $"Development" $"Would you like to use the stable or development (dev) software update channels? Stable is recommended. Do not use the development (dev) channels in a production environment (for example a school) as stability is not guaranteed. " 8 78
if [ $? -eq 0 ]; then
UpdateConfig ReleaseChannel "Stable"
@@ -2130,6 +2137,29 @@ CheckInstallSuccess(){
CreatePartitionTable() {
#Directly borrowed from Spindle -
sudo parted $1 <<EOF
unit b
mklabel msdos
mkpart primary fat32 $(expr 4 \* 1024 \* 1024) $(expr 60 \* 1024 \* 1024 - 1)
dd if=/dev/zero of=$fileName bs=512 count=208845
create_partition_table $fileName
sudo mkdosfs -n PINET -S 512 -s 16 -v $fileName
mkdir /mnt/sdimage
mount $fileName /mnt/sdimage
cp -r /home/$SUDO_USER/PiBoot/* /mnt/sdimage/
umount /mnt/sdimage
rm -r /mnt/sdimage
mv $fileName /home/$SUDO_USER/pinetSDImage.img
@@ -2207,6 +2237,7 @@ OtherMenu() {
"NBD-compress-enable" $"Enable auto NBD recompression after every change (default)" \
"Export-users" $"Export all user data for migrating to new PiNet server" \
"Change-release-channel" $"Change your current update channel to dev or stable" \
"Edit-Information" $"Edit information attached to the PiNet server" \
"Full-Install" $"Full install of PiNet server" \
3>&1 1>&2 2>&3)
@@ -2253,6 +2284,10 @@ case "$MENUEPT" in
$p "askExtraStatsInfo"
ChooseReleaseChannel "Restart"
@@ -2647,7 +2682,7 @@ case "$MENUOPT" in
if [ $? -eq 0 ]; then
whiptail --title $"SD image updated" --msgbox $"SD card image updated. Please copy the files found in /home/$SUDO_USER/PiBoot folder (I also tried to just open the folder for you) onto a blank SD card." 9 78
whiptail --title $"SD image updated" --msgbox $"SD card image updated. A folder of boot files in /home/$SUDO_USER/PiBoot has been created. An experimental disk image ready to flash onto the SD card has also been created at /home/$SUDO_USER/pinetSDImage.img. You can use either option. See for help." 11 78
@@ -2794,6 +2829,7 @@ if [ $intStat -eq 0 ]; then
checkKernelUpdater "NBD"
LegacyFixes #Makes sure all configuration data is correctly configured

0 comments on commit f1aa719

Please sign in to comment.