Daten grafisch aufbereiten

Jetzt steh ich auch auf´m Schlauch 🤦‍♂️

1589627534584.png

Das ist dein Anfang vom Codebereich.

Dort muss ich das hier reinkopieren:

Code:
#!/usr/bin/env python3
# coding=utf-8
"""
*
* by Wenger Florian 2015-09-02
* wenger@unifox.at
*
* endless loop (until ctrl+c) displays measurement from SMA Energymeter
*
*
*  this software is released under GNU General Public License, version 2.
*  This program is free software;
*  you can redistribute it and/or modify it under the terms of the GNU General Public License
*  as published by the Free Software Foundation; version 2 of the License.
*  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
*  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*  See the GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License along with this program;
*  if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* 2018-12-22 Tommi2Day small enhancements
* 2019-08-13 datenschuft run without config
* 2020-01-04 datenschuft changes to tun with speedwiredecoder
*
*/
"""

import signal
import sys
#import smaem
import socket
import struct
from configparser import ConfigParser
from speedwiredecoder import *

# clean exit
def abortprogram(signal,frame):
    # Housekeeping -> nothing to cleanup
    print('STRG + C = end program')
    sys.exit(0)

# abort-signal
signal.signal(signal.SIGINT, abortprogram)


#read configuration
parser = ConfigParser()
#default values
smaserials = ""
ipbind = '0.0.0.0'
MCAST_GRP = '239.12.255.254'
MCAST_PORT = 9522
parser.read(['/etc/smaemd/config','config'])
try:
    smaemserials=parser.get('SMA-EM', 'serials')
    ipbind=parser.get('DAEMON', 'ipbind')
    MCAST_GRP = parser.get('DAEMON', 'mcastgrp')
    MCAST_PORT = int(parser.get('DAEMON', 'mcastport'))
except:
    print('Cannot find config /etc/smaemd/config... using defaults')

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', MCAST_PORT))
try:
    mreq = struct.pack("4s4s", socket.inet_aton(MCAST_GRP), socket.inet_aton(ipbind))
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
except BaseException:
    print('could not connect to mulicast group or bind to given interface')
    sys.exit(1)
# processing received messages
while True:
  emparts = {}
  emparts=decode_speedwire(sock.recv(608))
  # Output...
  # don't know what P,Q and S means:
  # http://en.wikipedia.org/wiki/AC_power or http://de.wikipedia.org/wiki/Scheinleistung
  # thd = Total_Harmonic_Distortion http://de.wikipedia.org/wiki/Total_Harmonic_Distortion
  # cos phi is always positive, no matter what quadrant
  print ('\n')
  print ('SMA-EM Serial:{}'.format(emparts['serial']))
  print ('-------Gesamt-------')
  print ('P: Verbrauch: {}W   Einspeisung: {}W '.format(emparts['pconsume'],emparts['psupply']))
  print ('S: Verbrauch: {}VA  Einspeisung: {}VA '.format(emparts['sconsume'],emparts['ssupply']))
  print ('Q: induktiv: {}var  kapazitiv: {}var '.format(emparts['qconsume'],emparts['qsupply']))
  print ('cos phi: {}°'.format(emparts['cosphi']))
  print ('Frequenz: {}Hz'.format(emparts['frequency']))
  print ('-------L1-------')
  print ('P: Verbrauch: {}W   Einspeisung: {}W '.format(emparts['p1consume'],emparts['p1supply']))
  print ('S: Verbrauch: {}VA  Einspeisung: {}VA '.format(emparts['s1consume'],emparts['s1supply']))
  print ('Q: ind: {}var       kap: {}var '.format(emparts['q1consume'],emparts['q1supply']))
  print ('U: {}V          I: {}A       cos phi: {}°'.format(emparts['u1'],emparts['i1'],emparts['cosphi1']))
  print ('-------L2-------')
  print ('P: Verbrauch: {}W   Einspeisung: {}W '.format(emparts['p2consume'],emparts['p2supply']))
  print ('S: Verbrauch: {}VA  Einspeisung: {}VA '.format(emparts['s2consume'],emparts['s2supply']))
  print ('Q: ind: {}var       kap: {}var '.format(emparts['q2consume'],emparts['q2supply']))
  print ('U: {}V          I: {}A       cos phi:{}°'.format(emparts['u2'],emparts['i2'],emparts['cosphi2']))
  print ('-------L3-------')
  print ('P: Verbrauch: {}W   Einspeisung: {}W '.format(emparts['p3consume'],emparts['p3supply']))
  print ('S: Verbrauch: {}VA  Einspeisung: {}VA '.format(emparts['s3consume'],emparts['s3supply']))
  print ('Q: ind: {}var       kap: {}var '.format(emparts['q3consume'],emparts['q3supply']))
  print ('U: {}V          I: {}A       cos phi: {}°'.format(emparts['u3'],emparts['i3'],emparts['cosphi3']))
  print ('Version: {}'.format(emparts['speedwire-version']))

Sry, ich checks nicht und dann aus print payload machen ?
 
Ganz genau. Wie gesagt habe ich mir das Skript nicht im Detail angeschaut und es kann sein, dass man noch ein paar Dinge ändern muss. Zudem habe ich mit Python bisher wenig bis gar keine Berührungspunkte gehabt, kann also bezüglich Syntax und dergleichen nichts sagen. Da müsste es aber ausreichend Infos bei Onkel Google geben. Node Red hat eine recht gute Community.
 
1589634275173.png


So stĂĽrzt es sofort ab, k.A. wo der/die Fehler sind.
 
Zum einen ist gleich als erstes eine Return Anweisung. Damit wird direkt das msg Objekt an den Ausgang gelegt und dann ist das Skript vorbei.

Zum anderen sehe ich eine while Schleife, die ebenfalls raus muss. Das Skript darf nur einen Durchlauf haben, also einmal starten, auslesen, ausgeben. Die Funktionalität der Schleife wird extern getriggert, über Node Red.
 
  • Gefällt mir
Reaktionen: Avenger84
stimmt, ganz vergessen, aber wieso stĂĽrzt bei solchen Fehlern gleich das ganze NR ab?
Wie kann man so (als Noob) programmieren ?
:pcangry:

Jetzt hat mir NR den ganzen Flow gelöscht, ich geb´s auf so kann man wirklich nicht arbeiten, trotzdem danke für die vergebene Müh.
 
Zuletzt bearbeitet:
Naja, was soll ich sagen? Als "Noob" kann man nicht den Anspruch haben, etwas programmieren zu können, ohne sich damit zu beschäftigen. Das ist jetzt nicht speziell an dich adressiert, weil du dich ja offensichtlich damit beschäftigst, aber eine Antwort auf deine Frage. Programmieren ist und bleibt Programmieren und selbst Scratch, das sich an Kinder und Jugendliche richtet, geht nicht ohne Einarbeitung, Lernwillen und Nachdenken.

In deinem Fall kann es sein, dass man das Skript für Node Red an einigen Stellen noch weiter anpassen müsste. Alternativ kann man das Skript mit einem exec node auch aufrufen wie in der Kommandozeile, muss dann jedoch den Output als String parsen. So oder so wirst du nicht mit Handauflegen ein Skript für die Konsole plötzlich grafisch aufbereiten können. Irgendwo musst du programmieren, das lässt sich gar nicht vermeiden. Soweit ist die KI noch nicht, dass man ihr einfach ein Skript in die Hand drückt und dann wird's plötzlich bunt und mit bewegten Bildchen ;)
 
Sobald ich nur mit c&p das Skript einfĂĽge:
1589707403393.png


stĂĽrzt NR ab - so kann Niemand arbeiten, beim besten Willen nicht.
Ich kann nicht mal was anpassen da es sofort abstĂĽrzt.
 
Wie ich schon sagte, man muss das Skript vermutlich weiter anpassen. Die while true Schleife ist beispielsweise per Definition eine Endlosschleife, durch die das Skript niemals endet und wenn das Skript niemals endet, kann Node Red offensichtlich nicht fortfahren, es hängt. Das ist nachvollziehbar. Der Abbruchmechanismus mit ctrl+c ist für Node Red natürlich nicht praktikabel, weil das Skript eben nicht in der Konsole läuft. Ergo muss an die Schleife entfernen und das Skript auf einmalige Ausführung umbauen. Die Funktionalität der Schleife wird dann über den zyklischen Aufruf des Inject Nodes (zB 1/s) nachgebildet.
 
Das war mein letzter Versuch:
Code:
import signal
import sys
import socket
import struct
from configparser import ConfigParser
from speedwiredecoder import *
parser = ConfigParser()
smaserials = ""
ipbind = '0.0.0.0'
MCAST_GRP = '239.12.255.254'
MCAST_PORT = 9522
parser.read(['/etc/smaemd/config','config'])
smaemserials=parser.get('SMA-EM', 'serials')
ipbind=parser.get('DAEMON', 'ipbind')
MCAST_GRP = parser.get('DAEMON', 'mcastgrp')
MCAST_PORT = int(parser.get('DAEMON', 'mcastport'))
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', MCAST_PORT))
mreq = struct.pack("4s4s", socket.inet_aton(MCAST_GRP), socket.inet_aton(ipbind))
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
emparts = {}
emparts=decode_speedwire(sock.recv(608))
var messunggesamtvebrauch= (emparts['pconsume'];
var gesamtvebrauch= { payload: messunggesamtvebrauch, topic="Verbrauch" };
return [gesamtvebrauch];

Mit dem Ergebnis:
Code:
17 May 19:25:30 - [info] Flows starten
17 May 19:25:30 - [info] [python3-function:Phyton3] Python function 'Phyton3' running on PID undefined
17 May 19:25:30 - [info] Flows gestartet
17 May 19:25:30 - [red] Uncaught Exception:
17 May 19:25:30 - Error: spawn python ENOENT
    at Process.ChildProcess._handle.onexit (internal/child_process.js:267:19)
    at onErrorNT (internal/child_process.js:469:16)
    at processTicksAndRejections (internal/process/task_queues.js:84:21)
 
Ihr vermischt da Python und JavaScript Code ...
Bei mir kommt auf Konsole direkt ein Meldung wegen Syntaxfehlern unten bei messunggesamtvebrauch.
var gibts bei Python nicht und den Import from speedwiredecoder import * scheint es auch nicht zu moegen.

Ich wuerde dir empfehlen das Script per exec-Block auszufuehren und dann die Standard-Ausgabe zu verarbeiten.

Du kannst auch die Ausgabe vom Skript anpassen in dem du emparts (bzw. den Rueckgabewert von decode_speedwire) als JSON ausgibst.
Dazu muesstest du einfach import json am Anfang reinmachen. Dann unten die ganzen prints() und das while True: weghauen und gegen das folgende ersetzen:

Python:
json.dumps(decode_speedwire(sock.recv(608)))

Sieht dann wie folgt aus:
Python:
#!/usr/bin/env python3
# coding=utf-8
"""
*
* by Wenger Florian 2015-09-02
* wenger@unifox.at
*
* endless loop (until ctrl+c) displays measurement from SMA Energymeter
*
*
*  this software is released under GNU General Public License, version 2.
*  This program is free software;
*  you can redistribute it and/or modify it under the terms of the GNU General Public License
*  as published by the Free Software Foundation; version 2 of the License.
*  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
*  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*  See the GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License along with this program;
*  if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* 2018-12-22 Tommi2Day small enhancements
* 2019-08-13 datenschuft run without config
* 2020-01-04 datenschuft changes to tun with speedwiredecoder
*
*/
"""

import signal
import sys
#import smaem
import socket
import struct
from configparser import ConfigParser
from speedwiredecoder import *
import json

# clean exit
def abortprogram(signal,frame):
    # Housekeeping -> nothing to cleanup
    print('STRG + C = end program')
    sys.exit(0)

# abort-signal
signal.signal(signal.SIGINT, abortprogram)


#read configuration
parser = ConfigParser()
#default values
smaserials = ""
ipbind = '0.0.0.0'
MCAST_GRP = '239.12.255.254'
MCAST_PORT = 9522
parser.read(['/etc/smaemd/config','config'])
try:
    smaemserials=parser.get('SMA-EM', 'serials')
    ipbind=parser.get('DAEMON', 'ipbind')
    MCAST_GRP = parser.get('DAEMON', 'mcastgrp')
    MCAST_PORT = int(parser.get('DAEMON', 'mcastport'))
except:
    print('Cannot find config /etc/smaemd/config... using defaults')

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', MCAST_PORT))
try:
    mreq = struct.pack("4s4s", socket.inet_aton(MCAST_GRP), socket.inet_aton(ipbind))
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
except BaseException:
    print('could not connect to mulicast group or bind to given interface')
    sys.exit(1)

json.dumps(decode_speedwire(sock.recv(608)))

Die Ausgabe des Scripts muesste dann so aussehen:
JSON:
{
    "serial": "blabla",
    "pconsume": "wert",
    "pconsumecounter": "wert",
    "psupply": "wert",
    "psupplycounter": "wert",
    "sconsume": "wert",
    "sconsumecounter": "wert",
    "ssupply": "wert",
    "ssupplycounter": "wert",
    "qconsume": "wert",
    "qconsumecounter": "wert",
    "qsupply": "wert",
    "qsupplycounter": "wert",
    "cosphi": "wert",
    "frequency": "wert",
    "p1consume": "wert",
    "p1consumecounter": "wert",
    "p1supply": "wert",
    "p1supplycounter": "wert",
    "s1consume": "wert",
    "s1consumecounter": "wert",
    "s1supply": "wert",
    "s1supplycounter": "wert",
    "q1consume": "wert",
    "q1consumecounter": "wert",
    "q1supply": "wert",
    "q1supplycounter": "wert",
    "u1": "wert",
    "i1": "wert",
    "cosphi1": "wert",
    "p2consume": "wert",
    "p2consumecounter": "wert",
    "p2supply": "wert",
    "p2supplycounter": "wert",
    "s2consume": "wert",
    "s2consumecounter": "wert",
    "s2supply": "wert",
    "s2supplycounter": "wert",
    "q2consume": "wert",
    "q2consumecounter": "wert",
    "q2supply": "wert",
    "q2supplycounter": "wert",
    "u2": "wert",
    "i2": "wert",
    "cosphi2": "wert",
    "p3consume": "wert",
    "p3consumecounter": "wert",
    "p3supply": "wert",
    "p3supplycounter": "wert",
    "s3consume": "wert",
    "s3consumecounter": "wert",
    "s3supply": "wert",
    "s3supplycounter": "wert",
    "q3consume": "wert",
    "q3consumecounter": "wert",
    "q3supply": "wert",
    "q3supplycounter": "wert",
    "u3": "wert",
    "i3": "wert",
    "cosphi3": "wert",
    "speedwire-version": "wert"
}

JSON:
[
    {
        "id": "164b666b.61cb72",
        "type": "tab",
        "label": "Flow 4",
        "disabled": false,
        "info": ""
    },
    {
        "id": "64f203fb.3dfd94",
        "type": "debug",
        "z": "164b666b.61cb72",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 1150,
        "y": 460,
        "wires": []
    },
    {
        "id": "c7fe9219.6736e8",
        "type": "inject",
        "z": "164b666b.61cb72",
        "name": "",
        "topic": "",
        "payload": "",
        "payloadType": "str",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 350,
        "y": 440,
        "wires": [
            [
                "e9006b5f.e05c88"
            ]
        ]
    },
    {
        "id": "e9006b5f.e05c88",
        "type": "exec",
        "z": "164b666b.61cb72",
        "command": "python3 /opt/smaemd/SMA-EM/sma-em-measurement.py",
        "addpay": true,
        "append": "",
        "useSpawn": "false",
        "timer": "",
        "oldrc": false,
        "name": "",
        "x": 690,
        "y": 440,
        "wires": [
            [
                "e2ec451f.6fd9"
            ],
            [],
            [
                "64f203fb.3dfd94"
            ]
        ]
    },
    {
        "id": "e2ec451f.6fd9",
        "type": "json",
        "z": "164b666b.61cb72",
        "name": "",
        "property": "payload",
        "action": "",
        "pretty": false,
        "x": 990,
        "y": 380,
        "wires": [
            [
                "64f203fb.3dfd94"
            ]
        ]
    }
]
 

Anhänge

  • Snipaste_2020-05-18_17-55-49.png
    Snipaste_2020-05-18_17-55-49.png
    49,6 KB · Aufrufe: 189
  • Gefällt mir
Reaktionen: Avenger84 und Raijin
Ich habe ja bereits geschrieben, dass ich von python keine Ahnung habe und nur exemplarisch javascript code gezeigt habe. Drücken wir mal die Daumen, dass es mit deinem Flow dann läuft ;)
 
  • Gefällt mir
Reaktionen: r15ch13
Danke fĂĽr die MĂĽhe, hatte nicht mehr damit gerechnet !

ich muss gestehen, dass ich es nicht hin kriege den Flow nachzubauen 🤦‍♂️

ich kriege es nicht hin den alten kaputter Flow zu löschen oder Node-Red zu resetten, so dass ich wieder sauber anfangen kann.
Wenn ich die Datei flows_Ubuntu20.json lösche oder den Inhalt lösche, ist der kaputte Flow danach wieder da
:grr:
 
Zuletzt bearbeitet:
Den Flow löscht man im NodeRed durch Doppelklick auf den Flowreiter und dann Flow löschen (müsste unten sein)

Du musst den Flow auch nicht "nachbauen", sondern kannst den Spoiler "Flow" von @r15ch13 per Copy&Paste und "Flow importieren" direkt im NodeRed einbauen.
 
Manchmal kann es so einfach sein :hammer_alt:

Wie kriege ich das nun gestestet / Werte angezeigt ?

Die ganzen Objekte sind leer:
1590253694647.png
 
Hab mir den Flow jetzt nicht angeschaut. @r15ch13 verwendet aber keinen function node, sondern einen exec node. Das heiĂźt, dass das Skript nicht in NodeRed enthalten ist. Der exec node fĂĽhrt ein Skript im Dateisystem auf. D.h. du musst das sma-em-measurement.py Skript von @r15ch13 in einem Ordner ablegen und im exec node dann ggfs den Pfad anpassen, wenn das Skript dann woanders liegt.
 
  • Gefällt mir
Reaktionen: r15ch13
ich probier´s morgen noch mal.

Eigentlich wollte ich was anderes fragen:
In dem Projekt gibt es mehrere Features https://github.com/datenschuft/SMA-EM/tree/master/features
da ich mich sowieso noch mit MQTT beschäftigen muss, wollte ich das Feature aktivieren.

Versteht ihr wie ich das aktivieren kann in der config ?

Code:
[FEATURE-simplefswriter]
# list serials simplefswriter notice
serials=1900204522
# measurement vars simplefswriter should write to filesystem (only from smas with serial in serials)
values=pconsume psupply qsupply ssupply

[FEATURE-sample]
nothing=here

Das Feature "simplefswriter" funktioniert auch nicht.

Wie kann ich das: https://github.com/datenschuft/SMA-EM/blob/master/features/mqtt.py aktivieren ?
 
Dafuer musst du wohl den Daemon ausfuehren (also sma-daemon.py) da dieser die "Features" aufruft. Die mqtt.py alleine macht gar nichts.
 
Habe deine Anleitung noch mal ausgefĂĽhrt:
1590314397508.png


Das kommt nun im Debugfenster.

Ist das nun so gewollt oder nicht :confused_alt:

Zumindest stĂĽrzt NR nicht ab.
 
Das ist so gewollt. Das Problem jetzt ist nur das du die Ausgabe von sma-em-measurement.py noch nicht angepasst hast damit es JSON anstatt Text ausgibt. Sie meine Spoiler in #30
 
Das hier:
Die Ausgabe des Scripts muesste dann so aussehen:




JSON:

{
"serial": "blabla",
"pconsume": "wert",
"pconsumecounter": "wert",
"psupply": "wert",
"psupplycounter": "wert",
"sconsume": "wert",

Nur wo kann ich das einfĂĽgen ??

Hinten an sma-em-measurement.py anhängen ?


#!/usr/bin/env python3
# coding=utf-8

import signal
import sys
#import smaem
import socket
import struct
from configparser import ConfigParser
from speedwiredecoder import *
import json

# clean exit
def abortprogram(signal,frame):
# Housekeeping -> nothing to cleanup
print('STRG + C = end program')
sys.exit(0)

# abort-signal
signal.signal(signal.SIGINT, abortprogram)


#read configuration
parser = ConfigParser()
#default values
smaserials = ""
ipbind = '0.0.0.0'
MCAST_GRP = '239.12.255.254'
MCAST_PORT = 9522
parser.read(['/etc/smaemd/config','config'])
try:
smaemserials=parser.get('SMA-EM', 'serials')
ipbind=parser.get('DAEMON', 'ipbind')
MCAST_GRP = parser.get('DAEMON', 'mcastgrp')
MCAST_PORT = int(parser.get('DAEMON', 'mcastport'))
except:
print('Cannot find config /etc/smaemd/config... using defaults')

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', MCAST_PORT))
try:
mreq = struct.pack("4s4s", socket.inet_aton(MCAST_GRP), socket.inet_aton(ipbind))
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
except BaseException:
print('could not connect to mulicast group or bind to given interface')
sys.exit(1)

json.dumps(decode_speedwire(sock.recv(608)))
so hab ich die geändert bisher
 

Ă„hnliche Themen

ZurĂĽck
Oben