wtorek, 27 czerwca 2017

Licznik błyskawic w Domoticz. Wpis nieaktualny - serwis nie działa.

Dzień dobry!

Dzisiaj kolejny skrypt w stylu 'nie jest mi to do niczego potrzebne, ale skoro można, to czemu nie'...

Ponownie, korzystając z uprzejmości użytkowników forum Domoticz, skonfigurowałem i uruchomiłem program, który odczytuje ze strony ilość wyładowań atmosferycznych w zadanym dystansie.

Edytowane: niestety strona www.onweerdetectie.com nie udostępnia informacji o błyskawicach. Zostawiam jednak wpis, może komuś się przyda do nauki Pythona.

Instalacja i konfiguracja jest prosta i szybka. W sumie jedyne co musimy zrobić, to założyć wirtualny czujnik (czyli najpierw zakładka hardware, później Create Virtual Sensors).



Ważne jest, aby skonfigurować zmienne server, port, deviceIdx, distanceRange. Jeżeli w Domoticz macie skonfigurowane koordynaty GPS, skrypt je stamtąd pobierze. Jeśli nie - trzeba je podać ręcznie. Moim zdaniem jednak i tak są potrzebne, aby mieć informację o wschodach/zachodach słońca.

Poniżej skrypt do wklejenia i zmiany:

# Following libraries in python are needed : json, yaml,math,time,requests
# This script will load an external json file that contact for europe the lightning information and will send it to Domoticz when it's
# inside the distance range

import math
import requests
import json
import os
from datetime import datetime

# Domoticz server settings
server = "http://192.168.1.200"
port = 80
deviceIdx = 154

# Location to import the lightning info
jsonUrl = "http://www.onweerdetectie.com/domoticz_bo.json"

# GPS location and distance to calculate
#latHome = xx.xxxxxx
#lngHome = xx.xxxxxx
distanceRange = 10  # Distance in km

# Try to get GPS location from domoticz
try:
    data = json.loads(
        requests.get(
            "%s:%d/json.htm?type=settings" %
            (server, port)).content)
    latHome = float(data['Location']['Latitude'])
    lngHome = float(data['Location']['Longitude'])
except:
    pass


# Location distance calculation

def distance(lat1, lng1, lat2, lng2):
    radius = 6371

    dLat = (lat2 - lat1) * math.pi / 180
    dLng = (lng2 - lng1) * math.pi / 180

    lat1 = lat1 * math.pi / 180
    lat2 = lat2 * math.pi / 180

    val = math.sin(dLat / 2) * math.sin(dLat / 2) + math.sin(dLng / 2) * \
        math.sin(dLng / 2) * math.cos(lat1) * math.cos(lat2)
    ang = 2 * math.atan2(math.sqrt(val), math.sqrt(1 - val))
    return radius * ang

last = 0
if os.path.exists("/tmp/last_lightning.txt"):
    f = open("/tmp/last_lightning.txt")
    last = int(f.read())
    f.close()

z = requests.get(jsonUrl)
data = json.loads(z.content)
value = 0
ignored = 0
for pos in data:
    time_, lat, lng = pos
    distanceBetween = distance(latHome, lngHome, lat, lng)
    if (distanceBetween <= distanceRange):
        if (time_ > last):
            value += 1
        else:
            ignored += 1

f = open("/tmp/last_lightning.txt", "w")
f.write(str(time_))
f.close()

print ("Found %d matches -- %s" %
       (value, datetime.strftime(datetime.now(), "%c")))
print ("%d old matches were ignored -- %s" %
       (ignored, datetime.strftime(datetime.now(), "%c")))

requests.get("%s:%d/json.htm?type=command&param=udevice&idx=%s&svalue=%d" % (server, port, deviceIdx, value))

Ja zapisałem go w /home/pi/domoticz/scripts/python/lightning.py

Później wpis do cron, wygodniej było mi go uruchamiać co 15 minut.

crontab -e

*/15 * * * * sudo python /home/pi/domoticz/scripts/python/lightning.py

Działa, cieszy.


poniedziałek, 12 czerwca 2017

Czas drogi do pracy/domu w Domoticz


Tym razem mała, przydatna ciekawostka dla osób, które dojeżdżają do pracy trochę dalej niż kilka kilometrów - podawanie czasu dojazdu jako element w Domoticz. Za przykładem użytkownika Mastair z forum Domoticz.

Idea bardzo mi się spodobała, szczególnie dla żony, która do pracy na kilkadziesiąt kilometrów. Oczywiście można odpalić Google Maps i sprawdzić w nich, ale planując tablet na ścianę z Domoticz i kalendarzem naszej rodziny - taki gadżet może być dla niej przydatny.

Na 'dzień dobry' będziemy potrzebować zarejestrowania się jako Google developer i pozyskania klucza do API (tak ogólnie - interfejs programistyczny). Polling interval (czas co jaki jest odpytywany Google) nie powinien być zbyt mały, ponieważ bezpłatne jest 2500 zapytań dziennie.

https://developers.google.com/maps/documentation/directions/get-api-key

Lub posługujemy się kodem jak poniżej.

"""
<plugin key="TravelTimes" name="Travel Times" author="mastair" version="1.0.0">
    <params>
        <param field="Mode1" label="From address" width="200px" required="true"/>
        <param field="Mode2" label="To address" width="200px" required="true"/>
        <param field="Mode5" label="Google API Key" width="200px" required="true"/>
        <param field="Mode6" label="Polling interval (s)" width="40px" required="true"/>
    </params>
</plugin>
"""
import Domoticz
import json
import urllib.request
import urllib.parse

#variables
mode            = "driving"
directionsURL   = "https://maps.googleapis.com/maps/api/directions/json?origin=%s&destination=%s=&transit_mode=driving&departure_ti$
defaultPollingInterval = 120

def onStart():
    Domoticz.Debug("onStart called")

    if (len(Devices) == 0):
        Domoticz.Device(Name="Travel time", Unit=1, TypeName="Custom", Options={"Custom": "1;minutes"}).Create()
        Domoticz.Device(Name="Travel delay", Unit=2, TypeName="Custom", Options={"Custom": "1;%"}).Create()

    Domoticz.Heartbeat(pollingInterval())
    return True

def onHeartbeat():
    updateSensors()
    return True

def updateSensors():
    try:
        Domoticz.Debug("getDelay called")

        # Call Directions API
        url = directionsURL % (urllib.parse.quote(fromAddress()), urllib.parse.quote(toAddress()), apiKey())
        request = urllib.request.urlopen(url)
        data = json.loads(request.read().decode('utf-8'))

        if "error_message" in data:
            Domoticz.Error("Error retrieving travel times from Google Maps API: %s" % data["error_message"])
            return

        # Get durations
        normal_duration = int(data["routes"][0]["legs"][0]["duration"]["value"]/60.0)
        current_duration = int(data["routes"][0]["legs"][0]["duration_in_traffic"]["value"]/60.0)
        delay = round((float)(current_duration - normal_duration)/normal_duration*100)

        # Update devices
        if 1 in Devices:
            Devices[1].Update(nValue = current_duration, sValue = str(current_duration))

        if 2 in Devices:
            Devices[2].Update(nValue = delay, sValue = str(delay))
    except:
        Domoticz.Error("Error retrieving travel times from Google Maps API")

####### GETTERS FOR PARAMETERS ########
def pollingInterval():
    try:
        return int(Parameters["Mode6"])
    except:
        Domoticz.Error("Error converting polling interval to integer, using %s seconds as polling interval" %defaultPollingInterval)
        return defaultPollingInterval

def fromAddress():
    return Parameters["Mode1"]

def toAddress():
    return Parameters["Mode2"]

def apiKey():
    return Parameters["Mode5"]

############## NOT USED ##############
def onStop():
    return True

def onConnect(Status, Description):
    return True

def onMessage(Data, Status, Extra):
    return True

def onCommand(Unit, Command, Level, Hue):
    return True

def onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile):
    return True

def onDisconnect():
    return True


Zapisujemy na przykład w /home/pi/domoticz/plugins/TravelTimes pod nazwą plugin.py.

Później jeszcze nadanie odpowiednich praw:

sudo chmod 755 /home/pi/domoticz/plugins/TravelTimes/plugin.py

Konieczny jest restart Domoticz, aby pojawił się nowy dodatek. Gdy już będziemy go mieli, po prostu wpisujemy:
- Skąd (zasady identyczne jak przy wpisywaniu adresów w Google maps)
- Dokąd
- Klucz API Google
- Czas, co jaki Domoticz ma odpytywać Google