NEWS
Geekworm X1202 USV Variable in IObroker übernehmen
-
Hallo Zusammen,
Ich habe mir zum Raspi 5 eine USV Platine gegönnt.
zu der Platine gibt es das eine oder andere Pyton script. die Scripte lassen sich über die SSH Konsole ausführen. Es gibt dann Rückmeldungen über die Akkuspannung und die aktuelle Kappazität. Das sieht dann so aus.Nun möchte ich die Spannung und die Kapazität aus dem Script in eine Variable im IObroker übernehmen um damit den Ladevorgang zu starten bzw zu stoppen. Das Starten und Stoppen funtioniert schon aus dem IObrocker herraus.
da ich bisher eigenlich nie etwas in diese richtung gemacht, fehlt jegliche Fantasie wie ich aus dem Pyton Script den Spannungswert in eine User-Variable im IObrocker bekomme.
Kann mir da jemand unter die Arme greifen und mir Starthilfe geben .
Vielen Dank
-
@lieggie sagte: aus dem Pyton Script den Spannungswert in eine User-Variable im IObrocker bekomme.
Python kann http-requests, womit man die Werte per Simple-API an ioBroker senden kann.
-
@lieggie sagte: Das sieht dann so aus.
Alternativ zur Simple-API kannst du versuchen, per exec-Block die gezeigte String-Ausgabe zu erhalten.
Falls das funktioniert, kann man anschließend den String zerlegen.
Anmerkung: Das Trennzeichen für
ele
besteht aus Doppelpunkt + Leerzeichen. -
@paul53
hallo Paul53 erst einmal vielen dank für deine schnelle unterstützung. ich werde mir das beides gleich einmal genauer ansehen.
So wie ich das mit Simple Api verstanden habe schreibe ich in das vorhandene merged.py eine Zeile die dann den Wert per HTTP an die simpel api schickt.Auch vielen dank für das Blockly. Ich weis nur nicht wie ich aus einem String eine Value erzeuge. Ich brauche einen Zahlen Wert der sich ändert.
Gruß Thomas
-
@lieggie sagte: Ich brauche einen Zahlen Wert der sich ändert.
Das untere Blockly zeigt, wie man aus dem String die Zahlenwerte extrahieren kann.
-
@paul53 ok nun habe ich es auch gesehen.
nun habe ich erst einmal das Problem mit den Rechten. Ich muss dem IObroker erlauben auf das Verzeichnis
/home/pi/x120x zuzugreifen.Ich bekomme im Log diese Meldung
script.js.Skript_1: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helpersudo: a password is required
-
@lieggie sagte: Ich bekomme im Log diese Meldung
Versuche es mal ohne "sudo".
-
Habe ich... mag er nicht.
-
zu überlegen wäre es natürlich phyton zu umgehen und einfach direkt mit der raspi schnittstelle aus dem iobroker heraus zu sprechen.
das würde wahrscheinlich einige probleme lösen
wo ist das python skript zu finden?
gibt es einen artikel dazu? -
-
@lieggie sagte: Habe ich... mag er nicht.
Verschiebe das Python-Skript aus dem Verzeichnis "/home/pi/x120x" nach /home/iobroker
sudo mv merged.py /home/iobroker/merged.py
Dann sollte es so funktionieren:
-
ok, code gefunden, allerdings aktuell noch nicht direkt nutzbar, da es ein plugin für ein anderes system ist, aber den code kann man rausnehmen und für iobroker anpassen
da steht zwar das es für ein anderes geekwork (nicht der griechische wurm) ist,
aber die adressierung ist die selbe wie im pythonvoltage auf i2s adresse 2
capacity auf i2c adresse 4
abfrage ob rapsi auf strom oder batterie läuft auf gpio pin 6https://github.com/tmcolby/signalk-geekworm-x728/blob/master/index.js
ich schau mal, muss es halt blind machen und kann nicht testen, falls du einverstanden bist.
wie gesagt, dann würde das direkt als javascript-adapter skript laufen, ohne das da noch python über exec angesprochen wird und der text noch analysiert wird. das skript würde dann direkt in 3 datenpunkte schreiben -
hier zum testen
die beiden npm bibliotheken- i2c-bus
- onoff
müssen zuvor in den einstellungen des javascript adapters hinzugefügt werden
const I2c = require('i2c-bus') const Gpio = require('onoff').Gpio; const dp_voltage ="0_userdata.usv.voltage"; //number const dp_voltagestate ="0_userdata.usv.voltagestate"; //number const dp_capacity ="0_userdata.usv.capacity"; //number const dp_powerstate ="0_userdata.usv.powerstate"; //string const X728_ADDR = 0x36 const VOLTAGE_REG = 0x2 const CAPACITY_REG = 0x4 const extPower = new Gpio(6, 'in', 'both', { debounceTimeout: 300 }); extPower.read((err, externalPowerLoss) => { if (err) { log(err,"error"); } else { setPowerstate(externalPowerLoss); } }); // notification actions on gpio change extPower.watch((err, externalPowerLoss) => { if (err) { if (err) log(err,"error"); } else { setPowerstate(externalPowerLoss); } }); function readGeekworm() { // open the i2c bus let i2c = I2c.open(1, (err) => { if (err) log(err,"error"); }); // read and publish battery voltage i2c.readWord(X728_ADDR, VOLTAGE_REG, (err, rawData) => { if (err) log(err,"error"); rawData = (rawData >> 8) + ((rawData & 0xff) << 8); let voltage = rawData * 1.25 / 1000 / 16; console.debug(`battery voltage: ${voltage} VDC`); setState(dp_voltage,voltage); getVoltageState(voltage); }); // read and publish battery charge capacity i2c.readWord(X728_ADDR, CAPACITY_REG, (err, rawData) => { if (err) log(err,"error"); rawData = (rawData >> 8) + ((rawData & 0xff) << 8); let capacity = rawData / 256; //100% at 4.2VDC if (capacity > 1.0) capacity = 1.0; //cap at 1.0 if small rounding eror console.debug(`battery capacity: ${capacity} %`); setState(dp_capacity,capacity); }); // close the i2c bus i2c.close((err) => { if (err) log(err,"error"); }); } function getVoltageState(voltage) { let state="unknown"; if (voltage<=3.87 && voltage <=4.2) state="Full"; if (voltage<=3.7 && voltage <3.87) state="High"; if (voltage<=3.55 && voltage <3.7) state="Medium"; if (voltage<=3.4 && voltage <3.55) state="Low"; if (voltage<3.4) state="Critical"; setState(dp_voltagestate,state); } function setPowerstate(externalPowerLoss) { if (externalPowerLoss) { setState(dp_powerstate,"battery"); } else { setState(dp_powerstate,"power"); } } schedule('* * * * *',readGeekworm); //every minute
-
@oliverio sagte: "0_userdata.usv.voltagestate"; //number
... sollte vom Typ "string" sein.
Das Schreiben der eigenen Datenpunkte sollte mit Bestätigung erfolgen. -
Hallo Ihr 2.....ich komme grad vom Einkaufen und sehe wie ihr 2 euch gedanken macht erstenmal vielen dank dafür.
Ich habe in die Richtung noch nie was gemacht und war in den ersten IOB instalationsrutinen immer froh mit copy & Paste klar zukommen.
Ich habe das Script nun in /opt/Iobroker verschoben, jetzt fragt er nicht mehr nach einem Passwort.Es ist für mich nun der erste Versuch Daten aus anderen Scripten zu holen.
Aber ganz ehrlich das mit dem i2c ist mir zu viel da muss ich mich noch einarbeiten.
@OliverIO wenn du magst kann ich dir den pi5 zur verfügung stellen ...aber dann lern ich nicht dabei.Er ist noch nicht im Betrieb
Und ja du hast recht und der Überschrift ist ein R zuviel.
Vielen dank für eure Hilfe -
@lieggie sagte in Greekworm X1202 USV Variable in IObroker übernehmen:
Aber ganz ehrlich das mit dem i2c ist mir zu viel da muss ich mich noch einarbeiten.
dein python script nutzt das genau so.
du sollst das skript einfach nur mal laufen lassen. i2c musst du dich nicht einarbeitenalso datenpunkte einrichten, entweder nach meinen vorschlägen oder
eigene benennen, anlegen und im skript eintragen.dann die bibliotheken in den js adapter einstellungen eintragen, fertig.
-
@oliverio
ich stehe auf dem schlauch ... gemacht habe ich nunVariable erstellt
Minutliche ausführung
nu komme ich nicht weiter weil mein merged.py so aussieht.
wo soll ich deine Zeilen einfügen.#!/usr/bin/python3 import os import struct import smbus import time import logging import subprocess import gpiod from subprocess import call # User-configurable variables SHUTDOWN_THRESHOLD = 3 # Number of consecutive failures required for shutdown SLEEP_TIME = 60 # Time in seconds to wait between failure checks Loop = False def readVoltage(bus): read = bus.read_word_data(address, 2) swapped = struct.unpack("<H", struct.pack(">H", read))[0] voltage = swapped * 1.25 / 1000 / 16 return voltage def readCapacity(bus): read = bus.read_word_data(address, 4) swapped = struct.unpack("<H", struct.pack(">H", read))[0] capacity = swapped / 256 return capacity def get_battery_status(voltage): if 3.87 <= voltage <= 4.2: return "Full" elif 3.7 <= voltage < 3.87: return "High" elif 3.55 <= voltage < 3.7: return "Medium" elif 3.4 <= voltage < 3.55: return "Low" elif voltage < 3.4: return "Critical" else: return "Unknown" # Ensure only one instance of the script is running pid = str(os.getpid()) pidfile = "/run/X1200.pid" if os.path.isfile(pidfile): print("Script already running") exit(1) else: with open(pidfile, 'w') as f: f.write(pid) try: bus = smbus.SMBus(1) address = 0x36 PLD_PIN = 6 chip = gpiod.Chip('gpiochip4') pld_line = chip.get_line(PLD_PIN) pld_line.request(consumer="PLD", type=gpiod.LINE_REQ_DIR_IN) while True: failure_counter = 0 for _ in range(SHUTDOWN_THRESHOLD): ac_power_state = pld_line.get_value() voltage = readVoltage(bus) battery_status = get_battery_status(voltage) capacity = readCapacity(bus) print(f"Capacity: {capacity:.2f}% ({battery_status}), AC Power State: {'Plugged in' if ac_power_state == 1 else 'Unplugged'}, Voltage: {voltage:.2f}V") if capacity < 20: print("Battery level critical.") failure_counter += 1 elif voltage < 3.20: print("Battery voltage critical.") failure_counter += 1 elif ac_power_state == 0: print("UPS is unplugged or AC power loss detected.") failure_counter += 1 else: failure_counter = 0 break if failure_counter < SHUTDOWN_THRESHOLD: time.sleep(SLEEP_TIME) if failure_counter >= SHUTDOWN_THRESHOLD: shutdown_reason = "" if capacity < 20: shutdown_reason = "due to critical battery level." elif voltage < 3.20: shutdown_reason = "due to critical battery voltage." elif ac_power_state == 0: shutdown_reason = "due to AC power loss or UPS unplugged." shutdown_message = f"Critical condition met {shutdown_reason} Initiating shutdown." print(shutdown_message) call("sudo nohup shutdown -h now", shell=True) else: #print("System operating within normal parameters. No action required.") if Loop: time.sleep(SLEEP_TIME) else: exit(0) finally: if os.path.isfile(pidfile): os.unlink(pidfile) exit(0)
-
nix blockly.
du legst im javascript adapter ein neues skript an und wählst anstatt blockly
den javascript knopf (auch nicht typescript und auch nicht rules)du gibts deinem skript einen namen.
dann hast du ein textfenster.
dort kopierst du das skript rein
dann die namen der datenpunkte in den ersten paar zeilen des skripts anpassen
und drückst oben auf den play button
im unterne bereich des skripts ist ein log bereich.
da mal reinschauen was da so kommt.
wenn keine fehler erscheinen kannst du die datenpunkte überprüfen ob da die daten reingeschrieben wurden. -
@oliverio
Guten Morgen , sorry das ich mich erst jetzt Melde .Ich war gestern verhindert.
ich habe wie du gesagt hast nun das Script rin kopiert. bekomme aber nun diesen fehlerjavascript.0 10:12:51.180 info Stopping script script.js.USV javascript.0 10:12:53.042 info Start JavaScript script.js.USV (Javascript/js) javascript.0 10:12:53.058 error script.js.USV: Error: EINVAL: invalid argument, write javascript.0 10:12:53.059 error at script.js.USV:26:18 javascript.0 10:12:53.060 error at script.js.USV:169:3
ich glaub hier ist noch was faul
-
@lieggie sagte in Greekworm X1202 USV Variable in IObroker übernehmen:
Und ja du hast recht und der Überschrift ist ein R zuviel.
jetzt nicht mehr!
Ich hab's für dich rausgenommen