522 lines
15 KiB
HTML
Executable File
522 lines
15 KiB
HTML
Executable File
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="generator" content="pandoc">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||
<meta name="author" content="Dave Morriss">
|
||
<title>Making a Raspberry Pi inventory (HPR Show 2496)</title>
|
||
<style type="text/css">code{white-space: pre;}</style>
|
||
<!--[if lt IE 9]>
|
||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||
<![endif]-->
|
||
<style type="text/css">
|
||
div.sourceCode { overflow-x: auto; }
|
||
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
|
||
margin: 0; padding: 0; vertical-align: baseline; border: none; }
|
||
table.sourceCode { width: 100%; line-height: 100%; }
|
||
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
|
||
td.sourceCode { padding-left: 5px; }
|
||
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
|
||
code > span.dt { color: #902000; } /* DataType */
|
||
code > span.dv { color: #40a070; } /* DecVal */
|
||
code > span.bn { color: #40a070; } /* BaseN */
|
||
code > span.fl { color: #40a070; } /* Float */
|
||
code > span.ch { color: #4070a0; } /* Char */
|
||
code > span.st { color: #4070a0; } /* String */
|
||
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
|
||
code > span.ot { color: #007020; } /* Other */
|
||
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
|
||
code > span.fu { color: #06287e; } /* Function */
|
||
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
|
||
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
|
||
code > span.cn { color: #880000; } /* Constant */
|
||
code > span.sc { color: #4070a0; } /* SpecialChar */
|
||
code > span.vs { color: #4070a0; } /* VerbatimString */
|
||
code > span.ss { color: #bb6688; } /* SpecialString */
|
||
code > span.im { } /* Import */
|
||
code > span.va { color: #19177c; } /* Variable */
|
||
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
|
||
code > span.op { color: #666666; } /* Operator */
|
||
code > span.bu { } /* BuiltIn */
|
||
code > span.ex { } /* Extension */
|
||
code > span.pp { color: #bc7a00; } /* Preprocessor */
|
||
code > span.at { color: #7d9029; } /* Attribute */
|
||
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
|
||
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
|
||
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
|
||
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
|
||
</style>
|
||
<link rel="stylesheet" href="http://hackerpublicradio.org/css/hpr.css">
|
||
</head>
|
||
|
||
<body id="home">
|
||
<div id="container" class="shadow">
|
||
<header>
|
||
<h1 class="title">Making a Raspberry Pi inventory (HPR Show 2496)</h1>
|
||
<h2 class="author">Dave Morriss</h2>
|
||
<hr/>
|
||
</header>
|
||
|
||
<main id="maincontent">
|
||
<article>
|
||
<header>
|
||
<h1>Table of Contents</h1>
|
||
<nav id="TOC">
|
||
<ul>
|
||
<li><a href="#introduction">Introduction</a></li>
|
||
<li><a href="#script">Script</a></li>
|
||
<li><a href="#example-output">Example output</a></li>
|
||
<li><a href="#links">Links</a></li>
|
||
</ul>
|
||
</nav>
|
||
</header>
|
||
<h2 id="introduction">Introduction</h2>
|
||
<p>I have a number of Raspberry Pis – possibly too many – and I sometimes lose track of which is which, what model, size, name, address each one is. I wanted to be able to keep an inventory of them all, and to this end I wrote myself a little script that can be run on any Pi which will report useful information about it.</p>
|
||
<p>Every Pi has a unique serial number. Actually it’s randomly generated so there may be a few collisions but it’s close to unique! It also contains a revision number which encodes various items of information about it such as release date, model, PCB revision and memory. My script decodes this revision number for you based on a published table.</p>
|
||
<p>I run a Wikimedia instance on a Pi and have used this script to record details of my Pis there as well as what they are being used for and any planned projects. I now feel more organised!</p>
|
||
<h2 id="script">Script</h2>
|
||
<p>The script is called <em>what_pi</em> and uses Bash. The master copy is available on my <a href="https://gitlab.com/davmo/what_pi" title="Script 'what_pi' on GitLab">GitLab repository</a> or can be downloaded from HPR (or archive.org if you are reading these notes there). It is a work in progress and contains various notes pointing out possible shortcomings.</p>
|
||
<p>The script is listed below, but I will be brief in my description of its features in this episode.</p>
|
||
<div class="sourceCode"><table class="sourceCode numberLines"><tr class="sourceCode"><td class="lineNumbers"><pre>1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15
|
||
16
|
||
17
|
||
18
|
||
19
|
||
20
|
||
21
|
||
22
|
||
23
|
||
24
|
||
25
|
||
26
|
||
27
|
||
28
|
||
29
|
||
30
|
||
31
|
||
32
|
||
33
|
||
34
|
||
35
|
||
36
|
||
37
|
||
38
|
||
39
|
||
40
|
||
41
|
||
42
|
||
43
|
||
44
|
||
45
|
||
46
|
||
47
|
||
48
|
||
49
|
||
50
|
||
51
|
||
52
|
||
53
|
||
54
|
||
55
|
||
56
|
||
57
|
||
58
|
||
59
|
||
60
|
||
61
|
||
62
|
||
63
|
||
64
|
||
65
|
||
66
|
||
67
|
||
68
|
||
69
|
||
70
|
||
71
|
||
72
|
||
73
|
||
74
|
||
75
|
||
76
|
||
77
|
||
78
|
||
79
|
||
80
|
||
81
|
||
82
|
||
83
|
||
84
|
||
85
|
||
86
|
||
87
|
||
88
|
||
89
|
||
90
|
||
91
|
||
92
|
||
93
|
||
94
|
||
95
|
||
96
|
||
97
|
||
98
|
||
99
|
||
100
|
||
101
|
||
102
|
||
103
|
||
104
|
||
105
|
||
106
|
||
107
|
||
108
|
||
109
|
||
110
|
||
111
|
||
112
|
||
113
|
||
114
|
||
115
|
||
116
|
||
117
|
||
118
|
||
119
|
||
120
|
||
121
|
||
122
|
||
123
|
||
124
|
||
125
|
||
126
|
||
127
|
||
128
|
||
129
|
||
130
|
||
131
|
||
132
|
||
133
|
||
134
|
||
135
|
||
136
|
||
137
|
||
138
|
||
139
|
||
140
|
||
141
|
||
142
|
||
143
|
||
144
|
||
145
|
||
146
|
||
147
|
||
148
|
||
149
|
||
150
|
||
151
|
||
152
|
||
153
|
||
154
|
||
155
|
||
156
|
||
157
|
||
158
|
||
159
|
||
160
|
||
161
|
||
162
|
||
163
|
||
164
|
||
165
|
||
166
|
||
167
|
||
168
|
||
169
|
||
170
|
||
171
|
||
172
|
||
173
|
||
174
|
||
175
|
||
176
|
||
177
|
||
178
|
||
179
|
||
180
|
||
181
|
||
182
|
||
183
|
||
184
|
||
185
|
||
186
|
||
187
|
||
188
|
||
189
|
||
190
|
||
191
|
||
192
|
||
193
|
||
194
|
||
195
|
||
196
|
||
197
|
||
</pre></td><td class="sourceCode"><pre><code class="sourceCode">#!/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</code></pre></td></tr></table></div>
|
||
<p>The process of identifying important features like the revision, release date and model of the Pi is achieved by searching a table of data. The table originates from the website <a href="http://elinux.org/RPi_HardwareHistory" class="uri">http://elinux.org/RPi_HardwareHistory</a> and has just been copied and pasted into this script. Whenever new Pis are released and the website is updated it will be necessary to refresh this table.</p>
|
||
<p>If you do this make sure that the tab characters used in this table are preserved since they are used as the field delimiter.</p>
|
||
<p>The searching of the table and display of results is performed using Awk, with a program that is stored in a temporary file and run on lines 163-181.</p>
|
||
<p>The script tries to check that it is running on a Pi in the code on lines 97-102. This works for me, but may not be universal.</p>
|
||
<p>Lines 107-109 contain commands that create temporary files and set up a mechanism to delete them using the <code>trap</code> command. The function <code>cleanup_temp</code> is used to delete the files, and that is defined on lines 76-89. I plan to talk about <code>trap</code> a forthcoming episode on the way Bash works.</p>
|
||
<p>Any improvements to this script are welcome. Please submit a pull request to the GitLab repository.</p>
|
||
<h2 id="example-output">Example output</h2>
|
||
<p>This file (<code>example_output.txt</code>) can be downloaded if desired. See the Links section below.</p>
|
||
<pre><code>$ what_pi
|
||
Revision : 0010
|
||
Release date : Q3 2014
|
||
Model : B+
|
||
PCB Revision : 1.0
|
||
Memory : 512 MB
|
||
Notes : (Mfg by Sony)
|
||
Serial no : 00000000deadbeef
|
||
|
||
Various configuration and other settings:
|
||
CPU temp=39.0'C
|
||
H264: H264=enabled
|
||
MPG2: MPG2=disabled
|
||
WVC1: WVC1=disabled
|
||
MPG4: MPG4=enabled
|
||
MJPG: MJPG=enabled
|
||
WMV9: WMV9=disabled
|
||
sdtv_mode=0
|
||
sdtv_aspect=0
|
||
|
||
Network information:
|
||
Hostname : rpi2
|
||
IP : 192.168.0.65
|
||
MAC : b8:27:eb:22:de:ad (eth0)
|
||
</code></pre>
|
||
<h2 id="links">Links</h2>
|
||
<ul>
|
||
<li>GitLab repository: <a href="https://gitlab.com/davmo/what_pi" class="uri">https://gitlab.com/davmo/what_pi</a></li>
|
||
<li>Resources to download:
|
||
<ul>
|
||
<li>The script <em><a href="hpr2496_what_pi">what_pi</a></em></li>
|
||
<li>Example output <em><a href="hpr2496_example_output.txt">example_output.txt</a></em></li>
|
||
</ul></li>
|
||
</ul>
|
||
</article>
|
||
</main>
|
||
</div>
|
||
</body>
|
||
</html>
|