From 44512bf05f1a575f80821eedcfd5060bb5f2f942 Mon Sep 17 00:00:00 2001 From: Gene Liverman Date: Wed, 22 Jan 2020 23:26:55 -0500 Subject: [PATCH] Documented current setup process, created service This commit does a few things: - It removes distelli-manifest.yml since Puppet Pipelines is going EoL - It renames server-prep.sh to install.sh and overhauls it - It creates setup.pp to complement install.sh - It makes weather.py handle SIGTERM signals - It creates a systemd unit - It updates the readme with current info on setup Fixes #10 --- PiWeatherRock.service | 17 +++++++ README.md | 54 +++++++++++++++++--- distelli-manifest.yml | 39 --------------- install.sh | 22 +++++++++ server-prep.sh | 53 -------------------- setup.pp | 112 ++++++++++++++++++++++++++++++++++++++++++ weather.py | 8 +++ 7 files changed, 205 insertions(+), 100 deletions(-) create mode 100644 PiWeatherRock.service delete mode 100644 distelli-manifest.yml create mode 100755 install.sh delete mode 100755 server-prep.sh create mode 100644 setup.pp diff --git a/PiWeatherRock.service b/PiWeatherRock.service new file mode 100644 index 0000000..172b891 --- /dev/null +++ b/PiWeatherRock.service @@ -0,0 +1,17 @@ +# this file is managed by Puppet +[Unit] +Description=PiWeatherRock Service +After=network.target + +[Service] +Type=simple +User=pi +Group=pi +WorkingDirectory=/home/pi/PiWeatherRock +Environment='DISPLAY=:0' +ExecStart=/usr/bin/python3 /home/pi/PiWeatherRock/weather.py +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/README.md b/README.md index f70d501..05ff969 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ | ![daily-forecast-screenshot](screenshots/us-daily.png) | ![hourly-forecast-screenshot](screenshots/us-hourly.png) | ![info-screenshot](screenshots/us-info.png) | - [Introduction](#introduction) +- [Installation](#installation) + - [Optional Steps](#optional-steps) - [Usage](#usage) - [Non-US units](#non-us-units) - [Influence and Credit](#influence-and-credit) @@ -18,21 +20,57 @@ PiWeatherRock is an internet-connected weather station. Its purpose is to displa Right now all data is pulled from Dark Sky. A future iteration will also incorporate data from sensors connected to a battery powered Arduino. -## Usage +## Installation + +> This is based on the assumption that you are using Raspbian 10 (buster). Though the code works on other platforms, the setup process has been tailored for this operating system. + +Before continuing, run `sudo raspi-config` and select `Boot Options` > `Desktop / CLI` > `Desktop Autologin`. Reboot if prompted. + +After that, clone this repository to your to your home directory: + +```bash +git clone https://github.com/genebean/PiWeatherRock.git /home/pi/PiWeatherRock +``` + +Once you have cloned the repository, `cd` into it and create your initial config file: + +```bash +cd /home/pi/PiWeatherRock +cp config.py.sample config.py +``` -The first thing you need to do to run this application is go to https://darksky.net/dev and get an API key. You can make up to 1,000 API calls per day without paying or even providing payment info. After getting a key, copy `config.py.sample` to `config.py` and fill in values for your setup. In addition to your API key you will also need your latitude and longitude. https://gps-coordinates.org/ seems to work well for this as do some cell phone apps. +The next thing you need to do is go to https://darksky.net/dev and get an API key. You can make up to 1,000 API calls per day without paying, or even providing payment info. -Once you have your config file in place, you will need to install dependencies: +In addition to your API key, you will also need your latitude and longitude. https://gps-coordinates.org/ seems to work well for this but I prefer to use the compass app on my iPhone. + +After getting a key and your location information, edit `config.py` and adjust the values based on your preferences. + +With the config file edited you are ready to run the install script by providing it with the name you'd like your Pi to have. For example, to name your Pi `mylittlepi` you'd do this: ```bash -sudo apt install git vim python3-pip libsdl1.2-dev \ -libsdl-ttf2.0-dev libsdl-image1.2-dev libsdl-mixer1.2-dev \ -libjpeg-dev libportmidi-dev libtimedate-perl +sudo ./install.sh mylittlepi +``` + +This will execute the [install.sh](install.sh) from this repository which will do some initial prep work and then use Puppet to configure everything else by applying [setup.pp](setup.pp). + +When this finishes you will have a new systemd service named [PiWeatherRock.service](PiWeatherRock.service) that automatically starts up. You can check the status of the service by running `sudo systemctl status PiWeatherRock`. + +### Optional Steps -pip3 install -U -r requirements.txt +[setup.pp](setup.pp) contains some extra info that is commented out if you are not using the stock GUI. + +Running the command below will tell puppet to keep things in line every 30 minutes. See https://crontab.guru/ for examples of how you could adjust the interval. + +```bash +puppet resource cron 'run puppet' \ +ensure=present \ +command='/usr/bin/sudo /usr/bin/puppet apply /home/pi/PiWeatherRock/setup.pp' \ +minute='*/30' ``` -Now you should be able to run `python3 weather.py` to start the program. While its running there are some keyboard shortcuts to see additional information: +## Usage + +While the service is running there are some keyboard shortcuts to see additional information. These can be used from a keyboard plugged into the Pi or via VNC. VNC is available via IP or the name you set earlier (ex: `mylittlepi` is available via `mylittlepi.local`). - __w__: Displays the main weather screen - __i__: Displays an info screen which contains some additional info information diff --git a/distelli-manifest.yml b/distelli-manifest.yml deleted file mode 100644 index 17ee002..0000000 --- a/distelli-manifest.yml +++ /dev/null @@ -1,39 +0,0 @@ -genebean/PiWeatherRock: - Build: - - export DEBIAN_FRONTEND=noninteractive - - sudo apt-get update - - sudo apt-get install -y python python-serial python-requests python-pygame - PreRelease: - - | - cat << EOF > config.py - # Settings used by weather.py - """ Constants used in weather.py """ - # This is your Weather Underground API key - import os - WU_API_KEY = os.environ['WU_API_KEY'] - - # Seconds between API calls. - # Note: the free WU access only allows for 500 calls / day - # aka a check ~ every 2.88 minutes - WU_CHECK_INTERVAL = 300 # 5 minutes - - # The location you want to check - ZIP_CODE = os.getenv('ZIP_CODE', '30117') - - # Full screen is for when this is running on a TV or - # similar device with a much higher resolution. - FULLSCREEN = True - - # If the weather icons are overlapping the text try adjusting - # this value. Negative values raise the icon. - LARGE_ICON_OFFSET = -23.5 - EOF - PkgInclude: - - '*' - PreInstall: - - export DEBIAN_FRONTEND=noninteractive - - sudo apt-get update - - sudo apt-get install -y python python-serial python-requests python-pygame - Exec: - - export DISPLAY=:0.0 - - python weather.py diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..d7be49b --- /dev/null +++ b/install.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +NAME=$1 + +# set the timezone +sudo timedatectl set-timezone America/New_York + +# update the hostname +sudo hostnamectl set-hostname $NAME +sudo sed -i "s|raspberrypi|${NAME}|g" /etc/hosts + +# patch the system and do setup +sudo apt update +sudo apt full-upgrade -y +sudo apt install -y git puppet +sudo rm -f /etc/puppet/hiera.yaml +source /etc/profile.d/puppet-agent.sh +sudo puppet module install puppetlabs-vcsrepo +sudo puppet module install puppet-python +sudo puppet module install camptocamp-systemd + +sudo puppet apply /home/pi/PiWeatherRock/setup.pp diff --git a/server-prep.sh b/server-prep.sh deleted file mode 100755 index 88a1689..0000000 --- a/server-prep.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash -set -x - -# Adjust these two lines to include your desired hostname -sudo hostnamectl set-hostname tart -sudo sed -i 's|raspberrypi|tart|g' /etc/hosts - -sudo apt-get update -sudo apt-get dist-upgrade -y -sudo apt-get install -y --no-install-recommends xserver-xorg lightdm realvnc-vnc-server git libgl1-mesa-dri awesome lxterminal vim puppet x11-xserver-utils - -mkdir /home/pi/bin -echo '#!/bin/bash' > /home/pi/bin/xhost.sh -echo 'xhost +' >> /home/pi/bin/xhost.sh -chmod a+x /home/pi/bin/xhost.sh - -sudo sed -i 's|#display-setup-script=|display-setup-script=/home/pi/bin/xhost.sh|' /etc/lightdm/lightdm.conf -grep -e '^display-setup-script' /etc/lightdm/lightdm.conf - -# Install Distelli Agent -curl -sSL https://pipelines.puppet.com/download/client | sh -echo 'Enter your Access Token from Puppet Pipelines and press enter:' -read -s DistelliAccessToken -echo 'Enter your Secret Key from Puppet Pipelines and press enter:' -read -s DistelliSecretKey -cat << EOF |sudo tee /etc/distelli.yml > /dev/null -DistelliAccessToken: "$DistelliAccessToken" -DistelliSecretKey: "$DistelliSecretKey" -EOF -sudo /usr/local/bin/distelli agent install -conf /etc/distelli.yml -sudo /usr/local/bin/distelli agent status -sudo usermod -G gpio distelli - -cat << EOF > /home/pi/config.pp -service { 'vncserver-x11-serviced': - ensure => running, - enable => true, -} - -\$disabled_services = [ - 'bluetooth', - 'triggerhappy', -] - -service { \$disabled_services: - ensure => 'stopped', - enable => 'false', -} -EOF - -sudo -i puppet apply /home/pi/config.pp - -sudo reboot diff --git a/setup.pp b/setup.pp new file mode 100644 index 0000000..5a1f0a4 --- /dev/null +++ b/setup.pp @@ -0,0 +1,112 @@ +# post notice if not Raspbian 10 or newer +unless ($facts['os']['name'] == 'Debian') and + ($facts['os']['distro']['id'] == 'Raspbian') and + (versioncmp($facts['os']['release']['major'], '10') == 0) { + notice('This manifest has only been tested Raspbian 10 (buster)') +} + +$main_packages = [ + 'git', + 'libgl1-mesa-dri', + 'lightdm', + 'realvnc-vnc-server', + 'tmux', + 'x11-xserver-utils', + 'xserver-xorg', + 'vim', +] + +$piweatherrock_packages = [ + 'libjpeg-dev', + 'libportmidi-dev', + 'libsdl1.2-dev', + 'libsdl-image1.2-dev', + 'libsdl-mixer1.2-dev', + 'libsdl-ttf2.0-dev', + 'libtimedate-perl', + 'python3-pip', +] + +package { [ $main_packages, $piweatherrock_packages, ]: + ensure => latest, + install_options => [ + '--no-install-recommends', + ], +} + +# if using Raspbian Lite uncomment the bit below for a minimal desktop and terminal +# package { [ 'awesome', 'lxterminal', ]: +# ensure => latest, +# install_options => [ +# '--no-install-recommends', +# ], +# before => Python::Requirements['/home/pi/PiWeatherRock/requirements.txt'], +# } + +# allow all sessions to share the X server +# see https://www.computerhope.com/unix/xhost.htm +file { + default: + owner => 'pi', + group => 'pi', + mode => '0755', + ; + '/home/pi/bin': + ensure => directory, + ; + '/home/pi/bin/xhost.sh': + ensure => file, + content => @(END), + #!/bin/bash + xhost + + | END + ; +} + +# make lightdm use the xhost settings above +exec { 'enable display-setup-script': + path => '/bin:/usr/bin', + command => "sed -i 's|#display-setup-script=|display-setup-script=/home/pi/bin/xhost.sh|' /etc/lightdm/lightdm.conf", + unless => "grep -e '^display-setup-script' /etc/lightdm/lightdm.conf", +} + +service { 'vncserver-x11-serviced': + ensure => running, + enable => true, + require => Package[$main_packages], +} + +vcsrepo { '/home/pi/PiWeatherRock': + ensure => latest, + provider => git, + source => 'https://github.com/genebean/PiWeatherRock.git', +} + +python::requirements { '/home/pi/PiWeatherRock/requirements.txt': + virtualenv => '/home/pi/PiWeatherRock', + pip_provider => 'pip3', + owner => 'pi', + group => 'pi', + cwd => '/home/pi/PiWeatherRock', + require => [ + Package[ $main_packages, $piweatherrock_packages, ], + Vcsrepo['/home/pi/PiWeatherRock'], + ], +} + +systemd::unit_file { 'PiWeatherRock.service': + source => 'file:///home/pi/PiWeatherRock/PiWeatherRock.service', + require => Python::Requirements['/home/pi/PiWeatherRock/requirements.txt'], + notify => Service['PiWeatherRock.service'], +} + +service {'PiWeatherRock.service': + ensure => running, + enable => true, + require => Systemd::Unit_file['PiWeatherRock.service'], + subscribe => [ + File['/home/pi/bin/xhost.sh'], + Exec['enable display-setup-script'], + Vcsrepo['/home/pi/PiWeatherRock'], + ], +} diff --git a/weather.py b/weather.py index 096e7c0..322d524 100644 --- a/weather.py +++ b/weather.py @@ -39,6 +39,7 @@ import datetime import os import platform +import signal import sys import syslog import time @@ -58,6 +59,13 @@ UNICODE_DEGREE = u'\xb0' +def exit_gracefully(signum, frame): + sys.exit(0) + + +signal.signal(signal.SIGTERM, exit_gracefully) + + def deg_to_compass(degrees): val = int((degrees/22.5)+.5) dirs = ["N", "NNE", "NE", "ENE",