Punt abbey-weather role, entirely replaced by Home Assistant.
authorMatt Birkholz <matt@birchwood-abbey.net>
Wed, 18 Sep 2024 17:17:48 +0000 (11:17 -0600)
committerMatt Birkholz <matt@birchwood-abbey.net>
Wed, 18 Sep 2024 18:51:02 +0000 (12:51 -0600)
The 1-Wire hardware was replaced with an Ecowitt IoT hub and sensors
including wind and rain.

README.org
hosts
playbooks/site.yml
roles_t/abbey-weather/files/daemon-anoat [deleted file]
roles_t/abbey-weather/handlers/main.yml [deleted file]
roles_t/abbey-weather/tasks/main.yml [deleted file]

index e08fdd96c8a7641a1e232031b3679eeec76a2b50..379797dcbc1e11818539d5a51c3d8fc78275d9d8 100644 (file)
@@ -815,12 +815,10 @@ directory, =playbooks/=.
 
 ** Install Additional Packages
 
-The scripts that maintain the abbey's web site and run the Weather
-project use a number of additional software packages.  The
-=/WWW/live/Private/make-top-index= script uses ~HTML::TreeBuilder~ in
-the ~libhtml-tree-perl~ package.  The house task list uses JQuery.
-Weather scripts use ~mit-scheme~ and ~gnuplot~ (in pseudonymous
-packages).
+The scripts that maintain the abbey's web site use a number of
+additional software packages.  The =/WWW/live/Private/make-top-index=
+script uses ~HTML::TreeBuilder~ in the ~libhtml-tree-perl~ package.
+The house task list uses JQuery.
 
 #+CAPTION: [[file:roles_t/abbey-core/tasks/main.yml][=roles_t/abbey-core/tasks/main.yml=]]
 #+BEGIN_SRC conf :tangle roles_t/abbey-core/tasks/main.yml
@@ -1490,24 +1488,6 @@ Monkey's photo processing scripts use ~netpbm~ commands like
   apt: pkg=netpbm
 #+END_SRC
 
-** Configure Weather Updates
-
-Monkey on Core runs =/WWW/campus/Weather/Private/cronjob= every 5
-minutes and =cronjob-midnight= at midnight.
-
-#+CAPTION: [[file:roles_t/abbey-core/tasks/main.yml][=roles_t/abbey-core/tasks/main.yml=]]
-#+BEGIN_SRC :tangle roles_t/abbey-core/tasks/main.yml
-
-- name: Create Monkey's weather job.
-  become: yes
-  cron:
-    name: weather
-    hour: "*"
-    minute: "*/5"
-    job: "[ -d /WWW/house ] && /WWW/house/Weather/Private/cronjob"
-    user: monkey
-#+END_SRC
-
 ** Install Samba
 
 The abbey core provides NAS (Network Attached Storage) service to the
@@ -1810,379 +1790,23 @@ The monks of the abbey are masters of the staff and Emacs.
 
 * The Abbey Weather Role
 
-Birchwood Abbey's weather hosts use the 1-Wire server (from the
-~owserver~ package) and a 1-Wire USB adapter.  They use an
-unprivileged account (~monkey~) to run a SystemD service named
-~weatherd~ (aka "the daemon").  The daemon is a Perl script that runs
-~owread~ and logs the new measurements once per minute.
-
-The log files are collected by Monkey on Core (via ~rsync~), then
-processed and published in campus web pages by The Weather Project's
-code (old, using ~gnuplot(1)~, and so... unpublished).
-
-** The Abbey Weather Hardware
-
-The abbey currently has one weather host, Gate, and a couple 1-Wire
-sensor modules.  The modules measure inside and outside temperature
-and humidity.  Their desired locations are 7-8m from the core servers
-so they are plugged into a custom Y cable, with the inside sensor
-cable spliced into the middle of the outside/main cable.  The proximal
-end's RJ11 plugs into a 1-Wire USB adapter (a DS9490R) plugged into
-Gate.  The outside end goes out the window with the Starlink cable.
-
-** The Abbey Weather Host Setup
-
-The Ansible code in the ~abbey-weather~ role assumes it is working
-with a cloistered host (as described in [[*Cloistering][Cloistering]]) and proceeds in
-two phases.  The first installs the ~ow-server~ package and configures
-it to use a DS9490 (USB adapter) rather than a debugging fake.  After
-the first ~./abbey config new~, the new weather host seems to need a
-reboot before the 1-Wire bus becomes visible via ~owdir~.
-
-After a reboot ~owdir~ should list one or more type 26 device IDs.
-Listing them (e.g. running ~owdir /26.nnnnnnnn~ or ~owdir
-/26.nnnnnnnn/HIH~) should reveal "files" named =temperature= and
-=HIH/humidity=.  These pseudo-file paths are used in the daemon script
-below.  A test session is shown below.
-
-#+BEGIN_EXAMPLE
-monkey@new$ owdir
-...
-    /26.2153B6000000/
-...
-monkey@new$ owdir /26.2153B6000000
-...
-    /26.2153B6000000/temperature
-...
-monkey@new$ owread /26.2153B6000000/temperature; echo
-26.125
-monkey@new$ 
-#+END_EXAMPLE
-
-The second phase of weather host configuration waits for the host-
-specific weather daemon script to appear in the role's =files/=.
-
-** The Abbey Weather Daemons
-
-Different weather hosts, with different 1-Wire devices, need different
-daemon scripts, to call ~owread~ with different paths (containing the
-IDs of each host's devices).  At the moment there is just the
-one weather host, ~anoat~.
-
-#+CAPTION: [[file:roles_t/abbey-weather/files/daemon-anoat][=roles_t/abbey-weather/files/daemon-anoat=]]
-#+BEGIN_SRC perl :tangle roles_t/abbey-weather/files/daemon-anoat :mkdirp yes
-#!/usr/bin/perl -w
-# -*- CPerl -*-
-#
-# Weather/daemon
-#
-# Fetches data from the local owserver once per minute.  Appends to
-# Log/{In,Out}side/YEAR/MONTH/DAY.txt.
-
-use strict;
-use IO::File;
-use Date::Format;
-
-my $ILOG;
-my $OLOG;
-my $ymd = "";
-sub mymkdir ($);
-sub reopen_logs ()
-{
-  my $time = time;
-  my $datime = time2str ("%Y-%m-%d %H:%M:%S", $time, "UTC");
-  my ($year, $month, $day) = $datime =~ /^(\d{4})-(\d\d)-(\d\d) /;
-  my $new_ymd = "$year/$month/$day";
-  return if $new_ymd eq $ymd;
-  close $ILOG if defined $ILOG;
-  close $OLOG if defined $OLOG;
-  umask 07;
-  mymkdir "Inside/$year/$month";
-  mymkdir "Outside/$year/$month";
-  umask 027;
-  my $filename = "Inside/$new_ymd.txt";
-  $ILOG = new IO::File;
-  open $ILOG, ">>$filename" or die "Could not open $filename: $!\n";
-  $filename = "Outside/$new_ymd.txt";
-  $OLOG = new IO::File;
-  open $OLOG, ">>$filename" or die "Could not open $filename: $!\n";
-  $ymd = $new_ymd;
-}
-
-sub logit ($$$);
-sub main () {
-  die "usage: $0\n" if @ARGV != 0;
-  $0 = "weatherd";
-  chdir "/home/monkey/Weather/Log" or die;
-  umask 027;
-  my $start = time;
-  {
-    my $secs = 60 - $start % 60;
-    $start += $secs;
-    sleep ($secs);
-  }
-  while (1) {
-    reopen_logs;
-    logit $OLOG, "T", "/26.2153B6000000/temperature";
-    logit $OLOG, "H", "/26.2153B6000000/HIH4000/humidity";
-    logit $ILOG, "T", "/26.8859B6000000/temperature";
-    logit $ILOG, "H", "/26.8859B6000000/HIH4000/humidity";
-    $start += 60;
-    my $now = time;
-    while ($start < $now) { $start += 60; }
-    my $secs = $start - $now;
-    sleep  ($secs);
-  }
-}
-
-sub logit ($$$)
-{
-  my ($log, $name, $query) = @_;
-
-  my $tries = 0;
-  while ($tries < 3) {
-    my $time = time;
-    my $datime = time2str ("%Y-%m-%d %H:%M:%S", $time, "UTC");
-    $tries += 1;
-    my @lines = `/usr/bin/owread $query`;
-    chomp @lines;
-    my $status = $?;
-    my $sig = $status & 127;
-    $status >>= 8;
-    if ($status != 0) {
-      my $L = join "\\n", @lines;
-      print $log "$datime\t$name\terror: status $status: $L\n";
-      $log->flush;
-    } elsif (@lines != 1) {
-      my $L = join "\\n", @lines;
-      print $log "$datime\t$name\terror: multiple lines: $L\n";
-      $log->flush;
-    } elsif ($lines[0] !~ /^ *(-?\d+(\.\d+)?)$/) {
-      my $L = $lines[0];
-      print $log "$datime\t$name\terror: bogus line: $L\n";
-      $log->flush;
-    } else {
-      my $datum = $1;
-      print $log "$datime\t$name\t$datum\n";
-      $log->flush;
-      return;
-    }
-  }
-}
-
-sub mymkdir ($)
-{
-  my ($dirpath) = @_;
-
-  my @path_names = split /\//, $dirpath;
-  my $path;
-  if (!$path_names[0]) {
-    $path = "/";
-    shift @path_names;
-  } else {
-    $path = ".";
-  }
-  my @created;
-  while (@path_names) {
-    $path .= "/" . shift @path_names;
-    if (! -d $path) {
-      if (-e $path) {
-       die "mkdir $dirpath: already exists; not a directory!\n";
-      }
-      if (! mkdir $path) {
-       die "mkdir $path: $!\n";
-      } else {
-       chmod 02775, $path;
-       push @created, $path;
-      }
-    }
-  }
-  return @created;
-}
-
-main;
-#+END_SRC
-
-The above Perl script uses the ~Date::Format~ module, which is
-installed by the following task.
-
-#+CAPTION: [[file:roles_t/abbey-weather/tasks/main.yml][=roles_t/abbey-weather/tasks/main.yml=]]
-#+BEGIN_SRC conf :tangle roles_t/abbey-weather/tasks/main.yml :mkdirp yes
----
-- name: Install weather daemon packages.
-  become: yes
-  apt: pkg=libtimedate-perl
-#+END_SRC
-
-** Install 1-Wire Server
-
-This next task installs the 1-Wire server and shell commands.  The
-abbey uses the Dallas Semiconductor DS9490R, a USB to 1-Wire adapter,
-on all its weather hosts, so it also configures the server to use the
-USB adapter (rather than a test "fake" adapter).
-
-#+CAPTION: [[file:roles_t/abbey-weather/tasks/main.yml][=roles_t/abbey-weather/tasks/main.yml=]]
-#+BEGIN_SRC conf :tangle roles_t/abbey-weather/tasks/main.yml
-
-- name: Install 1-Wire server.
-  become: yes
-  apt:
-    pkg: [ owserver, ow-shell ]
-
-- name: Configure 1-Wire server.
-  become: yes
-  lineinfile:
-    path: /etc/owfs.conf
-    regexp: "{{ item.regexp }}"
-    line: "{{ item.line }}"
-    backrefs: yes
-  loop:
-  - { regexp: '^[# ]*server: *FAKE(.*)$', line: '#server: FAKE\1' }
-  - { regexp: '^[# ]*server: *usb(.*)$', line: 'server: usb\1' }
-#+END_SRC
-
-** Install Rsync
-
-Monkey on Core will want to download log records (files) using
-~rsync(1)~.
-
-#+CAPTION: [[file:roles_t/abbey-weather/tasks/main.yml][=roles_t/abbey-weather/tasks/main.yml=]]
-#+BEGIN_SRC conf :tangle roles_t/abbey-weather/tasks/main.yml
-
-- name: Install Rsync.
-  become: yes
-  apt: pkg=rsync
-#+END_SRC
-
-** Create Monkey
-
-The weather daemon is run by an unprivileged ~monkey~ account (/not/
-~sysadm~) which allows ~monkey~ on Core shell access.  This is also
-executed during the initial phase of configuration, allowing the
-administrator to login on the new weather host as ~monkey~ and thus to
-test access to the 1-Wire adapter and devices.  To facilitate
-debugging, the ~sysadm~ account is included in the ~monkey~ group.
-
-#+CAPTION: [[file:roles_t/abbey-weather/tasks/main.yml][=roles_t/abbey-weather/tasks/main.yml=]]
-#+BEGIN_SRC conf :tangle roles_t/abbey-weather/tasks/main.yml
-
-- name: Create monkey.
-  become: yes
-  user:
-    name: monkey
-    system: yes
-
-- name: Authorize monkey@core.
-  become: yes
-  vars:
-    pubkeyfile: ../Secret/ssh_monkey/id_rsa.pub
-  authorized_key:
-    user: monkey
-    key: "{{ lookup('file', pubkeyfile) }}"
-    manage_dir: yes
-
-- name: Add {{ ansible_user }} to monkey group.
-  become: yes
-  user:
-    name: "{{ ansible_user }}"
-    append: yes
-    groups: monkey
-#+END_SRC
-
-** Install Weather Daemon
-
-The weather daemon is kept alive as a Systemd service unit.  This task
-creates and starts that service /after/ the host-specific
-=files/daemon-HOST= file becomes available.
-
-The ~ExecStartPre=/bin/sleep 30~ is intended to avoid recent hangs in
-~owread~.
-
-#+CAPTION: [[file:roles_t/abbey-weather/tasks/main.yml][=roles_t/abbey-weather/tasks/main.yml=]]
-#+BEGIN_SRC conf :tangle roles_t/abbey-weather/tasks/main.yml
-
-- name: Install weather directory.
-  become: yes
-  file:
-    path: /home/monkey/Weather/Log
-    state: directory
-    owner: monkey
-    group: monkey
-    mode: u=rwx,g=rx,o=rx
-
-- name: Test for weather daemon script.
-  vars:
-    dir: ../roles/abbey-weather/files
-    file: "{{ dir }}/daemon-{{ inventory_hostname }}"
-  stat: path="{{ file }}"
-  delegate_to: localhost
-  register: weather
-
-- name: Note missing weather daemon script.
-  vars:
-    dir: ../roles/abbey-weather/files
-    script: "{{ dir }}/daemon-{{ inventory_hostname }}"
-  debug:
-    msg: "{{ script }}: not found"
-  when: not weather.stat.exists
-
-- name: Install weather daemon.
-  become: yes
-  vars:
-    dir: ../roles/abbey-weather/files
-    script: "{{ dir }}/daemon-{{ inventory_hostname }}"
-  copy:
-    src: "{{ script }}"
-    dest: /home/monkey/Weather/daemon
-    owner: monkey
-    group: monkey
-    mode: u=rwx,g=rx,o=
-  when: weather.stat.exists
-
-- name: Install weatherd service.
-  become: yes
-  copy:
-    content: |
-      [Unit]
-      Description=Weather Logger
-      After=owserver.service
-
-      [Service]
-      User=monkey
-      ExecStartPre=/bin/sleep 30
-      ExecStart=/home/monkey/Weather/daemon
-      Restart=always
-
-      [Install]
-      WantedBy=multi-user.target
-    dest: /etc/systemd/system/weatherd.service
-  when: weather.stat.exists
-  notify:
-  - Reload Systemd.
-  - Restart weather daemon.
+Birchwood Abbey now uses Home Assistant to record and display weather
+data from an Ecowitt GW2001 IoT gateway connecting wirelessly to a
+WS90 (7 function weather station) and a couple WN31s (temp/humidity
+sensors).
 
-- name: Enable/Start weather daemon.
-  become: yes
-  systemd:
-    service: weatherd
-    enabled: yes
-    state: started
-  when: weather.stat.exists
-#+END_SRC
-
-#+CAPTION: [[file:roles_t/abbey-weather/handlers/main.yml][=roles_t/abbey-weather/handlers/main.yml=]]
-#+BEGIN_SRC conf :tangle roles_t/abbey-weather/handlers/main.yml :mkdirp yes
----
-- name: Reload Systemd.
-  become: yes
-  command: systemctl daemon-reload
+The configuration of the GW2001 IoT hub involved turning off the Wi-Fi
+access point, and disabling unused channels.  The hub reports the data
+from all sensors in range, /anyone's/ sensors.  These new data sources
+are noticed and recorded by Home Assistant automatically as similarly
+equipped campers come and go.  Disabling unused channels helps avoid
+these distractions.
 
-- name: Restart weather daemon.
-  become: yes
-  systemd:
-    service: weatherd
-    state: restarted
-#+END_SRC
+The configuration of Home Assistant involved installing the Ecowitt
+"integration".  This was accomplished by choosing "Settings", then
+"Devices & services", then "Add Integration", and searching for
+"Ecowitt".  Once installed, the integration created dozens of weather
+entities which were organized into an "Abbey" dashboard.
 
 
 * The Abbey DVR Role
@@ -3272,9 +2896,6 @@ all:
         kamino:
         kessel:
         ord-mantell:
-    weather:
-      hosts:
-        anoat:
     dvrs:
       hosts:
         dantooine:
@@ -3324,10 +2945,6 @@ institutional roles, then the liturgical roles.
   hosts: campus
   roles: [ campus, abbey-cloister ]
 
-- name: Configure Weather
-  hosts: weather
-  roles: [ abbey-weather ]
-
 - name: Configure DVRs
   hosts: dvrs
   roles: [ abbey-dvr ]
@@ -3515,10 +3132,10 @@ if ($ARGV[0] eq "versions") {
 
 The abbey changes location almost weekly, so its timezone changes
 occasionally.  Droplet does not move.  Gate and other simple servers
-(the weather monitors) are kept in UTC.  Core, the DVRs, TVRs, and the
-desktops all want updating to the current local timezone.  The
-desktops are managed maually, but the rest can all be updated using
-Ansible.
+are kept in UTC.  Core, the DVRs, TVRs, Home Assistant and the
+desktops all want updating to the current local timezone.  Home
+Assistant and the desktops are managed maually, but the rest can all
+be updated using Ansible.
 
 The ~tz~ sub-command runs the =timezone.yml= playbook, which uses the
 current timezone/city on the administrator's notebook and updates
diff --git a/hosts b/hosts
index ba5280eab36557c245be71211d62e748a2afe125..8346a7b8ca514949c24055648120f717bad3cb81 100644 (file)
--- a/hosts
+++ b/hosts
@@ -47,9 +47,6 @@ all:
         kamino:
         kessel:
         ord-mantell:
-    weather:
-      hosts:
-        anoat:
     dvrs:
       hosts:
         dantooine:
index a294cc44a4686c511920fb62df18d0ae26929847..a1723c46b920fc722d90c3ef3679c21247e74671 100644 (file)
   hosts: campus
   roles: [ campus, abbey-cloister ]
 
-- name: Configure Weather
-  hosts: weather
-  roles: [ abbey-weather ]
-
 - name: Configure DVRs
   hosts: dvrs
   roles: [ abbey-dvr ]
diff --git a/roles_t/abbey-weather/files/daemon-anoat b/roles_t/abbey-weather/files/daemon-anoat
deleted file mode 100644 (file)
index 6006c14..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/usr/bin/perl -w
-# -*- CPerl -*-
-#
-# Weather/daemon
-#
-# Fetches data from the local owserver once per minute.  Appends to
-# Log/{In,Out}side/YEAR/MONTH/DAY.txt.
-
-use strict;
-use IO::File;
-use Date::Format;
-
-my $ILOG;
-my $OLOG;
-my $ymd = "";
-sub mymkdir ($);
-sub reopen_logs ()
-{
-  my $time = time;
-  my $datime = time2str ("%Y-%m-%d %H:%M:%S", $time, "UTC");
-  my ($year, $month, $day) = $datime =~ /^(\d{4})-(\d\d)-(\d\d) /;
-  my $new_ymd = "$year/$month/$day";
-  return if $new_ymd eq $ymd;
-  close $ILOG if defined $ILOG;
-  close $OLOG if defined $OLOG;
-  umask 07;
-  mymkdir "Inside/$year/$month";
-  mymkdir "Outside/$year/$month";
-  umask 027;
-  my $filename = "Inside/$new_ymd.txt";
-  $ILOG = new IO::File;
-  open $ILOG, ">>$filename" or die "Could not open $filename: $!\n";
-  $filename = "Outside/$new_ymd.txt";
-  $OLOG = new IO::File;
-  open $OLOG, ">>$filename" or die "Could not open $filename: $!\n";
-  $ymd = $new_ymd;
-}
-
-sub logit ($$$);
-sub main () {
-  die "usage: $0\n" if @ARGV != 0;
-  $0 = "weatherd";
-  chdir "/home/monkey/Weather/Log" or die;
-  umask 027;
-  my $start = time;
-  {
-    my $secs = 60 - $start % 60;
-    $start += $secs;
-    sleep ($secs);
-  }
-  while (1) {
-    reopen_logs;
-    logit $OLOG, "T", "/26.2153B6000000/temperature";
-    logit $OLOG, "H", "/26.2153B6000000/HIH4000/humidity";
-    logit $ILOG, "T", "/26.8859B6000000/temperature";
-    logit $ILOG, "H", "/26.8859B6000000/HIH4000/humidity";
-    $start += 60;
-    my $now = time;
-    while ($start < $now) { $start += 60; }
-    my $secs = $start - $now;
-    sleep  ($secs);
-  }
-}
-
-sub logit ($$$)
-{
-  my ($log, $name, $query) = @_;
-
-  my $tries = 0;
-  while ($tries < 3) {
-    my $time = time;
-    my $datime = time2str ("%Y-%m-%d %H:%M:%S", $time, "UTC");
-    $tries += 1;
-    my @lines = `/usr/bin/owread $query`;
-    chomp @lines;
-    my $status = $?;
-    my $sig = $status & 127;
-    $status >>= 8;
-    if ($status != 0) {
-      my $L = join "\\n", @lines;
-      print $log "$datime\t$name\terror: status $status: $L\n";
-      $log->flush;
-    } elsif (@lines != 1) {
-      my $L = join "\\n", @lines;
-      print $log "$datime\t$name\terror: multiple lines: $L\n";
-      $log->flush;
-    } elsif ($lines[0] !~ /^ *(-?\d+(\.\d+)?)$/) {
-      my $L = $lines[0];
-      print $log "$datime\t$name\terror: bogus line: $L\n";
-      $log->flush;
-    } else {
-      my $datum = $1;
-      print $log "$datime\t$name\t$datum\n";
-      $log->flush;
-      return;
-    }
-  }
-}
-
-sub mymkdir ($)
-{
-  my ($dirpath) = @_;
-
-  my @path_names = split /\//, $dirpath;
-  my $path;
-  if (!$path_names[0]) {
-    $path = "/";
-    shift @path_names;
-  } else {
-    $path = ".";
-  }
-  my @created;
-  while (@path_names) {
-    $path .= "/" . shift @path_names;
-    if (! -d $path) {
-      if (-e $path) {
-       die "mkdir $dirpath: already exists; not a directory!\n";
-      }
-      if (! mkdir $path) {
-       die "mkdir $path: $!\n";
-      } else {
-       chmod 02775, $path;
-       push @created, $path;
-      }
-    }
-  }
-  return @created;
-}
-
-main;
diff --git a/roles_t/abbey-weather/handlers/main.yml b/roles_t/abbey-weather/handlers/main.yml
deleted file mode 100644 (file)
index e314f9d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
----
-- name: Reload Systemd.
-  become: yes
-  command: systemctl daemon-reload
-
-- name: Restart weather daemon.
-  become: yes
-  systemd:
-    service: weatherd
-    state: restarted
diff --git a/roles_t/abbey-weather/tasks/main.yml b/roles_t/abbey-weather/tasks/main.yml
deleted file mode 100644 (file)
index 4764eda..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
----
-- name: Install weather daemon packages.
-  become: yes
-  apt: pkg=libtimedate-perl
-
-- name: Install 1-Wire server.
-  become: yes
-  apt:
-    pkg: [ owserver, ow-shell ]
-
-- name: Configure 1-Wire server.
-  become: yes
-  lineinfile:
-    path: /etc/owfs.conf
-    regexp: "{{ item.regexp }}"
-    line: "{{ item.line }}"
-    backrefs: yes
-  loop:
-  - { regexp: '^[# ]*server: *FAKE(.*)$', line: '#server: FAKE\1' }
-  - { regexp: '^[# ]*server: *usb(.*)$', line: 'server: usb\1' }
-
-- name: Install Rsync.
-  become: yes
-  apt: pkg=rsync
-
-- name: Create monkey.
-  become: yes
-  user:
-    name: monkey
-    system: yes
-
-- name: Authorize monkey@core.
-  become: yes
-  vars:
-    pubkeyfile: ../Secret/ssh_monkey/id_rsa.pub
-  authorized_key:
-    user: monkey
-    key: "{{ lookup('file', pubkeyfile) }}"
-    manage_dir: yes
-
-- name: Add {{ ansible_user }} to monkey group.
-  become: yes
-  user:
-    name: "{{ ansible_user }}"
-    append: yes
-    groups: monkey
-
-- name: Install weather directory.
-  become: yes
-  file:
-    path: /home/monkey/Weather/Log
-    state: directory
-    owner: monkey
-    group: monkey
-    mode: u=rwx,g=rx,o=rx
-
-- name: Test for weather daemon script.
-  vars:
-    dir: ../roles/abbey-weather/files
-    file: "{{ dir }}/daemon-{{ inventory_hostname }}"
-  stat: path="{{ file }}"
-  delegate_to: localhost
-  register: weather
-
-- name: Note missing weather daemon script.
-  vars:
-    dir: ../roles/abbey-weather/files
-    script: "{{ dir }}/daemon-{{ inventory_hostname }}"
-  debug:
-    msg: "{{ script }}: not found"
-  when: not weather.stat.exists
-
-- name: Install weather daemon.
-  become: yes
-  vars:
-    dir: ../roles/abbey-weather/files
-    script: "{{ dir }}/daemon-{{ inventory_hostname }}"
-  copy:
-    src: "{{ script }}"
-    dest: /home/monkey/Weather/daemon
-    owner: monkey
-    group: monkey
-    mode: u=rwx,g=rx,o=
-  when: weather.stat.exists
-
-- name: Install weatherd service.
-  become: yes
-  copy:
-    content: |
-      [Unit]
-      Description=Weather Logger
-      After=owserver.service
-
-      [Service]
-      User=monkey
-      ExecStartPre=/bin/sleep 30
-      ExecStart=/home/monkey/Weather/daemon
-      Restart=always
-
-      [Install]
-      WantedBy=multi-user.target
-    dest: /etc/systemd/system/weatherd.service
-  when: weather.stat.exists
-  notify:
-  - Reload Systemd.
-  - Restart weather daemon.
-
-- name: Enable/Start weather daemon.
-  become: yes
-  systemd:
-    service: weatherd
-    enabled: yes
-    state: started
-  when: weather.stat.exists