Ooit, een hele tijd terug heb ik een APC rack pdu (ap7921) in huis gehaald om 2 dingen te doen. Het meten van het totale verbruik van de mediahoek én het in/uitschakelen van lichten of andere zaken. Dat kan prima met deze pdu, want er zit netwerk op en dus ook via SNMP aan te sturen. Via een php webpagina (die ik met mijn mobile device kan openen) kan ik al heel lang de belangrijkste outlets schakelen en ik heb ook al een tijd een cronjob op een server draaien die de lichten schakelen. Ja, ook de kerstboom hoewel het stekkerblok op die outlet nu onder de bank ligt voor algemeen gebruik. De subwoofer was voor het gemak, tijdens een film licht uit, sub aan en geniet.
De pagina stuurt in feite ook via een ‘snmpset’ commando een 1 of 2 naar de juiste poort. Daarbij is de kleur groen ‘aan’ en rood is ‘uit’ puur voor de opmaak.
Het script in cronjob is een paar keer herschreven en kwijt geraakt door een crash van de OrangePi thuis en dus weer opnieuw gemaakt. Voor nu is het een ‘fancy’ versie want het kan uiteraard ook gewoon met praktisch 8 of zo regels. Maar dat is het mooie, je wil leren en je script verder ontwikkelen, verharden. Een geval van “good practice” dus.
#!/bin/bash# # Switching on or off light at home # bartjan@pc-mania.nl - 08 Mar 2018 snmp_exec="/usr/bin/snmpset" function check_reqs { if [ ! -f $snmp_exec ]; then echo "Error: snmpset executable not found.." echo "" exit 1 fi } function show_help { echo "Error: incorrect syntax.." echo "Usage: ./lights.sh [on|off]" echo "" } function switch { # 1st arg is outlet nr (integer) # 2nd arg options: on / off if [ $2 == "on" ]; then ${snmp_exec} -v2c -cpublic 192.168.1.251 1.3.6.1.4.1.318.1.1.4.4.2.1.3.${1} i 1 1>/dev/null 2>&1 elif [ $2 == "off" ]; then ${snmp_exec} -v2c -cpublic 192.168.1.251 1.3.6.1.4.1.318.1.1.4.4.2.1.3.${1} i 2 1>/dev/null 2>&1 fi } # Start the program check_reqs if [ ! $1 ]; then show_help exit 1 fi if [ $1 == "on" ]; then echo "Iluminate" switch 1 on switch 8 on elif [ $1 == "off" ]; then echo "Deluminate" switch 1 off switch 8 off else show_help exit 1 fi
De output op de cli is vanzelf sprekend. De cronjob zelf voert de output naar dev/null.
Nu kwam het zo naar boven dat in de herfst de tijden van de job in cron verschuiven. Elke keer dit aanpassen is suf en dat kan slimmer. Ik ben al een ruime tijd veel meer met Python bezig en dat bevalt erg goed. Ik heb een script geschreven die tijden ophaalt via een API call bij een publieke dienst aan de hand van de fysieke locatie. Hiermee kan ik de crontab van de user ‘root’ op de OrangePi weer aanpassen. Deze gebruikt deze dus de handige module ‘python-crontab‘.
#!/usr/bin/python # # @author bartjan@pc-mania.nl # Oct-6,2018 import requests import json import smtplib import sys import time from crontab import CronTab link = 'https://api.sunrise-sunset.org/json?lat=51.840449&lng=-4.972762?&formatted=0' localtime = time.localtime() def time_of(input): # Get the JSON output from the API try: data = requests.get(link).text except Exception: sendmail("Failed to connect to API") sys.exit() data = json.loads(data) # Fetch the wanted time try: time = str(data['results'][input]).split('T')[1].split('+')[0] except Exception: sendmail("No usable data is returned, keeping old time") sys.exit() return time def reset_crontab(minute,hour): cron = CronTab(user='root') # Check and remove the old job try: for job in cron.find_command('lights.sh on'): job.delete() except Exception: sendmail("Old cron job not found, stopping update") sys.exit() # Set the new job at the given time job = cron.new(command='/bin/bash /root/scripts/lights.sh on >/dev/null 2>&1') job.minute.on(minute) job.hour.on(hour) # Save job try: cron.write() except Exception: sendmail("Writing new cron failed") sys.exit() def sendmail(msg): msg = "Subject: sunset tool warning" + "\n\n" + msg server = smtplib.SMTP('smtp.yourisp.org',25) server.sendmail('you@domain.net','johndoe@somedomain.com',msg) ### # Get new time and split in hour/minute time = time_of('nautical_twilight_end') hour = time.split(':')[0] if not localtime.tm_isdst: # Correct daylight savings hour = hour - 1 minute = time.split(':')[1] # Update (so reset) the cronjob reset_crontab(minute,hour)
Dit script draait sowieso ook in de crontab van dezelfde user ‘root’. Dit alleen 1x per dag om 06.00, om te job voor diezelfde dag goed te zetten. De gewenste tijd is aan te passen door de parameter “time” te veranderen. De API call geeft namelijk al deze velden terug (formatted):
{ "results": { "sunrise":"6:30:51 AM", "sunset":"5:44:52 PM", "solar_noon":"12:07:51 PM", "day_length":"11:14:01", "civil_twilight_begin":"5:56:38 AM", "civil_twilight_end":"6:19:05 PM", "nautical_twilight_begin":"5:16:49 AM", "nautical_twilight_end":"6:58:54 PM", "astronomical_twilight_begin":"4:36:17 AM", "astronomical_twilight_end":"7:39:26 PM" }, "status":"OK" }
Of zonder format, de toevoeging ?&formatted=0 in de url zoals ik nu gebruik (scheelt een extra stapel stappen om naar 24-uurs tijd om te zetten):
{ "results": { "sunrise":"2018-10-08T06:34:22+00:00", "sunset":"2018-10-08T17:40:13+00:00", "solar_noon":"2018-10-08T12:07:17+00:00", "day_length":39951, "civil_twilight_begin":"2018-10-08T06:00:05+00:00", "civil_twilight_end":"2018-10-08T18:14:30+00:00", "nautical_twilight_begin":"2018-10-08T05:20:18+00:00", "nautical_twilight_end":"2018-10-08T18:54:17+00:00", "astronomical_twilight_begin":"2018-10-08T04:39:57+00:00", "astronomical_twilight_end":"2018-10-08T19:34:38+00:00" }, "status":"OK" }
Dus, nu past de cronjob zichzelf aan en zorgt dat de 2 lichten rondom het tv-meubel aangaan als het begint te schemeren en ik hoef niet meer in te loggen via SSH en crontab -e te doen en de tijd per x-dagen aan te passen.
De ‘nautical_twilight’ is een andere benadering van wanneer het donker word. Lees anders even ook deze pagina voor meer informatie.