#!/bin/bash -
#===============================================================================
#
#         FILE: what_pi
#
#        USAGE: ./what_pi
#
#  DESCRIPTION: To be run on a RPi. Reports back what model it is. Uses info
#               from /proc/cpuinfo and a lookup table from
#               http://elinux.org/RPi_HardwareHistory
#
#      OPTIONS: ---
# REQUIREMENTS: ---
#         BUGS: ---
#        NOTES: ---
#       AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com
#      VERSION: 0.0.2
#      CREATED: 2016-06-17 18:17:47
#     REVISION: 2017-04-10 14:45:32
#
#===============================================================================

set -o nounset                              # Treat unset variables as an error

SCRIPT=${0##*/}

#===  FUNCTION  ================================================================
#         NAME: network_info
#  DESCRIPTION: Reports some basic network information in a (hopefully)
#               generalised way.
#               TODO: Make it deal with multiple interfaces properly
#   PARAMETERS: None
#      RETURNS: Nothing
#===============================================================================
network_info () {
    local d dev mac

    echo "Network information:"
    printf "  %-11s: %s\n" "Hostname" "$(hostname -f)"
    printf "  %-11s: %s\n" "IP" "$(hostname -I)"
    for d in /sys/class/net/*/address; do
        dev="${d%/*}"
        dev="${dev##*/}"
        if [[ $dev != 'lo' ]]; then
            mac="$(cat "$d")"
            printf "  %-11s: %s (%s)\n" "MAC" "$mac" "$dev"
        fi
    done
}

#===  FUNCTION  ================================================================
#         NAME: settings_info
#  DESCRIPTION: Reports stuff about settings and config file elements
#   PARAMETERS: None
#      RETURNS: Nothing
#===============================================================================
settings_info () {
    local codec

    #
    # Is the user in the 'video' group?
    #
    if id -Gn | grep -q 'video'; then
        echo "Various configuration and other settings:"
        echo "CPU $(vcgencmd measure_temp)"
        for codec in H264 MPG2 WVC1 MPG4 MJPG WMV9; do
            echo -e "$codec:\t$(vcgencmd codec_enabled $codec)"
        done
        vcgencmd get_config sdtv_mode
        vcgencmd get_config sdtv_aspect
    else
        echo "Can't run 'vgencmd'; you're not in the 'video' group"
    fi
}

#===  FUNCTION  ================================================================
#         NAME: cleanup_temp
#  DESCRIPTION: Cleanup temporary files in case of a keyboard interrupt
#               (SIGINT) or a termination signal (SIGTERM) and at script
#               exit
#   PARAMETERS: * - names of temporary files to delete
#      RETURNS: Nothing
#===============================================================================
function cleanup_temp {
    for tmp in "$@"; do
        [ -e "$tmp" ] && rm --force "$tmp"
    done
    exit 0
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#
# Are we on a Pi at all?
# TODO: Check this. It works on all my machines, but may not work everywhere
#
model=$(grep -m 1 '^model name' /proc/cpuinfo | cut -f2 -d:)
re="ARMv[0-9]"
if [[ ! $model =~ $re ]]; then
    echo "This doesn't seem to be a Raspberry Pi"
    exit 1
fi

#
# Make temporary files and set traps to delete them
#
TMP1=$(mktemp) || { echo "$SCRIPT: creation of temporary file failed!"; exit 1; }
TMP2=$(mktemp) || { echo "$SCRIPT: creation of temporary file failed!"; exit 1; }
trap 'cleanup_temp $TMP1 $TMP2' SIGHUP SIGINT SIGPIPE SIGTERM EXIT

#
# Create a table of Pi stuff. Copied from http://elinux.org/RPi_HardwareHistory
# using simple cut and paste. The result is a table separated by tabs, and
# this script relies on this fact.
# You will have to refresh this every time a new Pi model is released. This
# version is dated Q1 2017 and includes the Pi Zero W
#
cat > "$TMP1" <<'ENDTABLE'
Revision 	Release Date 	Model 	PCB Revision 	Memory 	Notes
Beta 	Q1 2012 	B (Beta) 	 ? 	256 MB 	Beta Board
0002 	Q1 2012 	B 	1.0 	256 MB
0003 	Q3 2012 	B (ECN0001) 	1.0 	256 MB 	Fuses mod and D14 removed
0004 	Q3 2012 	B 	2.0 	256 MB 	(Mfg by Sony)
0005 	Q4 2012 	B 	2.0 	256 MB 	(Mfg by Qisda)
0006 	Q4 2012 	B 	2.0 	256 MB 	(Mfg by Egoman)
0007 	Q1 2013 	A 	2.0 	256 MB 	(Mfg by Egoman)
0008 	Q1 2013 	A 	2.0 	256 MB 	(Mfg by Sony)
0009 	Q1 2013 	A 	2.0 	256 MB 	(Mfg by Qisda)
000d 	Q4 2012 	B 	2.0 	512 MB 	(Mfg by Egoman)
000e 	Q4 2012 	B 	2.0 	512 MB 	(Mfg by Sony)
000f 	Q4 2012 	B 	2.0 	512 MB 	(Mfg by Qisda)
0010 	Q3 2014 	B+ 	1.0 	512 MB 	(Mfg by Sony)
0011 	Q2 2014 	Compute Module 1 	1.0 	512 MB 	(Mfg by Sony)
0012 	Q4 2014 	A+ 	1.1 	256 MB 	(Mfg by Sony)
0013 	Q1 2015 	B+ 	1.2 	512 MB 	 ?
0014 	Q2 2014 	Compute Module 1 	1.0 	512 MB 	(Mfg by Embest)
0015 	 ? 	A+ 	1.1 	256 MB / 512 MB 	(Mfg by Embest)
a01040 	Unknown 	2 Model B 	1.0 	1 GB 	(Mfg by Sony)
a01041 	Q1 2015 	2 Model B 	1.1 	1 GB 	(Mfg by Sony)
a21041 	Q1 2015 	2 Model B 	1.1 	1 GB 	(Mfg by Embest)
a22042 	Q3 2016 	2 Model B (with BCM2837) 	1.2 	1 GB 	(Mfg by Embest)
900021 	Q3 2016 	A+ 	1.1 	512 MB 	(Mfg by Sony)
900092 	Q4 2015 	Zero 	1.2 	512 MB 	(Mfg by Sony)
900093 	Q2 2016 	Zero 	1.3 	512 MB 	(Mfg by Sony)
920093 	Q4 2016? 	Zero 	1.3 	512 MB 	(Mfg by Embest)
9000C1 	Q1 2017 	Zero W 	1.1 	512 MB 	(Mfg by Sony)
a02082 	Q1 2016 	3 Model B 	1.2 	1 GB 	(Mfg by Sony)
a020a0 	Q1 2017 	Compute Module 3 (and CM3 Lite) 	1.0 	1 GB 	(Mfg by Sony)
a22082 	Q1 2016 	3 Model B 	1.2 	1 GB 	(Mfg by Embest)
a32082 	Q4 2016 	3 Model B 	1.2 	1 GB 	(Mfg by Sony Japan)
ENDTABLE

#
# Grab two values from the /proc/cpuinfo file
#
REV="$(grep '^Revision' /proc/cpuinfo | awk '{print $3}' | sed 's/^1000//')"
SER="$(grep '^Serial' /proc/cpuinfo | awk '{print $3}')"

#
# Make an Awk script which finds the details in the above table and displays
# them
#
cat > "$TMP2" <<'ENDPROG'
tolower($0) ~ rev {
    printf "%-13s: %s\n%-13s: %s\n%-13s: %s\n%-13s: %s\n%-13s: %s\n%-13s: %s\n%-13s: %s\n",
        "Revision",$1,
        "Release date",$2,
        "Model",$3,
        "PCB Revision",$4,
        "Memory",$5,
        "Notes",$6,
        "Serial no",serial
}
ENDPROG

#
# Run Awk on the table with the above script, passing the revision number as
# a regular expression for searching, and the serial number as a simple
# string.
#
awk -v "rev=^$REV" -v "serial=$SER" -F" *\t *" -f "$TMP2" "$TMP1"

#
# Report various settings and parameters
#
echo
settings_info

#
# Report network information
#
echo
network_info

exit

# vim: syntax=sh:ts=8:sw=4:ai:et:tw=78:fo=tcrqn21
