Plugins
De applicatie staat je toe om plugins te maken en te koppelen, op bepaalde gebeurtenissen.
Inhoud
Configuratie
Je kan plugins maken in hun eigen bestand in dsmr_plugins/modules/plugin_naam.py
, waar plugin_naam
de naam van je plugin is.
Zorg er voor dat plugin_naam
,
zonder hoofdletters is (
plugin_naam
en nietPLUGIN_NAAM
),geen spaties of koppeltekens bevat, gebruik daarvoor underscores en begin de naam niet met een cijfer.
Zie ook
Voeg het dotted pad in als DSMRREADER_PLUGINS
env var. Voor meer informatie, zie DSMRREADER_PLUGINS in Env-instellingen.
Je plugin-bestand wordt eenmalig geimporteerd, dus zorg ervoor dat je gebeurtenissen koppelt die je wilt volgen.
Tot slot, zorg ervoor dat je de applicatie herstart om de wijzigingen door te voeren. Voer als root of sudo-gebruiker dit uit:
sudo supervisorctl restart all
Gebeurtenissen / Signalen
Deze worden verstuurd door ofwel het Django framework ofwel de applicatie zelf.
dsmr_backend.signals.backend_called
Aangeroepen bij elke iteratie van de backend. Gebruik dit terughoudend, gezien het alle backend-acties kan blokkeren wanneer het verkeerd gebruikt wordt.
dsmr_pvoutput.signals.pvoutput_upload
Aangeroepen door dsmr_pvoutput vlak voor het uploaden van gegevens naar PVOutput. De data
kwarg bevat de gegevens die verstuurd worden.
dsmr_datalogger.signals.raw_telegram
Aangeroepen door dsmr_datalogger wanneer er een telegram ontvangen of uitgelezen wordt. De data
kwarg bevat de ruwe string met het telegram.
dsmr_notification.signals.notification_sent
Aangeroepen door dsmr_notification vlak nadat een notificatie verstuurd wordt. De title
kwarg bevat de titel van de notificatie, message
bevat het inhoudelijke bericht.
django.db.models.signals.post_save
Aangeroepen door Django bij het opslaan van nieuwe databaserecords. Kan gekoppeld worden aan bijvoorbeeld het DayStatistics
model, om dagelijkse statistieken ergens anders te verwerken.
Overige
Meer signalen/gebeurtenissen zijn beschikbaar voor gebruik, echter wees voorzichtig bij het gebruiken van Django save-signalen, aangezien het de performance kan beïnvloeden.
Voorbeelden:
Voorbeeld #1: Upload gegevens naar een tweede PVOutput-account
Dit is een voorbeeld van issue #407, met het verzoek om gegevens te uploaden naar een tweede PVOutput-account.
Zie ook
DSMRREADER_PLUGINS configuratie:
DSMRREADER_PLUGINS=dsmr_plugins.modules.secondary_pvoutput_upload
Plugin bestand dsmr_plugins/modules/secondary_pvoutput_upload.py
(nieuw bestand):
import requests
from django.dispatch import receiver
from dsmr_pvoutput.models.settings import PVOutputAddStatusSettings
from dsmr_pvoutput.signals import pvoutput_upload
@receiver(pvoutput_upload)
def handle_secondary_pvoutput_upload(**kwargs):
print(' - Uploading the same data to PVOutput using plugin: {}'.format(kwargs['data']))
response = requests.post(
PVOutputAddStatusSettings.API_URL,
headers={
'X-Pvoutput-Apikey': 'XXXXX',
'X-Pvoutput-SystemId': 'YYYYY',
},
data=kwargs['data']
)
if response.status_code != 200:
print(' [!] PVOutput upload failed (HTTP {}): {}'.format(response.status_code, response.text))
Let op
N.B.: De variablen XXXXX
en YYYYY
vervang je door de API-credentials van je tweede PVOutput-account.
Voorbeeld #2: Doorsturen van ruwe telegram-gegevens naar een andere seriële poort
Dit is een voorbeeld van issue #557, wat ervoor zorgt dat je DSMR-telegrammen kunt doorsturen naar een andere seriële poort.
Zie ook
DSMRREADER_PLUGINS configuratie:
DSMRREADER_PLUGINS=dsmr_plugins.modules.forward_raw_telegram_to_serial
Plugin bestand dsmr_plugins/modules/forward_raw_telegram_to_serial.py
(nieuw bestand):
import serial
from django.dispatch import receiver
from dsmr_datalogger.signals import raw_telegram
import dsmr_datalogger.services.datalogger
@receiver(raw_telegram)
def handle_forward_raw_telegram_to_serial(**kwargs):
DEST_PORT = '/dev/ttyUSBvA'
connection_parameters = dsmr_datalogger.services.datalogger.get_dsmr_connection_parameters()
serial_handle = serial.Serial()
serial_handle.port = DEST_PORT
serial_handle.baudrate = connection_parameters['baudrate']
serial_handle.bytesize = connection_parameters['bytesize']
serial_handle.parity = connection_parameters['parity']
serial_handle.stopbits = serial.STOPBITS_ONE
serial_handle.xonxoff = 1
serial_handle.rtscts = 0
serial_handle.timeout = 1
serial_handle.write_timeout = 0.2
try:
serial_handle.open()
bytes_sent = serial_handle.write(bytes(kwargs['data'], 'utf-8'))
except Exception as error:
print(error)
else:
print(' >>> Sent {} bytes to {}'.format(bytes_sent, DEST_PORT))
serial_handle.close()
Let op
N.B.: Je moet de /dev/ttyUSBvA
variabele nog wijzigen naar de juiste seriële poort in je eigen situatie.
Voorbeeld #3: Doorsturen van ruwe telegram-gegevens naar een andere instantie van DSMR-reader, via de API
Dit kan behoorlijk handig zijn wanneer je meerdere instanties van DSMR-reader draait (bijvoorbeeld op een Raspberry en gespiegeld in de cloud).
Zie ook
DSMRREADER_PLUGINS configuratie:
DSMRREADER_PLUGINS=dsmr_plugins.modules.forward_raw_telegram_to_api
Plugin bestand dsmr_plugins/modules/forward_raw_telegram_to_api.py
(nieuw bestand):
import requests
import logging
from django.dispatch import receiver
from dsmr_datalogger.signals import raw_telegram
@receiver(raw_telegram)
def handle_forward_raw_telegram_to_api(**kwargs):
API_HOST = 'https://YOUR-DSMR-HOST' # Note: Check whether you use HTTP or SSL (HTTPS).
API_KEY = 'YOUR-API-KEY'
TIMEOUT = 5 # A low timeout prevents the application from hanging, when the server is unavailable.
try:
# Register telegram by simply sending it to the application with a POST request.
response = requests.post(
'{}/api/v1/datalogger/dsmrreading'.format(API_HOST),
headers={'X-AUTHKEY': API_KEY},
data={'telegram': kwargs['data']},
timeout=TIMEOUT
)
except Exception as error:
return logging.error(error)
if response.status_code != 201:
logging.error('Server Error forwarding telegram: {}'.format(response.text))
Let op
N.B.: De API_HOST
, API_KEY
en TIMEOUT
variabelen moet je nog wijzigen naar je eigen voorkeuren.
Voorbeeld #4: Doorsturen van DSMR-metingen in JSON-formaat naar een API
Gebruik dit om DSMR-metingen in JSON-formaat naar een (willekeurige) API door te sturen.
Zie ook
DSMRREADER_PLUGINS configuratie:
DSMRREADER_PLUGINS=dsmr_plugins.modules.forward_json_dsmrreading_to_api
Plugin bestand dsmr_plugins/modules/forward_json_dsmrreading_to_api.py
(nieuw bestand):
import requests
import json
from django.dispatch import receiver
from django.core import serializers
from django.utils import timezone
import django.db.models.signals
from dsmr_datalogger.models.reading import DsmrReading
@receiver(django.db.models.signals.post_save, sender=DsmrReading)
def handle_forward_json_dsmrreading_to_api(sender, instance, created, raw, **kwargs):
if not created or raw:
return
instance.timestamp = timezone.localtime(instance.timestamp)
if instance.extra_device_timestamp:
instance.extra_device_timestamp = timezone.localtime(instance.extra_device_timestamp)
serialized = json.loads(serializers.serialize('json', [instance]))
json_string = json.dumps(serialized[0]['fields'])
try:
requests.post(
'https://YOUR-DSMR-HOST/api/endpoint/',
data=json_string,
# A low timeout prevents DSMR-reader from hanging, when the remote server is unreachable.
timeout=5
)
except Exception as error:
print('forward_json_dsmrreading_to_api:', error)
Voorbeeld #5: Lees telegrammen uit de DSMRloggerWS API
Zie ook
DSMRREADER_PLUGINS configuratie:
DSMRREADER_PLUGINS=dsmr_plugins.modules.poll_dsmrloggerws_api
Plugin bestand dsmr_plugins/modules/poll_dsmrloggerws_api.py
(nieuw bestand):
import requests
from django.dispatch import receiver
from dsmr_backend.signals import backend_called
import dsmr_datalogger.services.datalogger
# Preverve a low timeout to prevent the entire backend process from hanging too long.
DSMRLOGGERWS_ENDPOINT = 'http://localhost/api/v1/sm/telegram'
DSMRLOGGERWS_TIMEOUT = 5
@receiver(backend_called)
def handle_backend_called(**kwargs):
response = requests.get(DSMRLOGGERWS_ENDPOINT,
timeout=DSMRLOGGERWS_TIMEOUT)
if response.status_code != 200:
print(' [!] DSMRloggerWS plugin: Telegram endpoint failed (HTTP {}): {}'.format(
response.status_code,
response.text
))
return
dsmr_datalogger.services.datalogger.telegram_to_reading(data=response.text)
Let op
Let op dat je mogelijk de waarde van http://localhost
moet bijwerken naar je eigen situatie.