Pushover-Benachrichtigungen mit HPCL versenden

Programmierung der HomeMatic CCU mittels contronics homeputer CL

Moderator: Co-Administratoren

Antworten
Familienvater
Beiträge: 7151
Registriert: 31.12.2006, 15:18
System: Alternative CCU (auf Basis OCCU)
Wohnort: Rhein-Main
Danksagung erhalten: 35 Mal

Pushover-Benachrichtigungen mit HPCL versenden

Beitrag von Familienvater » 03.03.2013, 18:28

Moin,

ich habe mich mal hingesetzt und ein Pushover-Modul für HPCL geschrieben.

Pushover wurde hier http://homematic-forum.de/forum/viewtop ... 31&t=11579 vorgestellt
Vorraussetzung ist curl auf der ccu http://homematic-forum.de/forum/viewtop ... 326#p35326
Des weiteren gehe ich davon aus, das ein USB-Stick in der CCU steckt und dort das Modul drauf rumschreiben darf. Wenn kein Stick in der CCU ist, ist das auch nicht schlimm, dann wird das tempfs (Ramdisk) an dieser Stelle genutzt.

Zur Vorgehensweise:
Das Modul m_URLEncode codiert Sonderzeichen, so das diese im POST von curl übertragen werden können. (curl kann das im Prinzip auch selbst, aber ich habe es nicht geschafft, das dann ein ä auch als ä ankam anstatt eines ?...). Die zu Codierende Nachricht wird in die Variable m_URLEncode.ToEncode geschrieben, dann das Modul ausgeführt und das Ergebnis kann in m_URLEncode.Encoded abgeholt werden. Die Codierung erfolgt aber automatisch aus m_SendPushover.

m_SendPushover hat die folgenden Eingangsparameter:
strAppToken(Zeichen): Der Applikation-Token, der muss 30 Byte lang sein
strUserToken(Zeichen): Der User-Token, der muss auch 30 Byte lang sein
strMessage(Zeichen): Die eigentliche Nachricht, die verschickt werden soll, kann Sonderzeichen enthalten (soweit diese in m_URLEncode vorgesehen sind)
strTitle(Zeichen): Der Titel der Nachricht (Nachricht und Titel zusammen dürfen uncodiert nicht länger als 512 Byte sein)
strSound(Zeichen): Optional, welchen Sound soll der Pushover Client spielen

lngPriority(Zahl): Optional, Priorität der Nachricht (-1 bis 2)

Nur für Priorität 2 (Emergency) notwendig
lngExpire(Zahl): Sekunden, die der Pushover Client versucht, die Nachricht zu verkünden (max. 86400 Sekunden)
lngRetry(Zahl): Sekunden, die der Pushover zwischen den Benachrichtungen wartet (min. 30 Sekunden)

strFehler(Zeichen): Evtl. Fehlermeldung beim Überprüfen der Parameter auf Fehler

Es gibt weitere Variablen im Modul, die eigentlich nicht umgestellt werden brauchen:
lngVerbose(Zahl): 0 oder 1, am Anfang evtl. auf 1 stellen, dann ist die Ausgabe von curl extrem ausführlich
strPfad(Zeichen): Sollte eigentlich auf /var/datadisk/ stehen, falls jemand exlizit ein anderes Verzeichnis nutzen will, kann er es hier einstellen (der Charme an diesem Verzeichnis ist die einfache Möglichkeit, sich die Dateien per Aufruf von http://[IP-Der-CCU]/addons/contronics/files/workfiles.cgi im Browser anzeigen zu lassen)


Es werden für jede Nachricht 4 Dateien erstellt:
po_message_*, po_title_*
Beim Versenden werden die Ausgaben von curl in Dateien umgeleitet:
po_send_result_* sowie po_send_err_*

Warum immer _*? Da evtl. mehrere Pushover-Clients mit unterschiedlichen UserTokens zu erreichen sind, habe ich einen Round-Robin-Zähler eingebaut, der die Zahlen von 1 bis 9 durchläuft, damit hat man ein paar Stunden/Tage Zeit, eventuellen Problemen bei der Benachrichtigung nachzugehen, und auch das "gleichzeitige" Versenden von mehreren Nachrichten sollte so funktionieren. Startprogramm wartet nicht, bis curl beendet ist, und bei mir dauert es 2-3 Sekunden, bis curl fertig ist.
Wenn das ganze funktioniert, kann man auch die Ausgabe nach /dev/null umleiten...

Es ist keine Auswertung des Ergebnisses implementiert, weil man sicherheitshalber min. 5 Sekunden nach dem startprogramm warten müsste, bevor man das Ergebnis zurücklesen kann. Und für das Zurücklesen müsste man auch die Ergebnisdatei noch umbauen...

Der Code wurde mit den SPG-Tools extrahiert....

Code: Alles auswählen

//! ============================================================
//! OBJEKT m_SendPushover
//! ============================================================
//! OBJEKT-TYP              : Makro
//! BEZEICHNUNG             : m_SendPushover
//! STARTWERT               :
//! ------------------------------------------------------------
//! AUSFÜHRUNGSINTERVALL    : nein
//! AUSFÜHRUNG BEI EINGABE  : ja
//! AUSFÜHRUNG BEI EMPFANG  : nein
//! AUSFÜHRUNG BEI ÄNDERUNG : nein
//! ------------------------------------------------------------
//! KONF.:ALLV=0/MAV=1
//!
//! ============================================================
//! VARIABLENDEFINITIONEN
//! ============================================================
//! NAME                TYP                 STARTWERT
//! ------------------------------------------------------------
//! lngExpire           Zahl                0
//! lngPriority         Zahl                0
//! lngRetry            Zahl                0
//! lngRoundRobin       Zahl                0
//! lngVerbose          Zahl                0
//! strAppToken         Zeichen
//! strFehler           Zeichen
//! strMessage          Zeichen
//! strParams           Zeichen
//! strPfad             Zeichen             /var/datadisk/
//! strRoundRobin       Zeichen
//! strSound            Zeichen
//! strTemp             Zeichen
//! strTitle            Zeichen
//! strUserToken        Zeichen
//! strZeile            Zeichen

// SendPushover, Version 1.0, 2012-03-03 Familienvater

strFehler := ""
strParams := ""

lngRoundRobin := lngRoundRobin +1
wenn lngRoundRobin > 9 oder lngRoundRobin < 1 dann
  lngRoundRobin := 1
endewenn

strRoundRobin := "_" + lngRoundRobin

// App-Token auf Länge prüfen
wenn textlänge(strAppToken)=30 dann
  strParams := strParams + " -d token=" + strAppToken
sonst
  strFehler := "Länge AppToken falsch!"
  gehezu Ende
endewenn

// User-Token auf Länge prüfen
wenn textlänge(strUserToken)=30 dann
  strParams := strParams + " -d user=" + strUserToken
sonst
  strFehler := "Länge UserToken falsch!"
  gehezu Ende
endewenn

// Priority -1=Silent, 0=Normal, 1=High, 2=Emergency
wenn lngPriority zwischen -1 und 2 dann
  strParams := strParams + " -d priority=" + lngPriority
sonst
  strFehler := "Unbekannte Priorität!"
  gehezu Ende
endewenn

// Optional: zu spielender Sound, Liste der aktuell verfügbaren Sounds:https://api.pushover.net/1/sounds.json
// Wer sich die Mühe machen will, könnte das mit getsite Abfragen und dann zerlegen...
wenn strSound <> "" dann
  strParams := strParams + " -d sound=" + strSound
endewenn

// Optional: Retry bei Priority=2, min. 30 Sekunden
wenn lngpriority=2 und lngRetry>0 dann
  wenn lngRetry<30 dann
    lngRetry := 30
  endewenn
  strParams := strParams + " -d retry=" + lngRetry
endewenn

// Optional: Expire bei Priority=2, max. 86400 Sekunden
wenn lngpriority=2 und lngExpire>0 dann
  wenn lngExpire>86400 dann
    lngExpire := 86400
  endewenn
  strParams := strParams + " -d expire=" + lngExpire
endewenn

wenn strMessage<>"" dann

  // -> Message reingeben .ToEncode
  m_URLEncode.ToEncode := strMessage

  aufrufen(m_URLEncode)
  // <- UrlEncodierte Nachricht abholen .Encoded

  strTemp:="po_message"+strRoundRobin
  löschedatei(strTemp)

  // -> UrlEncodierte Nachricht in Textdatei schreiben
  // 0 -> KEIN Zeilenvorschub am Ende
  strZeile := "message="+m_URLEncode.Encoded
  schreibedatei(strTemp,strZeile,0)
  schliessedateien

  strParams := strParams + " --data @"+strPfad+"po_message"+strRoundRobin
endewenn

wenn strTitle<>"" dann

  // -> Title reingeben
  m_URLEncode.ToEncode := strTitle

  aufrufen(m_URLEncode)
  // <- UrlEncodierte Title abholen

  strTemp:="po_title"+strRoundRobin
  löschedatei(strTemp)

  // -> UrlEncodierte Title in Textdatei schreiben
  // 0 -> KEIN Zeilenvorschub am Ende
  strZeile := "title="+m_URLEncode.Encoded
  schreibedatei(strTemp,strZeile,0)
  schliessedateien

  strParams := strParams + " --data @"+strPfad+"po_title"+strRoundRobin
endewenn

// Gerade am Anfang oder zur Fehlersuche empfiehlt es sich, lngVerbose auf 1 zu stellen,
// dann gibt es in der Ausgabedatei zu dem Job viele Infos über den Verbindungsauf, die gesendeten Daten etc.
wenn lngVerbose >0 dann
  strParams := strParams + " -v --trace-ascii -"
endewenn

// Aufruf curl zusammenbauen
// curl -s
// -k                                         -> KEINE SSL-Zertifikatsüberprüfung durchführen (/etc/ssl/... gibt es nicht!/Read-Only!)
// -d token=xYz.30ByteTokenvonPushOver.yZ     -> APP-Token
// -d user=xYz.30ByteTokenvonPushOver.yZ      -> User-Token
// -d priority=-1/0/1/2                       -> Prioritäten der Nachrichten
// -d sound=
// -d device=                                 -> Zur Zeit nicht in diesem Script implementiert...
// --data-binary @/var/datadisk/po_message_*  -> In der Datei po_message_* ist die URL-Encodierte Nachricht enthalten
// --data-binary @/var/datadisk/po_title_*    -> In der Datei po_title_* ist der URL-Encodierte Titel enthalten
// DEBUG: -v                                  -> VERBOSE
// DEBUG: --trace-ascii -                     -> Alles rausschreiben, was so gesendet und empfangen wurde...
// https://api.pushover.net/1/messages.json   -> Und das ganze an diese Adresse schicken

// Mit dieser Zeile wird die normale Ausgabe in eine Datei po_send_result_* umgeleitet,
// Auftretende Fehler werden in die Datei po_send_err_* umgeleitet
strParams := "/bin/curl -s -k " + strParams + " https://api.pushover.net/1/messages.json >"+strPfad+"po_send_result"+strRoundRobin+" 2>"+strPfad+"po_send_err"+strRoundRobin

// ALTERNATIV: Wer keine Result/Err Dateien braucht, kann einfach die Ausgabe nach /dev/null umleiten
// strParams := "/bin/curl -s -k " + strParams + " https://api.pushover.net/1/messages.json >/dev/null 2>/dev/null"

startprogramm(strParams)

// Noch eine Alternative, wenn es Probleme geben sollte:
// Bei dieser Methode wird ein Shell-Script erzeugt, was dann später aufgerufen werden kann
// strTemp:="./po_send"+strRoundRobin+".sh"
// löschedatei(strTemp)
// strZeile := "#!/bin/sh"
// schreibedatei(strTemp,strZeile,1)
// schreibedatei(strTemp,strParams,1)
// schliessedateien

// strtemp:=strPfad+strTemp
// startprogramm(strTemp)

Ende:
// Wieder alles zurückstellen
lngPriority := 0
lngRetry := 0
lngExpire := 0
strSound := ""
strUserToken := ""
strAppToken := ""
strRoundRobin := ""

// strFehler Nicht löschen, enthält evtl. Probleme
verlassen

Code: Alles auswählen

//! ============================================================
//! OBJEKT m_URLEncode
//! ============================================================
//! OBJEKT-TYP              : Makro
//! BEZEICHNUNG             : m_URLEncode
//! STARTWERT               :
//! ------------------------------------------------------------
//! AUSFÜHRUNGSINTERVALL    : nein
//! AUSFÜHRUNG BEI EINGABE  : ja
//! AUSFÜHRUNG BEI EMPFANG  : nein
//! AUSFÜHRUNG BEI ÄNDERUNG : nein
//! ------------------------------------------------------------
//! KONF.:ALLV=0/MAV=0
//!
//! ============================================================
//! VARIABLENDEFINITIONEN
//! ============================================================
//! NAME                TYP                 STARTWERT
//! ------------------------------------------------------------
//! Encoded             Zeichen
//! strTemp             Zeichen
//! ToEncode            Zeichen

// URLEncode, Version 1.0, 2012-03-03 Familienvater
// Wer weitere Sonderzeichen benutzten möchte, kann z.B. hier die Codierung erfahren: http://www.url-encode-decode.com/

strTemp := ToEncode
Encoded := ""

// '%' = asc(37)
strTemp := Ersetzen(strTemp, "%", "%25")

// '<<' = Neue Zeile, eigentlich asc(10)
strTemp := Ersetzen(strTemp, "<<", "%0A")

// '!' = asc(33)
strTemp := Ersetzen(strTemp, "!", "%21")

// '"' = asc(34) <- Wenn jemand unbedingt das Doppelte Anführungszeichen in Nachrichten brauch,
//                  muss er sich dafür z.B. '' in die Nachricht schreiben und dann entsprechend das ersetzen
// strTemp := Ersetzen(strTemp, """, "%22")

// '$' = asc(36)
strTemp := Ersetzen(strTemp, "$", "%24")
// '%' = asc(37)
strTemp := Ersetzen(strTemp, "&", "%26")
// '/' = asc(47)
strTemp := Ersetzen(strTemp, "/", "%2F")
// '(' = asc(40)
strTemp := Ersetzen(strTemp, "(", "%28")
// ')' = asc(41)
strTemp := Ersetzen(strTemp, ")", "%29")
// '=' = asc(61)
strTemp := Ersetzen(strTemp, "=", "%3D")
// '?' = asc(63)
strTemp := Ersetzen(strTemp, "?", "%3F")
// '+' = asc(43)
strTemp := Ersetzen(strTemp, "+", "%2B")
// '*' = asc(42)
strTemp := Ersetzen(strTemp, "*", "%2A")
// '#' = asc(35)
strTemp := Ersetzen(strTemp, "#", "%23")
// '-' = asc(45)
strTemp := Ersetzen(strTemp, "-", "%2D")
// '_' = asc(95)
strTemp := Ersetzen(strTemp, "_", "%5F")
// '.' = asc(46)
strTemp := Ersetzen(strTemp, ".", "%2E")
// ',' = asc(44)
strTemp := Ersetzen(strTemp, ",", "%2C")
// ';' = asc(59)
strTemp := Ersetzen(strTemp, ";", "%3B")
// ':' = asc(58)
strTemp := Ersetzen(strTemp, ":", "%3A")
// '<' = asc(60)
strTemp := Ersetzen(strTemp, "<", "%3C")
// '>' = asc(62)
strTemp := Ersetzen(strTemp, ">", "%3E")
// '°' = asc(176)
strTemp := Ersetzen(strTemp, "°", "%C2%B0")
// '~' = asc(126)
strTemp := Ersetzen(strTemp, "~", "%7E")
// 'ä' = asc(228)
strTemp := Ersetzen(strTemp, "ä", "%C3%A4")
// 'ö' = asc(246)
strTemp := Ersetzen(strTemp, "ö", "%C3%B6")
// 'ü' = asc(252)
strTemp := Ersetzen(strTemp, "ü", "%C3%BC")
// 'Ä' = asc(196)
strTemp := Ersetzen(strTemp, "Ä", "%C3%84")
// 'Ö' = asc(214)
strTemp := Ersetzen(strTemp, "Ö", "%C3%96")
// 'Ü' = asc(220)
strTemp := Ersetzen(strTemp, "Ü", "%C3%9C")
// 'ß' = asc(223)
strTemp := Ersetzen(strTemp, "ß", "%C3%9F")

// ' ' = asc(32)
strTemp := Ersetzen(strTemp, " ", "%20")

Encoded := strTemp

strTemp := ""
ToEncode := ""
Noch ein Beispiel, wie eine Nachricht versendet werden kann (Ich habe bei mir ein extra Modul mit Namen const angelegt, dort sind z.B. die ganzen Token hinterlegt)

Code: Alles auswählen

m_SendPushover.strAppToken := const.AppTokenWarning
m_SendPushover.strUserToken := const.UserTokenPapa
m_SendPushover.strMessage := "Das hier ist der Nachrichtentext.<<Das hier geht in eine neue Zeile!<<Und es darf mit Sonderzeichen äöüÄÖÜß° hantiert werden :-)"
m_SendPushover.strTitle := "Hallo Welt, das Makro geht!"
m_SendPushover.lngPriority := 1
m_SendPushover.strSound := "spacealarm"
aufrufen(m_SendPushover)
So, genug geschrieben, viel Spaß ;-)

der Familienvater

Antworten

Zurück zu „homeputer CL“