├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── bluetooth-scan.sh ├── build_raspbian_sdcard.sh ├── build_ubuntu_sdcard.sh ├── customize-raspbian.sh ├── customize-ubuntu.sh ├── equality_test.sh ├── install-air-pi.sh ├── install-rpi-mjpg.sh ├── install-twython.sh ├── install-uv4l.sh ├── ip-location.py ├── ip_mailer.py ├── speedtest-ifttt.sh ├── speedtest.py ├── stockmonitor-neopixel.py ├── stockmonitor-sensehat.py ├── stockticker-ledboard.py ├── stockticker-sensehat.py └── take-photo.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # PyInstaller 26 | # Usually these files are written by a python script from a template 27 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 28 | *.manifest 29 | *.spec 30 | 31 | # Installer logs 32 | pip-log.txt 33 | pip-delete-this-directory.txt 34 | 35 | # Unit test / coverage reports 36 | htmlcov/ 37 | .tox/ 38 | .coverage 39 | .cache 40 | nosetests.xml 41 | coverage.xml 42 | 43 | # Translations 44 | *.mo 45 | *.pot 46 | 47 | # Django stuff: 48 | *.log 49 | 50 | # Sphinx documentation 51 | docs/_build/ 52 | 53 | # PyBuilder 54 | target/ 55 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: bash 2 | 3 | before_script: 4 | - curl -L "http://downloads.sourceforge.net/shunit2/shunit2-2.0.3.tgz" | tar zx 5 | 6 | script: 7 | - bash equality_test.sh 8 | 9 | notifications: 10 | email: 11 | on_failure: 12 | - always 13 | on_success: 14 | - never 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | Copyright 2014 Shawn Woodford 179 | https://github.com/swoodford 180 | 181 | Licensed under the Apache License, Version 2.0 (the "License"); 182 | you may not use this file except in compliance with the License. 183 | You may obtain a copy of the License at 184 | 185 | http://www.apache.org/licenses/LICENSE-2.0 186 | 187 | Unless required by applicable law or agreed to in writing, software 188 | distributed under the License is distributed on an "AS IS" BASIS, 189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 190 | See the License for the specific language governing permissions and 191 | limitations under the License. 192 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | raspberrypi 2 | ======= 3 | 4 | A collection of scripts for performing various tasks with a Raspberry Pi 5 | 6 | [![Build Status](https://travis-ci.org/swoodford/raspberrypi.svg?branch=master)](https://travis-ci.org/swoodford/raspberrypi) 7 | 8 | - **bluetooth-scan.sh** Install, initialize Bluetooth USB Dongle and scan for devices 9 | - **build_raspbian_sdcard.sh** Build Raspbian bootable SD card from Raspbian img file 10 | - **build_ubuntu_sdcard.sh** Build Ubuntu bootable SD card from Ubuntu img file 11 | - **customize-raspbian.sh** Setup and Customize New Raspberry Pi Raspbian Installation 12 | - **customize-ubuntu.sh** Setup and Customize New Raspberry Pi Ubuntu Installation 13 | - **install-air-pi.sh** Install the Shairport Airplay emulator for Raspberry Pi 14 | - **install-rpi-mjpg.sh** Install the Raspberry Pi camera compatible MJPG-Streamer 15 | - **install-twython.sh** Install Twython, a Twitter API Python library 16 | - **install-uv4l.sh** Install UV4L for Raspberry Pi camera 17 | - **ip-location.py** Print your IP-based geolocation coordinates 18 | - **ip_mailer.py** Email Raspberry Pi IP Address at boot using Gmail SMTP server 19 | - **speedtest-ifttt.sh** Run a speedtest and log the results to a Google sheet using IFTTT 20 | - **speedtest.py** Run a speedtest and tweet to Time Warner when slow 21 | - **stockmonitor-neopixel.py** Raspberry Pi and NeoPixel Stock Symbol Price Monitor 22 | - **stockmonitor-sensehat.py** Raspberry Pi and Sense Hat Stock Symbol Price Monitor 23 | - **stockticker-ledboard.py** Raspberry Pi and MAX7219 LED Board Stock Symbol Price Ticker 24 | - **stockticker-sensehat.py** Raspberry Pi and Sense Hat Stock Symbol Price Ticker 25 | - **take-photo.py** Take a photo from the Raspberry Pi camera 26 | -------------------------------------------------------------------------------- /bluetooth-scan.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Install Packages 4 | sudo apt-get install bluez python-gobject dbus-glib -y 5 | sudo aptitude install blueman -y 6 | 7 | # Initialize Raspberry Pi Bluetooth USB Dongle and scan for devices 8 | sudo service bluetooth restart 9 | sudo service bluetooth status 10 | /etc/init.d/bluetooth status 11 | lsusb | grep -i bluetooth 12 | sudo hciconfig hci0 reset 13 | sudo hciconfig hci0 piscan 14 | hcitool scan 15 | bluetoothctl 16 | -------------------------------------------------------------------------------- /build_raspbian_sdcard.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Script to build Raspbian bootable SD card from Raspbian img file 4 | 5 | DEBUGMODE=0 6 | 7 | # Functions 8 | 9 | # Check required commands 10 | function check_command { 11 | type -P $1 &>/dev/null || fail "Unable to find $1, please install it and run this script again." 12 | } 13 | 14 | # Alert 15 | function alert(){ 16 | tput setaf 1; echo "$*" && tput sgr0 17 | } 18 | 19 | # Fail 20 | function fail(){ 21 | tput setaf 1; echo "Failure: $*" && tput sgr0 22 | exit 1 23 | } 24 | 25 | # Pause 26 | function pause(){ 27 | read -p "Press any key to continue..." 28 | echo 29 | } 30 | 31 | # Success 32 | function success(){ 33 | tput setaf 2; echo "$*" && tput sgr0 34 | } 35 | 36 | # Unmount 37 | function unmount(){ 38 | echo "Unmounting" $DISK "..." 39 | UNMOUNT=$(diskutil unmountDisk $DISK 2>&1) 40 | if echo "$UNMOUNT" | grep -q "fail"; then 41 | fail "$UNMOUNT" 42 | exit 1 43 | fi 44 | } 45 | 46 | 47 | # Select Raspian Image 48 | function image(){ 49 | # clear 50 | echo "=================================================================================================================" 51 | success "This tool will build a Raspbian bootable SD card from an uncompressed Raspbian img file in your Downloads folder." 52 | echo "=================================================================================================================" 53 | pause 54 | 55 | RASPBIAN=$(find ~/Downloads -type f -name "*raspbian*.img" | sort -r) 56 | 57 | if [ -z "$RASPBIAN" ]; then 58 | ZIPPED=$(find ~/Downloads -type f -name "*raspbian*.zip") 59 | if [ -z "$ZIPPED" ]; then 60 | fail "Could not find any Raspbian img files in your Downloads folder." 61 | else 62 | echo "Found compressed Raspbian img:" 63 | echo "$ZIPPED" 64 | fail "Must uncompress img first." 65 | fi 66 | else 67 | NUMIMAGES=$(echo "$RASPBIAN" | wc -l) 68 | success Found $NUMIMAGES Raspbian img files in Downloads. 69 | echo 70 | # echo "List of Raspbian images found in Downloads:" 71 | success "$RASPBIAN" 72 | echo 73 | # echo Number of images found: $NUMIMAGES 74 | 75 | if [ "$NUMIMAGES" -gt "1" ]; then 76 | START=1 77 | for (( COUNT=$START; COUNT<=$NUMIMAGES; COUNT++ )) 78 | do 79 | # echo "=====================================================" 80 | # echo \#$COUNT 81 | IMAGE=$(echo "$RASPBIAN" | nl | grep -w $COUNT | cut -f2) 82 | echo "Image: "$IMAGE 83 | read -rp "Use this Raspbian img file? (y/n) " REPLY 84 | echo 85 | if [[ $REPLY =~ ^[Yy]$ ]]; then 86 | SELECTED="Y" 87 | RASPBIAN=$IMAGE 88 | if [[ $DEBUGMODE = "1" ]]; then 89 | echo Image: $IMAGE 90 | echo Raspbian: $RASPBIAN 91 | fi 92 | break 93 | fi 94 | 95 | # if [[ $REPLY =~ ^[Nn]$ ]]; then 96 | # echo 97 | # read -rp "Enter full path to Raspbian image: " REPLY 98 | # RASPBIAN=$REPLY 99 | # fi 100 | done 101 | 102 | if ! [[ $SELECTED =~ "Y" ]]; then 103 | fail "Must select at least one Raspbian img file!" 104 | fi 105 | fi 106 | fi 107 | } 108 | 109 | # Select Mounted Disk 110 | function disk(){ 111 | echo 112 | echo "=================================================================================================" 113 | success "List of mounted disks:" 114 | echo 115 | df -lH 116 | success "(The Filesystem column is the path to the disk.)" 117 | echo "=================================================================================================" 118 | # ls -fl /Volumes/ 119 | echo 120 | echo "Type the full Filesystem path to disk for your Raspberry Pi MicroSD Card:" 121 | echo "Example: /dev/disk5" 122 | read DISK 123 | if [ -z "$DISK" ]; then 124 | alert "Must enter full path to disk to format!" 125 | echo 126 | echo "Type the full Filesystem path to disk for your Raspberry Pi MicroSD Card:" 127 | echo "Example: /dev/disk5" 128 | read DISK 129 | fi 130 | if [ -z "$DISK" ]; then 131 | fail "Must enter full path to disk to format!" 132 | fi 133 | alert "=================================================================================================" 134 | alert "WARNING THE NEXT STEP WILL ERASE THE SD CARD!!!" 135 | alert "=================================================================================================" 136 | tput setaf 1; read -rp "Proceed to erase and format \"$DISK\" with Raspbian image? (y/n) " REPLY && tput sgr0 137 | echo 138 | if [[ $REPLY =~ ^[Yy]$ ]]; then 139 | unmount 140 | echo "Formatting with FAT32..." 141 | FORMAT=$(sudo diskutil eraseDisk FAT32 RASPBERRYPI MBRFormat $DISK 2>&1) 142 | if echo "$FORMAT" | grep -q "fail"; then 143 | fail "$FORMAT" 144 | exit 1 145 | fi 146 | unmount 147 | if [[ $UNMOUNT = "dd: $DISK: Resource busy" ]]; then 148 | UNMOUNT=$(sudo diskutil unmountDisk $DISK) 149 | fi 150 | if [[ $DEBUGMODE = "1" ]]; then 151 | echo 152 | echo "Raspbian Image: "; success "$RASPBIAN" 153 | echo 154 | echo "Filesystem path: "; success "$DISK" 155 | fi 156 | echo 157 | # tput setaf 1; echo "CONFIRM AND FORMAT DISK?" 158 | # pause 159 | echo "=================================================================================================" 160 | success "Installing the Raspberry Pi image to SD Card... (this may take some time)" 161 | alert "DO NOT REMOVE THE SD CARD!!!" 162 | echo "=================================================================================================" 163 | start=$(date +%s) 164 | if [[ $DEBUGMODE = "1" ]]; then 165 | echo $start 166 | pause 167 | fi 168 | DD=$(eval sudo dd bs=1m if="$RASPBIAN" of="$DISK" 2>&1) 169 | if [[ $DEBUGMODE = "1" ]]; then 170 | echo "DD is done..." 171 | fi 172 | if echo "$DD" | grep -q "unknown"; then 173 | fail "$DD" 174 | exit 1 175 | fi 176 | dur=$(echo "$(date +%s) - $start" | bc) 177 | printf "Execution time: %.2f seconds\n" $dur 178 | echo "$DD" 179 | else 180 | fail "Cancelled." 181 | fi 182 | success "Done!" 183 | osascript -e 'tell app "Terminal" to display dialog "Raspbian bootable SD card ready!"' 184 | unmount 185 | } 186 | 187 | check_command "dd" 188 | check_command "diskutil" 189 | image 190 | disk 191 | -------------------------------------------------------------------------------- /build_ubuntu_sdcard.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Script to build Ubuntu bootable SD card from file 4 | 5 | DEBUGMODE=0 6 | 7 | # Functions 8 | 9 | # Check required commands 10 | function check_command { 11 | type -P $1 &>/dev/null || fail "Unable to find $1, please install it and run this script again." 12 | } 13 | 14 | # Fail 15 | function fail(){ 16 | tput setaf 1; echo "Failure: $*" && tput sgr0 17 | exit 1 18 | } 19 | 20 | # Success 21 | function success(){ 22 | tput setaf 2; echo "$*" && tput sgr0 23 | } 24 | 25 | # Pause 26 | function pause(){ 27 | read -p "Press any key to continue..." 28 | echo 29 | } 30 | 31 | # Select Ubuntu Image 32 | function image(){ 33 | # clear 34 | echo "=======================================================================================" 35 | success "This tool will build an Ubuntu bootable SD card from img file in your Downloads folder." 36 | echo "=======================================================================================" 37 | pause 38 | 39 | 40 | Ubuntu=$(find ~/Downloads -type f -name "*ubuntu*.img" | sort -r) 41 | 42 | if [ -z "$Ubuntu" ]; then 43 | ZIPPED=$(find ~/Downloads -type f -name "*ubuntu*.zip") 44 | if [ -z "$ZIPPED" ]; then 45 | fail "Could not find any Ubuntu images in your Downloads folder." 46 | else 47 | echo "List of compressed Ubuntu images" 48 | echo "$ZIPPED" 49 | fail "Must uncompress image first." 50 | fi 51 | else 52 | NUMIMAGES=$(echo "$Ubuntu" | wc -l) 53 | success Found $NUMIMAGES Ubuntu images found in Downloads. 54 | echo 55 | echo "$Ubuntu" 56 | # echo "List of Ubuntu images found in Downloads:" 57 | success "$Ubuntu" 58 | echo 59 | 60 | if [ "$NUMIMAGES" -gt "1" ]; then 61 | START=1 62 | for (( COUNT=$START; COUNT<=$NUMIMAGES; COUNT++ )) 63 | do 64 | # echo "=====================================================" 65 | # echo \#$COUNT 66 | IMAGE=$(echo "$Ubuntu" | nl | grep -w $COUNT | cut -f2) 67 | echo "Image: "$IMAGE 68 | read -rp "Use this Ubuntu image? (y/n) " REPLY 69 | echo 70 | if [[ $REPLY =~ ^[Yy]$ ]]; then 71 | SELECTED="Y" 72 | Ubuntu=$IMAGE 73 | if [[ $DEBUGMODE = "1" ]]; then 74 | echo Image: $IMAGE 75 | echo Ubuntu: $Ubuntu 76 | fi 77 | break 78 | fi 79 | 80 | # if [[ $REPLY =~ ^[Nn]$ ]]; then 81 | # echo 82 | # read -rp "Enter full path to Ubuntu image: " REPLY 83 | # Ubuntu=$REPLY 84 | # fi 85 | done 86 | 87 | if ! [[ $SELECTED =~ "Y" ]]; then 88 | fail "Must select at least one Ubuntu image!" 89 | fi 90 | fi 91 | fi 92 | } 93 | 94 | # Select Mounted Disk 95 | function disk(){ 96 | echo 97 | echo "=================================================================================================" 98 | success "List of mounted disks:" 99 | echo 100 | df -lH 101 | success "(The Filesystem column is the path to the disk.)" 102 | echo "=================================================================================================" 103 | # ls -fl /Volumes/ 104 | echo 105 | echo "Type the full Filesystem path to disk for your Raspberry Pi MicroSD Card:" 106 | echo "Example: /dev/disk5" 107 | read DISK 108 | if [ -z "$DISK" ]; then 109 | fail "Must enter full path to disk to format!" 110 | fi 111 | echo "=================================================================================================" 112 | tput setaf 1; echo "WARNING THE NEXT STEP WILL ERASE THE DISK!!!" 113 | echo "=================================================================================================" 114 | read -rp "Proceed to erase and format \"$DISK\" with Ubuntu image? (y/n) " REPLY && tput sgr0 115 | echo 116 | if [[ $REPLY =~ ^[Yy]$ ]]; then 117 | echo "Unmounting" $DISK 118 | UNMOUNT=$(diskutil unmountDisk $DISK 2>&1) 119 | if echo "$UNMOUNT" | grep -q "fail"; then 120 | fail "$UNMOUNT" 121 | exit 1 122 | fi 123 | echo "Formatting with FAT32" 124 | FORMAT=$(sudo diskutil eraseDisk FAT32 RASPBERRYPI MBRFormat $DISK 2>&1) 125 | if echo "$FORMAT" | grep -q "fail"; then 126 | fail "$FORMAT" 127 | exit 1 128 | fi 129 | UNMOUNT=$(diskutil unmountDisk $DISK 2>&1) 130 | if echo "$UNMOUNT" | grep -q "fail"; then 131 | fail "$UNMOUNT" 132 | exit 1 133 | fi 134 | if [[ $UNMOUNT = "dd: $DISK: Resource busy" ]]; then 135 | UNMOUNT=$(diskutil unmountDisk $DISK) 136 | fi 137 | if [[ $DEBUGMODE = "1" ]]; then 138 | echo 139 | echo "Ubuntu Image: "; success "$Ubuntu" 140 | echo 141 | echo "Filesystem path: "; success "$DISK" 142 | fi 143 | echo 144 | # tput setaf 1; echo "CONFIRM AND FORMAT DISK?" 145 | # pause 146 | echo "=================================================================================================" 147 | echo "Installing the Raspberry Pi image... (this may take some time)" 148 | echo "=================================================================================================" 149 | 150 | start=$(date +%s) 151 | pause 152 | DD=$(eval sudo dd bs=1m if="$Ubuntu" of="$DISK" 2>&1) 153 | if [[ $DEBUGMODE = "1" ]]; then 154 | echo "DD is done..." 155 | fi 156 | if echo "$DD" | grep -q "unknown"; then 157 | fail "$DD" 158 | exit 1 159 | fi 160 | dur=$(echo "$(date +%s) - $start" | bc) 161 | printf "Execution time: %.2f seconds\n" $dur 162 | echo "$DD" 163 | else 164 | fail "Cancelled." 165 | fi 166 | echo "Done!" 167 | } 168 | 169 | check_command "dd" 170 | check_command "diskutil" 171 | image 172 | disk 173 | -------------------------------------------------------------------------------- /customize-raspbian.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Customize New Raspberry Pi Raspbian Installation 3 | 4 | # YOU MUST SET THESE VARIABLES FIRST 5 | id_rsa_pub="YOUR SSH PUB KEY" 6 | wep_wifi_ssid="YOUR WEP WIFI SSID" 7 | wep_wifi_password="YOUR WEP WIFI PASSWORD" 8 | gmail_user="YOUR GMAIL EMAIL ADDRESS" 9 | gmail_password="YOUR GMAIL PASSWORD" 10 | email_to="EMAIL RECIPIENT" 11 | 12 | 13 | # Pause 14 | function pause(){ 15 | read -p "Press any key to continue..." 16 | echo 17 | } 18 | 19 | # Warning 20 | echo "##################################################################" 21 | echo "This script will setup a new Raspberry Pi with Raspbian installed." 22 | echo "You should not proceed if you have already modified some settings," 23 | echo "Or if you have not configured the required variables in this file." 24 | echo "##################################################################" 25 | echo 26 | pause 27 | 28 | # Check Variables Set 29 | if [ "$id_rsa_pub" = "YOUR SSH PUB KEY" ]; then 30 | echo "You failed to configure the variables!" 31 | echo "Please edit this script before running." 32 | exit 1 33 | fi 34 | 35 | 36 | # PACKAGE UPDATES AND INSTALLATIONS 37 | sudo apt-get update 38 | sudo apt-get dist-upgrade -y 39 | sudo sync 40 | sudo apt-get install -y git ImageMagick python-setuptools cmake libssl-dev rpi-update python-dev libffi-dev libssl-dev --force-yes 41 | sudo easy_install pip 42 | sudo apt-get upgrade -y 43 | sudo pip install pyopenssl ndg-httpsclient pyasn1 44 | sudo pip install twython 45 | sudo rpi-update 46 | 47 | 48 | # CONFIG NETWORKING 49 | sudo sed -i 's/manual/dhcp/' /etc/network/interfaces 50 | 51 | 52 | # CONFIG WIFI 53 | sudo bash -c 'echo >> /etc/wpa_supplicant/wpa_supplicant.conf' 54 | sudo bash -c 'echo "network={" >> /etc/wpa_supplicant/wpa_supplicant.conf' 55 | sudo bash -c 'echo " ssid=\"REPLACE1\"" >> /etc/wpa_supplicant/wpa_supplicant.conf' 56 | sudo bash -c 'echo " psk=\"REPLACE2\"" >> /etc/wpa_supplicant/wpa_supplicant.conf' 57 | sudo bash -c 'echo "}" >> /etc/wpa_supplicant/wpa_supplicant.conf' 58 | sudo bash -c 'echo >> /etc/wpa_supplicant/wpa_supplicant.conf' 59 | sudo sed -i "s/REPLACE1/$wep_wifi_ssid/" /etc/wpa_supplicant/wpa_supplicant.conf 60 | sudo sed -i "s/REPLACE2/$wep_wifi_password/" /etc/wpa_supplicant/wpa_supplicant.conf 61 | 62 | sudo ifdown wlan0 63 | sudo ifup wlan0 64 | 65 | # SSH 66 | # Copies the contents of the id_rsa.pub file to your clipboard 67 | # pbcopy < ~/.ssh/id_rsa.pub 68 | 69 | mkdir ~/.ssh 70 | touch ~/.ssh/authorized_keys 71 | chmod 700 ~/.ssh 72 | chmod 600 ~/.ssh/authorized_keys 73 | echo $id_rsa_pub >> ~/.ssh/authorized_keys 74 | echo >> ~/.ssh/authorized_keys 75 | 76 | 77 | # SSHD CONFIG 78 | sudo bash -c 'echo >> /etc/ssh/sshd_config' 79 | sudo bash -c 'echo >> /etc/ssh/sshd_config' 80 | sudo bash -c 'echo "Match User pi" >> /etc/ssh/sshd_config' 81 | sudo bash -c 'echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config' 82 | sudo bash -c 'echo "RSAAuthentication yes" >> /etc/ssh/sshd_config' 83 | sudo bash -c 'echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config' 84 | sudo bash -c 'echo >> /etc/ssh/sshd_config' 85 | sudo bash -c 'echo "Match User root" >> /etc/ssh/sshd_config' 86 | sudo bash -c 'echo "PasswordAuthentication no" >> /etc/ssh/sshd_config' 87 | 88 | # sudo service ssh restart 89 | 90 | 91 | # BASHRC 92 | echo >> ~/.bashrc 93 | echo "export CLICOLOR=1" >> ~/.bashrc 94 | echo "export LSCOLORS=eafxcxdxbxegedabagacad" >> ~/.bashrc 95 | echo "export GREP_OPTIONS='--color=auto'" >> ~/.bashrc 96 | echo >> ~/.bashrc 97 | echo "alias ll='ls -lah --color'" >> ~/.bashrc 98 | source ~/.bashrc 99 | 100 | 101 | # IP MAILER 102 | touch ~/ip_mailer.py 103 | chmod +x ~/ip_mailer.py 104 | 105 | echo "#!/usr/bin/python" >> ~/ip_mailer.py 106 | echo "# Script to email Raspberry Pi IP Address at boot using Gmail SMTP" >> ~/ip_mailer.py 107 | echo "" >> ~/ip_mailer.py 108 | echo "import subprocess" >> ~/ip_mailer.py 109 | echo "import smtplib" >> ~/ip_mailer.py 110 | echo "from email.mime.text import MIMEText" >> ~/ip_mailer.py 111 | echo "import datetime" >> ~/ip_mailer.py 112 | echo "" >> ~/ip_mailer.py 113 | echo "# Change to your own account information" >> ~/ip_mailer.py 114 | echo "to = '$email_to'" >> ~/ip_mailer.py 115 | echo "gmail_user = '$gmail_user'" >> ~/ip_mailer.py 116 | echo "gmail_password = '$gmail_password'" >> ~/ip_mailer.py 117 | echo "smtpserver = smtplib.SMTP('smtp.gmail.com', 587)" >> ~/ip_mailer.py 118 | echo "smtpserver.ehlo()" >> ~/ip_mailer.py 119 | echo "smtpserver.starttls()" >> ~/ip_mailer.py 120 | echo "smtpserver.ehlo" >> ~/ip_mailer.py 121 | echo "smtpserver.login(gmail_user, gmail_password)" >> ~/ip_mailer.py 122 | echo "today = datetime.date.today()" >> ~/ip_mailer.py 123 | echo "" >> ~/ip_mailer.py 124 | echo "# Very Linux Specific" >> ~/ip_mailer.py 125 | echo "arg = 'ip route list'" >> ~/ip_mailer.py 126 | echo "p = subprocess.Popen(arg, shell=True, stdout=subprocess.PIPE)" >> ~/ip_mailer.py 127 | echo "data = p.communicate()" >> ~/ip_mailer.py 128 | echo "split_data = data[0].split()" >> ~/ip_mailer.py 129 | echo "ipaddr = split_data[split_data.index('src') + 1]" >> ~/ip_mailer.py 130 | echo "my_ip = 'Your IP is %s' % ipaddr" >> ~/ip_mailer.py 131 | echo "msg = MIMEText(my_ip)" >> ~/ip_mailer.py 132 | echo "msg['Subject'] = 'IP For RaspberryPi on %s' % today.strftime('%b %d %Y')" >> ~/ip_mailer.py 133 | echo "msg['From'] = gmail_user" >> ~/ip_mailer.py 134 | echo "msg['To'] = to" >> ~/ip_mailer.py 135 | echo "smtpserver.sendmail(gmail_user, [to], msg.as_string())" >> ~/ip_mailer.py 136 | echo "smtpserver.quit()" >> ~/ip_mailer.py 137 | echo "" >> ~/ip_mailer.py 138 | 139 | 140 | # ENABLE CAMERA ON BOOT 141 | sudo sed -i '/# By default this script does nothing./ a\ 142 | \ 143 | sudo modprobe bcm2835-v4l2' /etc/rc.local 144 | 145 | 146 | # RUN IP MAILER ON BOOT 147 | sudo sed -i '/printf "My IP address is %s\\n" "$_IP"/ a\ 148 | python /home/pi/ip_mailer.py' /etc/rc.local 149 | 150 | 151 | echo "Customization completed! Rebooting Raspberry Pi..." 152 | pause 153 | 154 | sudo reboot 155 | -------------------------------------------------------------------------------- /customize-ubuntu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Customize New Ubuntu on Raspberry Pi 3 | 4 | # YOU MUST SET THESE VARIABLES FIRST 5 | id_rsa_pub="YOUR SSH PUB KEY" 6 | wep_wifi_ssid="YOUR WEP WIFI SSID" 7 | wep_wifi_password="YOUR WEP WIFI PASSWORD" 8 | gmail_user="YOUR GMAIL EMAIL ADDRESS" 9 | gmail_password="YOUR GMAIL PASSWORD" 10 | email_to="EMAIL RECIPIENT" 11 | 12 | 13 | # Pause 14 | function pause(){ 15 | read -p "Press any key to continue..." 16 | echo 17 | } 18 | 19 | # Warning 20 | echo "##################################################################" 21 | echo "This script will setup a new Raspberry Pi with Raspbian installed." 22 | echo "You should not proceed if you have already modified some settings," 23 | echo "Or if you have not configured the required variables in this file." 24 | echo "##################################################################" 25 | echo 26 | pause 27 | 28 | # Check Variables Set 29 | if [ "$id_rsa_pub" = "YOUR SSH PUB KEY" ]; then 30 | echo "You failed to configure the variables!" 31 | echo "Please edit this script before running." 32 | exit 1 33 | fi 34 | 35 | 36 | # PACKAGE UPDATES AND INSTALLATIONS 37 | sudo apt-get update 38 | sudo apt-get install -y git ImageMagick openssh-server wireless-tools wpasupplicant python-setuptools cmake libssl-dev --force-yes 39 | sudo easy_install pip 40 | sudo apt-get upgrade -y 41 | 42 | 43 | # CONFIG NETWORKING 44 | sudo sed -i 's/manual/dhcp/' /etc/network/interfaces 45 | 46 | 47 | # CONFIG WIFI 48 | touch /etc/wpa_supplicant/wpa_supplicant.conf 49 | bash -c 'echo >> /etc/wpa_supplicant/wpa_supplicant.conf' 50 | bash -c 'echo "network={" >> /etc/wpa_supplicant/wpa_supplicant.conf' 51 | bash -c 'echo " ssid=\"REPLACE1\"" >> /etc/wpa_supplicant/wpa_supplicant.conf' 52 | bash -c 'echo " psk=\"REPLACE2\"" >> /etc/wpa_supplicant/wpa_supplicant.conf' 53 | bash -c 'echo "}" >> /etc/wpa_supplicant/wpa_supplicant.conf' 54 | bash -c 'echo >> /etc/wpa_supplicant/wpa_supplicant.conf' 55 | sed -i "s/REPLACE1/$wep_wifi_ssid/" /etc/wpa_supplicant/wpa_supplicant.conf 56 | sed -i "s/REPLACE2/$wep_wifi_password/" /etc/wpa_supplicant/wpa_supplicant.conf 57 | 58 | ifconfig wlan0 down 59 | ifconfig wlan0 up 60 | # iwconfig 61 | # iwlist scan 62 | # wpa_passphrase 63 | 64 | 65 | /etc/network/interfaces 66 | 67 | # SSH 68 | mkdir ~/.ssh 69 | touch ~/.ssh/authorized_keys 70 | chmod 700 ~/.ssh 71 | chmod 600 ~/.ssh/authorized_keys 72 | echo $id_rsa_pub >> ~/.ssh/authorized_keys 73 | echo >> ~/.ssh/authorized_keys 74 | 75 | 76 | # SSHD CONFIG 77 | sudo bash -c 'echo >> /etc/ssh/sshd_config' 78 | sudo bash -c 'echo >> /etc/ssh/sshd_config' 79 | sudo bash -c 'echo "Match User ubuntu" >> /etc/ssh/sshd_config' 80 | sudo bash -c 'echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config' 81 | sudo bash -c 'echo "RSAAuthentication yes" >> /etc/ssh/sshd_config' 82 | sudo bash -c 'echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config' 83 | sudo bash -c 'echo >> /etc/ssh/sshd_config' 84 | sudo bash -c 'echo "Match User root" >> /etc/ssh/sshd_config' 85 | sudo bash -c 'echo "PasswordAuthentication no" >> /etc/ssh/sshd_config' 86 | 87 | 88 | # BASHRC 89 | echo >> ~/.bashrc 90 | echo "export CLICOLOR=1" >> ~/.bashrc 91 | echo "export LSCOLORS=eafxcxdxbxegedabagacad" >> ~/.bashrc 92 | echo "export GREP_OPTIONS='--color=auto'" >> ~/.bashrc 93 | echo >> ~/.bashrc 94 | echo "alias ll='ls -lah --color'" >> ~/.bashrc 95 | source ~/.bashrc 96 | 97 | 98 | # IP MAILER 99 | touch ~/ip_mailer.py 100 | chmod +x ~/ip_mailer.py 101 | 102 | echo "#!/usr/bin/python" >> ~/ip_mailer.py 103 | echo "# Script to email Raspberry Pi IP Address at boot using Gmail SMTP" >> ~/ip_mailer.py 104 | echo "" >> ~/ip_mailer.py 105 | echo "import subprocess" >> ~/ip_mailer.py 106 | echo "import smtplib" >> ~/ip_mailer.py 107 | echo "from email.mime.text import MIMEText" >> ~/ip_mailer.py 108 | echo "import datetime" >> ~/ip_mailer.py 109 | echo "" >> ~/ip_mailer.py 110 | echo "# Change to your own account information" >> ~/ip_mailer.py 111 | echo "to = '$email_to'" >> ~/ip_mailer.py 112 | echo "gmail_user = '$gmail_user'" >> ~/ip_mailer.py 113 | echo "gmail_password = '$gmail_password'" >> ~/ip_mailer.py 114 | echo "smtpserver = smtplib.SMTP('smtp.gmail.com', 587)" >> ~/ip_mailer.py 115 | echo "smtpserver.ehlo()" >> ~/ip_mailer.py 116 | echo "smtpserver.starttls()" >> ~/ip_mailer.py 117 | echo "smtpserver.ehlo" >> ~/ip_mailer.py 118 | echo "smtpserver.login(gmail_user, gmail_password)" >> ~/ip_mailer.py 119 | echo "today = datetime.date.today()" >> ~/ip_mailer.py 120 | echo "" >> ~/ip_mailer.py 121 | echo "# Very Linux Specific" >> ~/ip_mailer.py 122 | echo "arg = 'ip route list'" >> ~/ip_mailer.py 123 | echo "p = subprocess.Popen(arg, shell=True, stdout=subprocess.PIPE)" >> ~/ip_mailer.py 124 | echo "data = p.communicate()" >> ~/ip_mailer.py 125 | echo "split_data = data[0].split()" >> ~/ip_mailer.py 126 | echo "ipaddr = split_data[split_data.index('src') + 1]" >> ~/ip_mailer.py 127 | echo "my_ip = 'Your IP is %s' % ipaddr" >> ~/ip_mailer.py 128 | echo "msg = MIMEText(my_ip)" >> ~/ip_mailer.py 129 | echo "msg['Subject'] = 'IP For RaspberryPi on %s' % today.strftime('%b %d %Y')" >> ~/ip_mailer.py 130 | echo "msg['From'] = gmail_user" >> ~/ip_mailer.py 131 | echo "msg['To'] = to" >> ~/ip_mailer.py 132 | echo "smtpserver.sendmail(gmail_user, [to], msg.as_string())" >> ~/ip_mailer.py 133 | echo "smtpserver.quit()" >> ~/ip_mailer.py 134 | echo "" >> ~/ip_mailer.py 135 | 136 | 137 | # RUN IP MAILER ON BOOT 138 | sudo sed -i '/printf "My IP address is %s\\n" "$_IP"/ a\ 139 | python /home/pi/ip_mailer.py' /etc/rc.local 140 | 141 | 142 | 143 | echo "Customization completed! Rebooting Raspberry Pi..." 144 | pause 145 | 146 | sudo reboot now 147 | -------------------------------------------------------------------------------- /equality_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | testEquality() { 4 | assertEquals 1 1 5 | } 6 | 7 | . shunit2-2.0.3/src/shell/shunit2 -------------------------------------------------------------------------------- /install-air-pi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script will install the Shairport Airplay emulator for Raspberry Pi 3 | 4 | # Install deps 5 | sudo apt-get install -y git libao-dev libssl-dev libcrypt-openssl-rsa-perl libio-socket-inet6-perl libwww-perl avahi-utils libmodule-build-perl libavahi-client-dev libasound2-dev libpulse-dev 6 | 7 | # Install perl net sdp 8 | git clone https://github.com/njh/perl-net-sdp.git perl-net-sdp 9 | cd perl-net-sdp 10 | perl Build.PL 11 | sudo ./Build 12 | sudo ./Build test 13 | sudo ./Build install 14 | cd ~ 15 | 16 | # Install shairport 17 | git clone git@github.com:abrasive/shairport.git 18 | cd shairport 19 | ./configure 20 | make 21 | 22 | # Optionally install it to run at boot 23 | sudo make install 24 | cp shairport.init.sample /etc/init.d/shairport 25 | cd /etc/init.d 26 | chmod a+x shairport 27 | update-rc.d shairport defaults 28 | echo "change DAEMON_ARGS to -w \$PIDFILE -a AirPi" 29 | read -p "Press any key to continue..." 30 | sudo nano shairport 31 | 32 | 33 | # Start up Airplay 34 | ./shairport -a AirPi & 35 | 36 | echo "Airplay started as device: AirPi" -------------------------------------------------------------------------------- /install-rpi-mjpg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script will install the Raspberry Pi camera compatible MJPG-Streamer 3 | 4 | # Install deps 5 | sudo apt-get install -y libjpeg8-dev cmake 6 | 7 | # Download mjpg-streamer with raspicam plugin 8 | git clone https://github.com/jacksonliam/mjpg-streamer.git ~/mjpg-streamer 9 | 10 | # Change directory 11 | cd ~/mjpg-streamer/mjpg-streamer-experimental 12 | 13 | # Compile 14 | make clean all 15 | 16 | # Install 17 | sudo cp mjpg_streamer /usr/local/bin 18 | sudo cp input_raspicam.so output_http.so /usr/local/lib 19 | sudo cp www/stream_simple.html /var/www/index.html 20 | 21 | # Begin streaming 22 | /usr/local/bin/./mjpg_streamer -i "/usr/local/lib/input_raspicam.so -fps 15 -q 75 -x 1440 -y 1280 -vf -hf" -o "/usr/local/lib/output_http.so -p 9000 -w /var/www" & 23 | 24 | # View stream 25 | IP=$(hostname -I | rev | cut -c 2- | rev) 26 | echo "You can view your stream by browsing to http://$IP:9000" -------------------------------------------------------------------------------- /install-twython.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script installs Twython on Raspberry Pi 3 | # https://github.com/ryanmcgrath/twython 4 | 5 | sudo apt-get update 6 | sudo apt-get upgrade 7 | sudo apt-get install python-dev python-setuptools libffi-dev libssl-dev -y 8 | sudo easy_install pip 9 | sudo pip install pyopenssl ndg-httpsclient pyasn1 10 | sudo pip install twython 11 | 12 | echo "Twython Installed." 13 | -------------------------------------------------------------------------------- /install-uv4l.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script will install UV4L for Raspberry Pi camera 3 | 4 | # Get key 5 | wget http://www.linux-projects.org/listing/uv4l_repo/lrkey.asc && sudo apt-key add ./lrkey.asc 6 | 7 | # Add repo 8 | sudo bash -c 'echo "deb http://www.linux-projects.org/listing/uv4l_repo/raspbian/ wheezy main" >> /etc/apt/sources.list' 9 | 10 | # Update firmware 11 | sudo rpi-update 12 | 13 | # Install deps 14 | sudo apt-get update 15 | sudo apt-get install -y uv4l uv4l-raspicam uv4l-raspicam-extras uv4l-server 16 | 17 | # Start uv4l_raspicam 18 | sudo service uv4l_raspicam start 19 | 20 | # View stream 21 | IP=$(hostname -I | rev | cut -c 2- | rev) 22 | echo "You can view your stream by browsing to http://$IP:8080" -------------------------------------------------------------------------------- /ip-location.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This script will print your ip-based geolocation coordinates 4 | 5 | import sys 6 | import os 7 | 8 | # Get geolocation using IP address 9 | getlat = 'curl -s http://whatismycountry.com/ | sed -n \'s/.*Coordinates \\(.*\\)<.*/\\1/p\' | cut -d \' \' -f1' 10 | getlong = 'curl -s http://whatismycountry.com/ | sed -n \'s/.*Coordinates \\(.*\\)<.*/\\1/p\' | cut -d \' \' -f2' 11 | 12 | lat = os.popen(getlat).readline() 13 | long = os.popen(getlong).readline() 14 | 15 | lat = lat.strip() 16 | long = long.strip() 17 | 18 | print lat 19 | print long 20 | -------------------------------------------------------------------------------- /ip_mailer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Script to email Raspberry Pi IP Address at boot using Gmail SMTP 3 | 4 | import subprocess 5 | import smtplib 6 | # import socket 7 | from email.mime.text import MIMEText 8 | import datetime 9 | 10 | # Change to your own account information 11 | to = 'me@example.com' 12 | gmail_user = 'test@gmail.com' 13 | gmail_password = 'yourpassword' 14 | smtpserver = smtplib.SMTP('smtp.gmail.com', 587) 15 | smtpserver.ehlo() 16 | smtpserver.starttls() 17 | smtpserver.ehlo 18 | smtpserver.login(gmail_user, gmail_password) 19 | today = datetime.date.today() 20 | 21 | # Very Linux Specific 22 | arg = 'ip route list' 23 | p = subprocess.Popen(arg, shell=True, stdout=subprocess.PIPE) 24 | data = p.communicate() 25 | split_data = data[0].split() 26 | ipaddr = split_data[split_data.index('src') + 1] 27 | my_ip = 'ssh pi@%s' % ipaddr 28 | msg = MIMEText(my_ip) 29 | msg['Subject'] = 'IP For RaspberryPi on %s' % today.strftime('%b %d %Y') 30 | msg['From'] = gmail_user 31 | msg['To'] = to 32 | smtpserver.sendmail(gmail_user, [to], msg.as_string()) 33 | smtpserver.quit() 34 | -------------------------------------------------------------------------------- /speedtest-ifttt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ########################################################################### 3 | # Originally written by: Henrik Bengtsson, 2014 4 | # https://github.com/HenrikBengtsson/speedtest-cli-extras 5 | # Modified to use IFTTT by: Alasdair Allan, 2015 6 | # License: GPL (>= 2.1) [http://www.gnu.org/licenses/gpl.html] 7 | ########################################################################### 8 | 9 | # Character for separating values 10 | # (commas are not safe, because some servers return speeds with commas) 11 | sep=";" 12 | 13 | # Temporary file holding speedtest-cli output 14 | user=$USER 15 | if test -z $user; then 16 | user=$USERNAME 17 | fi 18 | log=/tmp/$user/speedtest-csv.log 19 | 20 | # Local functions 21 | function str_extract() { 22 | pattern=$1 23 | # Extract 24 | res=`grep "$pattern" $log | sed "s/$pattern//g"` 25 | # Drop trailing ... 26 | res=`echo $res | sed 's/[.][.][.]//g'` 27 | # Trim 28 | res=`echo $res | sed 's/^ *//g' | sed 's/ *$//g'` 29 | echo $res 30 | } 31 | 32 | # Display header? 33 | if test "$1" = "--header"; then 34 | start="start" 35 | stop="stop" 36 | from="from" 37 | from_ip="from_ip" 38 | server="server" 39 | server_dist="server_dist" 40 | server_ping="server_ping" 41 | download="download" 42 | upload="upload" 43 | share_url="share_url" 44 | else 45 | mkdir -p `dirname $log` 46 | 47 | start=`date +"%Y-%m-%d %H:%M:%S"` 48 | 49 | if test -n "$SPEEDTEST_CSV_SKIP" && test -f "$log"; then 50 | # Reuse existing results (useful for debugging) 51 | 1>&2 echo "** Reusing existing results: $log" 52 | else 53 | # Query Speedtest 54 | /usr/local/bin/speedtest-cli --share > $log 55 | fi 56 | 57 | stop=`date +"%Y-%m-%d %H:%M:%S"` 58 | 59 | # Parse 60 | from=`str_extract "Testing from "` 61 | from_ip=`echo $from | sed 's/.*(//g' | sed 's/).*//g'` 62 | from=`echo $from | sed 's/ (.*//g'` 63 | 64 | server=`str_extract "Hosted by "` 65 | server_ping=`echo $server | sed 's/.*: //g'` 66 | server=`echo $server | sed 's/: .*//g'` 67 | server_dist=`echo $server | sed 's/.*\\[//g' | sed 's/\\].*//g'` 68 | server=`echo $server | sed 's/ \\[.*//g'` 69 | 70 | download=`str_extract "Download: "` 71 | upload=`str_extract "Upload: "` 72 | share_url=`str_extract "Share results: "` 73 | fi 74 | 75 | # Standardize units? 76 | if test "$1" = "--standardize"; then 77 | download=`echo $download | sed 's/Mbits/Mbit/'` 78 | upload=`echo $upload | sed 's/Mbits/Mbit/'` 79 | fi 80 | 81 | # Send to IFTTT 82 | secret_key="SECRET_KEY" 83 | value1=`echo $server_ping | cut -d" " -f1` 84 | value2=`echo $download | cut -d" " -f1` 85 | value3=`echo $upload | cut -d" " -f1` 86 | json="{\"value1\":\"${value1}\",\"value2\":\"${value2}\",\"value3\":\"${value3}\"}" 87 | curl -X POST -H "Content-Type: application/json" -d "${json}" https://maker.ifttt.com/trigger/speedtest/with/key/${secret_key} -------------------------------------------------------------------------------- /speedtest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # http://www.pcworld.com/article/3027446/hardware/irate-comcast-subscriber-turns-raspberry-pi-into-a-watchdog-for-slow-internet-speeds.html 4 | # http://pastebin.com/WMEh802V 5 | # https://github.com/sivel/speedtest-cli 6 | # https://twitter.com/A_Comcast_User 7 | 8 | # Requires sudo pip install twitter 9 | # DO NOT sudo pip install python-twitter 10 | 11 | import csv 12 | import datetime 13 | import os 14 | # import sys 15 | import time 16 | 17 | import twitter 18 | 19 | 20 | def test(): 21 | 22 | # Run speedtest-cli 23 | print 'Running speedtest...' 24 | a = os.popen("python /usr/local/bin/speedtest-cli --simple").read() 25 | print 'Speedtest completed:' 26 | # Split the 3 line result (ping,down,up) 27 | lines = a.split('\n') 28 | print a 29 | ts = time.time() 30 | date = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') 31 | # If speedtest could not connect set the speeds to 0 32 | if "Cannot" in a: 33 | p = 100 34 | d = 0 35 | u = 0 36 | # Extract the values for ping down and up values 37 | else: 38 | p = lines[0][6:11] 39 | d = lines[1][10:14] 40 | u = lines[2][8:12] 41 | print date, p, d, u 42 | # Save the data to file for local network plotting 43 | out_file = open('/home/pi/speedtest.csv', 'a') 44 | writer = csv.writer(out_file) 45 | writer.writerow((ts * 1000, p, d, u)) 46 | out_file.close() 47 | 48 | # Twitter Credentials 49 | token = "" 50 | token_key = "" 51 | con_sec = "" 52 | con_sec_key = "" 53 | 54 | my_auth = twitter.OAuth(token, token_key, con_sec, con_sec_key) 55 | twit = twitter.Twitter(auth=my_auth) 56 | 57 | # Try to tweet if speedtest couldnt even connect. Probably wont work if the internet is down 58 | if "Cannot" in a: 59 | print "Internet seems to be down." 60 | try: 61 | tweet = "Hey @TWC @TWC_Help why is my #internet #down? I pay for 100 down\\10 up in #Westchester #NY? #twcoutage #TWC" 62 | twit.statuses.update(status=tweet) 63 | except: 64 | pass 65 | 66 | # Tweet if down speed is less than whatever I set 67 | elif eval(d) < 100: 68 | print "Tweeting slow bandwidth." 69 | try: 70 | # I know there must be a better way than to do (str(int(eval()))) 71 | tweet = "Hey @TWC why is my #internet #speed " + str(int(eval(d))) + " down\\" + str(int(eval(u))) + " up when I pay for 100 down\\10 up in #Westchester #NY? @TWC_Help @TWC_NYNJ #TWC #slow #speedtest" 72 | twit.statuses.update(status=tweet) 73 | except Exception, e: 74 | print str(e) 75 | pass 76 | return 77 | 78 | if __name__ == '__main__': 79 | test() 80 | print 'Completed!' 81 | -------------------------------------------------------------------------------- /stockmonitor-neopixel.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Raspberry Pi and NeoPixel Stock Symbol Price Monitor LEDs 4 | # A simple stock ticker price change monitor of today's positive or negative change using an Adafruit NeoPixel RGB LED Strip 5 | # Shows a full red/green solid color 1x8 matrix 6 | 7 | import datetime 8 | import time 9 | import ystockquote 10 | import atexit 11 | import sys 12 | import os 13 | import urllib2 14 | 15 | from socket import error as SocketError 16 | import errno 17 | 18 | from decimal import * 19 | from neopixel import * 20 | 21 | debug = 0 22 | 23 | # Stock quote configuration: 24 | tickerSymbol = 'AAPL' 25 | 26 | # LED strip configuration: 27 | LED_COUNT = 8 # Number of LED pixels. 28 | LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!). 29 | LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) 30 | LED_DMA = 4 # DMA channel to use for generating signal (try 5) 31 | LED_BRIGHTNESS = 10 # Set to 0 for darkest and 255 for brightest 32 | LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) 33 | 34 | 35 | # Define functions which animate LEDs in various ways. 36 | 37 | def solidColor(strip, color): 38 | for i in range(strip.numPixels()): 39 | strip.setPixelColor(i, color) 40 | strip.show() 41 | 42 | def lightsOut(): 43 | # Turn off all the LEDs. 44 | if debug == 1: 45 | print ('Turning off all LEDs.') 46 | 47 | strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS) 48 | strip.begin() 49 | 50 | for i in range(strip.numPixels()): 51 | strip.setPixelColor(i, 0) 52 | strip.show() 53 | 54 | def marketClosed(): 55 | print "Stock Market Closed.", now 56 | lightsOut() 57 | time.sleep(60) 58 | 59 | atexit.register(lightsOut) 60 | 61 | 62 | 63 | if debug == 1: 64 | allInfo = ystockquote.get_all(tickerSymbol) 65 | print allInfo 66 | # quote = ystockquote.get_change(tickerSymbol) 67 | # print quote 68 | 69 | # print tickerSymbol + " Price = " + allInfo["price"] 70 | # print tickerSymbol + " Change = " + allInfo["change"] 71 | # print allInfo["change"] 72 | 73 | # print allInfo 74 | 75 | getcontext().prec = 8 76 | 77 | def getQuote(change): 78 | if debug == 1: 79 | print "Function getQuote" 80 | 81 | try: 82 | change = ystockquote.get_change(tickerSymbol) 83 | except urllib2.HTTPError as err: 84 | if err.code == 404: 85 | print "404 ERROR" 86 | else: 87 | print "err.code: ", err.code 88 | # pass 89 | except SocketError as err: 90 | if err.errno == errno.ECONNRESET: 91 | print "Connection reset by peer." 92 | pass 93 | # price = ystockquote.get_price(tickerSymbol) 94 | 95 | while change == 'N/A': 96 | print "ERROR: NO PRICE CHANGE DATA!" 97 | time.sleep(60) 98 | change = ystockquote.get_change(tickerSymbol) 99 | 100 | changedecimal = Decimal(change) 101 | # pricedecimal = Decimal(price) 102 | # changedecimal = 0 103 | print "$ Change: ", changedecimal 104 | # print pricedecimal 105 | 106 | # lastclose = Decimal(pricedecimal) - Decimal(changedecimal) 107 | 108 | # print lastclose 109 | 110 | # Negative 111 | if changedecimal < 0: 112 | LED_BRIGHTNESS = abs(int(round(100 * changedecimal))) 113 | if LED_BRIGHTNESS > 255: 114 | LED_BRIGHTNESS = 255 115 | if debug == 1: 116 | print "Brightness: ", LED_BRIGHTNESS 117 | strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS) 118 | strip.begin() 119 | # Colors: GREEN, RED, BLUE 120 | solidColor(strip, Color(0, 255, 0)) 121 | 122 | # Positive 123 | if changedecimal > 0: 124 | LED_BRIGHTNESS = int(round(100 * changedecimal)) 125 | if LED_BRIGHTNESS > 255: 126 | LED_BRIGHTNESS = 255 127 | if debug == 1: 128 | print "Brightness: ", LED_BRIGHTNESS 129 | strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS) 130 | strip.begin() 131 | # Colors: GREEN, RED, BLUE 132 | solidColor(strip, Color(255, 0, 0)) 133 | 134 | # Zero 135 | if changedecimal == 0: 136 | if debug == 1: 137 | print "Zero Change!" 138 | LED_BRIGHTNESS = 10 139 | strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS) 140 | strip.begin() 141 | strip.setPixelColor(0, Color(0, 255, 0)) 142 | strip.setPixelColor(1, Color(255, 0, 0)) 143 | strip.setPixelColor(2, Color(0, 255, 0)) 144 | strip.setPixelColor(3, Color(255, 0, 0)) 145 | strip.setPixelColor(4, Color(0, 255, 0)) 146 | strip.setPixelColor(5, Color(255, 0, 0)) 147 | strip.setPixelColor(6, Color(0, 255, 0)) 148 | strip.setPixelColor(7, Color(255, 0, 0)) 149 | strip.show() 150 | 151 | time.sleep(1) 152 | 153 | # Main program logic follows: 154 | if __name__ == '__main__': 155 | 156 | try: 157 | while True: 158 | now = datetime.datetime.now() 159 | # print now 160 | 161 | # Between Monday - Friday 162 | if 0 <= now.weekday() <= 5: 163 | if debug == 1: 164 | print "Weekday: ", now.weekday() 165 | # print now.hour 166 | 167 | # Between 9AM - 5PM 168 | if now.hour == 9: 169 | if debug == 1: 170 | print "Hour 9AM" 171 | if now.minute >= 30: 172 | if debug == 1: 173 | print "Minute 30 or later" 174 | if 9 <= now.hour <= 17: 175 | # print "Hour: ", now.hour 176 | # print now.time() 177 | 178 | if debug == 1: 179 | print "Calling function getQuote" 180 | 181 | getQuote(0) 182 | 183 | else: 184 | marketClosed() 185 | 186 | else: 187 | if 9 <= now.hour <= 15: 188 | if debug == 1: 189 | print "Hour between 10AM-4PM" 190 | # print "Hour: ", now.hour 191 | # print now.time() 192 | 193 | if debug == 1: 194 | print "Calling function getQuote" 195 | 196 | getQuote(0) 197 | 198 | else: 199 | marketClosed() 200 | 201 | else: 202 | marketClosed() 203 | 204 | except KeyboardInterrupt: 205 | lightsOut() 206 | print ' - Exiting' 207 | try: 208 | sys.exit(0) 209 | except SystemExit: 210 | os._exit(0) 211 | -------------------------------------------------------------------------------- /stockmonitor-sensehat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Raspberry Pi and Sense Hat Stock Symbol Price Monitor 4 | # A simple stock ticker price change monitor of today's positive or negative change using the Sense Hat 5 | # Shows a full red/green solid color 8x8 matrix 6 | 7 | import datetime 8 | import time 9 | import ystockquote 10 | import atexit 11 | import sys 12 | import os 13 | import urllib2 14 | 15 | from socket import error as SocketError 16 | import errno 17 | 18 | from decimal import * 19 | 20 | from sense_hat import SenseHat 21 | 22 | sense = SenseHat() 23 | 24 | debug = 0 25 | 26 | # Stock quote configuration: 27 | tickerSymbol = 'AAPL' 28 | 29 | 30 | # Define functions which animate LEDs in various ways. 31 | 32 | def lightsOut(): 33 | # Turn off all the LEDs. 34 | if debug == 1: 35 | print ('Turning off all LEDs.') 36 | 37 | sense.clear() 38 | 39 | def marketClosed(): 40 | print "Stock Market Closed.", now 41 | lightsOut() 42 | time.sleep(60) 43 | 44 | atexit.register(lightsOut) 45 | 46 | if debug == 1: 47 | allInfo = ystockquote.get_all(tickerSymbol) 48 | print allInfo 49 | # quote = ystockquote.get_change(tickerSymbol) 50 | # print quote 51 | 52 | # print tickerSymbol + " Price = " + allInfo["price"] 53 | # print tickerSymbol + " Change = " + allInfo["change"] 54 | # print allInfo["change"] 55 | 56 | # print allInfo 57 | 58 | getcontext().prec = 8 59 | 60 | def getQuote(change): 61 | if debug == 1: 62 | print "Function getQuote" 63 | 64 | try: 65 | change = ystockquote.get_change(tickerSymbol) 66 | except urllib2.HTTPError as err: 67 | if err.code == 404: 68 | print "404 ERROR" 69 | else: 70 | print "err.code: ", err.code 71 | # pass 72 | except SocketError as err: 73 | if err.errno == errno.ECONNRESET: 74 | print "Connection reset by peer." 75 | pass 76 | # price = ystockquote.get_price(tickerSymbol) 77 | 78 | while change == 'N/A': 79 | print "ERROR: NO PRICE CHANGE DATA!" 80 | time.sleep(60) 81 | change = ystockquote.get_change(tickerSymbol) 82 | 83 | changedecimal = Decimal(change) 84 | # pricedecimal = Decimal(price) 85 | # changedecimal = 0 86 | print "$ Change: ", changedecimal 87 | # print pricedecimal 88 | 89 | # lastclose = Decimal(pricedecimal) - Decimal(changedecimal) 90 | 91 | # print lastclose 92 | 93 | # Negative 94 | if changedecimal < 0: 95 | LED_BRIGHTNESS = abs(int(round(100 * changedecimal))) 96 | if LED_BRIGHTNESS > 255: 97 | LED_BRIGHTNESS = 255 98 | if LED_BRIGHTNESS < 50: 99 | LED_BRIGHTNESS = 50 100 | if debug == 1: 101 | print "Brightness: ", LED_BRIGHTNESS 102 | sense.clear([LED_BRIGHTNESS, 0, 0]) 103 | 104 | # Positive 105 | if changedecimal > 0: 106 | LED_BRIGHTNESS = int(round(100 * changedecimal)) 107 | if LED_BRIGHTNESS > 255: 108 | LED_BRIGHTNESS = 255 109 | if LED_BRIGHTNESS < 50: 110 | LED_BRIGHTNESS = 50 111 | if debug == 1: 112 | print "Brightness: ", LED_BRIGHTNESS 113 | sense.clear([0, LED_BRIGHTNESS, 0]) 114 | 115 | # Zero 116 | if changedecimal == 0: 117 | if debug == 1: 118 | print "Zero Change!" 119 | sense.clear([50, 50, 50]) 120 | 121 | time.sleep(1) 122 | 123 | # Main program logic follows: 124 | if __name__ == '__main__': 125 | 126 | try: 127 | while True: 128 | now = datetime.datetime.now() 129 | # print now 130 | 131 | # Between Monday - Friday 132 | if 0 <= now.weekday() <= 5: 133 | if debug == 1: 134 | print "Weekday: ", now.weekday() 135 | # print now.hour 136 | 137 | # Between 9AM - 5PM 138 | if now.hour == 9: 139 | if debug == 1: 140 | print "Hour 9AM" 141 | if now.minute >= 30: 142 | if debug == 1: 143 | print "Minute 30 or later" 144 | if 9 <= now.hour <= 17: 145 | # print "Hour: ", now.hour 146 | # print now.time() 147 | 148 | if debug == 1: 149 | print "Calling function getQuote" 150 | 151 | getQuote(0) 152 | 153 | else: 154 | marketClosed() 155 | 156 | else: 157 | if 9 <= now.hour <= 15: 158 | if debug == 1: 159 | print "Hour between 10AM-4PM" 160 | # print "Hour: ", now.hour 161 | # print now.time() 162 | 163 | if debug == 1: 164 | print "Calling function getQuote" 165 | 166 | getQuote(0) 167 | 168 | else: 169 | marketClosed() 170 | 171 | else: 172 | marketClosed() 173 | 174 | except KeyboardInterrupt: 175 | lightsOut() 176 | print ' - Exiting' 177 | try: 178 | sys.exit(0) 179 | except SystemExit: 180 | os._exit(0) 181 | -------------------------------------------------------------------------------- /stockticker-ledboard.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Raspberry Pi and MAX7219 LED Board Stock Symbol Price Monitor 5 | # A simple stock ticker price change monitor of today's positive or negative change using a MAX7219 LED Board 6 | 7 | 8 | import re 9 | import time 10 | import argparse 11 | import atexit 12 | import sys 13 | import os 14 | 15 | import decimal 16 | import errno 17 | import signal 18 | import urllib2 19 | # import ystockquote 20 | import json 21 | import requests 22 | 23 | from luma.led_matrix.device import max7219 24 | from luma.core.interface.serial import spi, noop 25 | from luma.core.render import canvas 26 | from luma.core.virtual import viewport 27 | from luma.core.legacy import text, show_message 28 | from luma.core.legacy.font import proportional, CP437_FONT, TINY_FONT, SINCLAIR_FONT, LCD_FONT 29 | 30 | from socket import error as SocketError 31 | 32 | debug = 0 33 | 34 | # Stock quote configuration: 35 | tickerSymbol = 'AAPL' 36 | 37 | # MAX7219 configuration: 38 | serial = spi(port=0, device=0, gpio=noop()) 39 | device = max7219(serial, cascaded=4, block_orientation=-90, rotate=0) 40 | 41 | # Turn off all the LEDs 42 | def lightsOut(): 43 | device.cleanup() 44 | 45 | # Run lightsOut at exit 46 | atexit.register(lightsOut) 47 | 48 | # Console message and LEDs off while market closed 49 | def marketClosed(): 50 | print "Stock Market Closed.", now 51 | lightsOut() 52 | time.sleep(60) 53 | 54 | # Debugging 55 | if debug == 1: 56 | allInfo = ystockquote.get_all(tickerSymbol) 57 | print allInfo 58 | 59 | decimal.getcontext().prec = 8 60 | 61 | # Handle timeouts gracefully 62 | def timeoutHandler(signum, frame): 63 | print "Error: Timeout fetching quote." 64 | lightsOut() 65 | time.sleep(10) 66 | signal.alarm(0) 67 | return 68 | 69 | signal.signal(signal.SIGALRM, timeoutHandler) 70 | 71 | # Scroll message across the LCD Panel 72 | # msg = "This is a test! 123456789 ABCDEFG" 73 | 74 | 75 | # # Main program logic follows: 76 | # if __name__ == '__main__': 77 | 78 | # try: 79 | # while True: 80 | # print(msg) 81 | # show_message(device, msg, fill="white", font=proportional(LCD_FONT)) 82 | 83 | # Main function to get the quote and animate the LEDs 84 | def getQuote(change): 85 | if debug == 1: 86 | print "Function getQuote" 87 | 88 | try: 89 | signal.alarm(10) 90 | rsp = requests.get('https://finance.google.com/finance?q=' + tickerSymbol + '&output=json') 91 | if rsp.status_code in (200,): 92 | fin_data = json.loads(rsp.content[6:-2].decode('unicode_escape')) 93 | print('Change: {}'.format(fin_data['c'])) 94 | change = format(fin_data['c']) 95 | except urllib2.HTTPError as err: 96 | if err.code == 404: 97 | print "Error: 404 Not Found." 98 | else: 99 | print "Error: ", err.code 100 | except urllib2.URLError as err: 101 | print "Error: Connection reset by peer." 102 | except SocketError as err: 103 | if err.errno == errno.ECONNRESET: 104 | print "Error: Connection reset by peer." 105 | # price = ystockquote.get_price(tickerSymbol) 106 | 107 | # while change == 'N/A': 108 | # print "Error: No price change data." 109 | # time.sleep(60) 110 | # change = ystockquote.get_change(tickerSymbol) 111 | 112 | # changedecimal = decimal.Decimal(change) 113 | # pricedecimal = Decimal(price) 114 | # changedecimal = 0 115 | 116 | # Reset timeout 117 | signal.alarm(0) 118 | 119 | # Console message with price change 120 | print "$ Change: ", change 121 | # print pricedecimal 122 | 123 | # lastclose = Decimal(pricedecimal) - Decimal(changedecimal) 124 | 125 | # print lastclose 126 | 127 | show_message(device, (str (change)), fill="white", font=proportional(LCD_FONT)) 128 | time.sleep(1) 129 | # sense.show_message(str (changedecimal), text_colour=[LED_BRIGHTNESS, 0, 0]) 130 | 131 | # Main program logic follows: 132 | if __name__ == '__main__': 133 | 134 | try: 135 | while True: 136 | now = datetime.datetime.now() 137 | # print now 138 | 139 | # Between Monday - Friday 140 | if 0 <= now.weekday() <= 5: 141 | if debug == 1: 142 | print "Weekday: ", now.weekday() 143 | # print now.hour 144 | 145 | # Between 9AM - 5PM 146 | if now.hour == 9: 147 | if debug == 1: 148 | print "Hour 9AM" 149 | if now.minute >= 30: 150 | if debug == 1: 151 | print "Minute 30 or later" 152 | if 9 <= now.hour <= 17: 153 | # print "Hour: ", now.hour 154 | # print now.time() 155 | 156 | if debug == 1: 157 | print "Calling function getQuote" 158 | 159 | getQuote(0) 160 | 161 | else: 162 | marketClosed() 163 | 164 | else: 165 | if 9 <= now.hour <= 15: 166 | if debug == 1: 167 | print "Hour between 10AM-4PM" 168 | # print "Hour: ", now.hour 169 | # print now.time() 170 | 171 | if debug == 1: 172 | print "Calling function getQuote" 173 | 174 | getQuote(0) 175 | 176 | else: 177 | marketClosed() 178 | 179 | else: 180 | marketClosed() 181 | 182 | # Handle Ctrl-C gracefully 183 | except KeyboardInterrupt: 184 | print ' - Exiting' 185 | lightsOut() 186 | try: 187 | sys.exit(0) 188 | except SystemExit: 189 | os._exit(0) 190 | -------------------------------------------------------------------------------- /stockticker-sensehat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Raspberry Pi and Sense Hat Stock Symbol Price Ticker 4 | # A simple stock ticker price change monitor of today's positive or negative change using the Sense Hat 5 | # Shows a red/green solid color 8x8 matrix up/down arrow and stock price ticker 6 | 7 | import atexit 8 | import datetime 9 | import decimal 10 | import errno 11 | import os 12 | import signal 13 | import sys 14 | import time 15 | import urllib2 16 | import ystockquote 17 | 18 | from socket import error as SocketError 19 | 20 | # from decimal import * 21 | 22 | from sense_hat import SenseHat 23 | 24 | sense = SenseHat() 25 | 26 | # Rotation (Default=0) 27 | sense.set_rotation(90) 28 | 29 | debug = 0 30 | 31 | # Stock quote configuration: 32 | tickerSymbol = 'AAPL' 33 | 34 | 35 | # Functions 36 | 37 | # Turn off all the LEDs 38 | def lightsOut(): 39 | if debug == 1: 40 | print ('Turning off all LEDs.') 41 | sense.clear() 42 | 43 | # Console message and LEDs off while market closed 44 | def marketClosed(): 45 | print "Stock Market Closed.", now 46 | lightsOut() 47 | time.sleep(60) 48 | 49 | # Turn the LEDs off at program exit 50 | atexit.register(lightsOut) 51 | 52 | # Debugging 53 | if debug == 1: 54 | allInfo = ystockquote.get_all(tickerSymbol) 55 | print allInfo 56 | # quote = ystockquote.get_change(tickerSymbol) 57 | # print quote 58 | 59 | # print tickerSymbol + " Price = " + allInfo["price"] 60 | # print tickerSymbol + " Change = " + allInfo["change"] 61 | # print allInfo["change"] 62 | 63 | # print allInfo 64 | 65 | decimal.getcontext().prec = 8 66 | 67 | # Handle timeouts gracefully 68 | def timeoutHandler(signum, frame): 69 | print "Error: Timeout fetching quote." 70 | lightsOut() 71 | time.sleep(10) 72 | signal.alarm(0) 73 | return 74 | 75 | signal.signal(signal.SIGALRM, timeoutHandler) 76 | 77 | # Main function to get the quote and animate the LEDs 78 | def getQuote(change): 79 | if debug == 1: 80 | print "Function getQuote" 81 | 82 | try: 83 | signal.alarm(10) 84 | change = ystockquote.get_change(tickerSymbol) 85 | except urllib2.HTTPError as err: 86 | if err.code == 404: 87 | print "Error: 404 Not Found." 88 | else: 89 | print "Error: ", err.code 90 | except urllib2.URLError as err: 91 | print "Error: Connection reset by peer." 92 | except SocketError as err: 93 | if err.errno == errno.ECONNRESET: 94 | print "Error: Connection reset by peer." 95 | # price = ystockquote.get_price(tickerSymbol) 96 | 97 | while change == 'N/A': 98 | print "Error: No price change data." 99 | time.sleep(60) 100 | change = ystockquote.get_change(tickerSymbol) 101 | 102 | changedecimal = decimal.Decimal(change) 103 | # pricedecimal = Decimal(price) 104 | # changedecimal = 0 105 | 106 | # Reset timeout 107 | signal.alarm(0) 108 | 109 | # Console message with price change 110 | print "$ Change: ", changedecimal 111 | # print pricedecimal 112 | 113 | # lastclose = Decimal(pricedecimal) - Decimal(changedecimal) 114 | 115 | # print lastclose 116 | 117 | # Negative 118 | if changedecimal < 0: 119 | LED_BRIGHTNESS = abs(int(round(100 * changedecimal))) 120 | if LED_BRIGHTNESS > 255: 121 | LED_BRIGHTNESS = 255 122 | if LED_BRIGHTNESS < 50: 123 | LED_BRIGHTNESS = 50 124 | if debug == 1: 125 | print "Brightness: ", LED_BRIGHTNESS 126 | R = [LED_BRIGHTNESS, 0, 0] # Red 127 | G = [0, LED_BRIGHTNESS, 0] # Green 128 | B = [0, 0, 0] # Black 129 | 130 | down_arrow = [ 131 | R, R, R, R, R, R, R, R, 132 | R, R, R, R, R, R, R, R, 133 | B, R, R, R, R, R, R, B, 134 | B, R, R, R, R, R, R, B, 135 | B, B, R, R, R, R, B, B, 136 | B, B, R, R, R, R, B, B, 137 | B, B, B, R, R, B, B, B, 138 | B, B, B, R, R, B, B, B 139 | ] 140 | 141 | sense.set_pixels(down_arrow) 142 | time.sleep(1.5) 143 | sense.show_message(str (changedecimal), text_colour=[LED_BRIGHTNESS, 0, 0]) 144 | 145 | # Positive 146 | if changedecimal > 0: 147 | LED_BRIGHTNESS = int(round(100 * changedecimal)) 148 | if LED_BRIGHTNESS > 255: 149 | LED_BRIGHTNESS = 255 150 | if LED_BRIGHTNESS < 50: 151 | LED_BRIGHTNESS = 50 152 | if debug == 1: 153 | print "Brightness: ", LED_BRIGHTNESS 154 | R = [LED_BRIGHTNESS, 0, 0] # Red 155 | G = [0, LED_BRIGHTNESS, 0] # Green 156 | B = [0, 0, 0] # Black 157 | 158 | up_arrow = [ 159 | B, B, B, G, G, B, B, B, 160 | B, B, B, G, G, B, B, B, 161 | B, B, G, G, G, G, B, B, 162 | B, B, G, G, G, G, B, B, 163 | B, G, G, G, G, G, G, B, 164 | B, G, G, G, G, G, G, B, 165 | G, G, G, G, G, G, G, G, 166 | G, G, G, G, G, G, G, G 167 | ] 168 | 169 | sense.set_pixels(up_arrow) 170 | time.sleep(1.5) 171 | sense.show_message( str (changedecimal), text_colour=[0, LED_BRIGHTNESS, 0]) 172 | 173 | # Zero 174 | if changedecimal == 0: 175 | if debug == 1: 176 | print "Zero Change!" 177 | # sense.clear([50, 50, 50]) 178 | sense.show_message(str (changedecimal), text_colour=[50, 50, 50]) 179 | 180 | time.sleep(.5) 181 | 182 | # Main program logic follows: 183 | if __name__ == '__main__': 184 | 185 | try: 186 | while True: 187 | now = datetime.datetime.now() 188 | # print now 189 | 190 | # Between Monday - Friday 191 | if 0 <= now.weekday() <= 5: 192 | if debug == 1: 193 | print "Weekday: ", now.weekday() 194 | # print now.hour 195 | 196 | # Between 9AM - 5PM 197 | if now.hour == 9: 198 | if debug == 1: 199 | print "Hour 9AM" 200 | if now.minute >= 30: 201 | if debug == 1: 202 | print "Minute 30 or later" 203 | if 9 <= now.hour <= 17: 204 | # print "Hour: ", now.hour 205 | # print now.time() 206 | 207 | if debug == 1: 208 | print "Calling function getQuote" 209 | 210 | getQuote(0) 211 | 212 | else: 213 | marketClosed() 214 | 215 | else: 216 | if 9 <= now.hour <= 15: 217 | if debug == 1: 218 | print "Hour between 10AM-4PM" 219 | # print "Hour: ", now.hour 220 | # print now.time() 221 | 222 | if debug == 1: 223 | print "Calling function getQuote" 224 | 225 | getQuote(0) 226 | 227 | else: 228 | marketClosed() 229 | 230 | else: 231 | marketClosed() 232 | 233 | # Handle Ctrl-C gracefully 234 | except KeyboardInterrupt: 235 | lightsOut() 236 | print ' - Exiting' 237 | try: 238 | sys.exit(0) 239 | except SystemExit: 240 | os._exit(0) 241 | -------------------------------------------------------------------------------- /take-photo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This script will take a photo from the Raspberry Pi camera 4 | 5 | import pygame 6 | import pygame.camera 7 | import os 8 | import time 9 | from pygame.locals import * 10 | 11 | # Take a photo from the camera 12 | pygame.init() 13 | pygame.camera.init() 14 | cam = pygame.camera.Camera("/dev/video0", (768, 1024)) 15 | cam.start() 16 | image = cam.get_image() 17 | image = pygame.transform.rotate(image, -90) 18 | pygame.image.save(image, 'webcam.jpg') 19 | --------------------------------------------------------------------------------