Moin,
ist zwar schon ne weile her aber ich hatte mir da was selber gebastelt.
Die Daten lokal abzugreifen war mir nicht möglich vor allem, weil ich keine extra Hardware verbastelten wollt (RS485-->TCP).
Ich habe meinen ioBroker als Container auf meiner Synology zu laufen. Und habe mich als Lösung für einen Web Scraper entschieden also hab ich mir einen Selenium Container hinzugefügt. Dieser nutzt wie der iobroker MAC VLAN. Hier die yaml von meinem Portainer:
version: '3.7'
name: selenium-standalone-chrome
services:
python:
container_name: selenium-standalone-chrome
hostname: chrome
image: selenium/standalone-chrome
dns:
- '192.168.100.1'
networks:
vlan:
ipv4_address: "192.168.100.71"
environment:
- SE_START_XVFB=true
- SE_BROWSER_ARGS_DISABLE_DSHM=--disable-dev-shm-usage
networks:
vlan:
external: true
name: vlan
Zum Schluss noch nen kleines JS Skript das die Daten alle 15 min vom Web abgreift.
Nicht vergessen den "selenium-webdriver" in die JS Module zu packen und die Datenpunkte anzulegen.
const { Builder, By, until } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const password = 'put-your-password-here';
const email = 'put-your-email-here';
//0 = off
//1 = debug
//2 = all
let mylogging = 1;
// for debug selenium http://192.168.100.71:7900/ pw: secret
let options = new chrome.Options();
options.addArguments('--window-size=1920,1080');
options.addArguments('--no-sandbox'); // Wichtig für Linux/Docker
options.addArguments('--disable-dev-shm-usage'); // Verhindert Abstürze durch Speichermangel
async function run() {
let driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.usingServer('http://192.168.100.71:4444')
.build();
try {
await driver.get("https://www.st-ems.com/login");
mylogging === 2 && console.log('page loaded');
// Login
await driver.findElement(By.id('normal_login_email')).sendKeys(email);
await driver.findElement(By.id('normal_login_password')).sendKeys(password);
await driver.findElement(By.xpath('//*[@id="normal_login"]/div[3]/div/div/div/div/button')).click();
mylogging === 2 && console.log('login triggered');
await driver.sleep(5000);
// Navigation zur Detailseite
await driver.findElement(By.xpath('//table/tbody/tr[2]/td[2]/a')).click();
await driver.sleep(5000);
mylogging === 2 && console.log('moved to sub page');
// Daten auslesen
let soc = await driver.findElement(By.xpath('/html/body/div[1]/div/div[2]/div/div/main/div/div/div/div/div[2]/div/div/div/div[1]/div[2]/div/div[1]/div[2]/div/div/div/div[1]/div[2]/div[1]/div/div/div/span')).getText()
setState('0_userdata.0.power_mgnt.PV1.soc',parseInt(soc.slice(0, -1)),true);
let batt_power = await driver.findElement(By.xpath('/html/body/div[1]/div/div[2]/div/div/main/div/div/div/div/div[2]/div/div/div/div[1]/div[2]/div/div[1]/div[2]/div/div/div/div[1]/div[2]/span/span[1]')).getText()
let batt_power_unit = await driver.findElement(By.xpath('/html/body/div[1]/div/div[2]/div/div/main/div/div/div/div/div[2]/div/div/div/div[1]/div[2]/div/div[1]/div[2]/div/div/div/div[1]/div[2]/span/span[2]')).getText()
setState('0_userdata.0.power_mgnt.PV1.batt_power',batt_power_unit!='W' ? parseFloat(batt_power) * 1000 : parseFloat(batt_power),true);
let sol_power = await driver.findElement(By.xpath('/html/body/div[1]/div/div[2]/div/div/main/div/div/div/div/div[2]/div/div/div/div[1]/div[2]/div/div[1]/div[2]/div/div/div/div[1]/div[1]/div[1]/span/span[1]')).getText()
let sol_power_unit = await driver.findElement(By.xpath('/html/body/div[1]/div/div[2]/div/div/main/div/div/div/div/div[2]/div/div/div/div[1]/div[2]/div/div[1]/div[2]/div/div/div/div[1]/div[1]/div[1]/span/span[2]')).getText()
setState('0_userdata.0.power_mgnt.PV1.sol_power',sol_power_unit!='W' ? parseFloat(sol_power) * 1000 : parseFloat(sol_power),true);
let power_today = await driver.findElement(By.xpath('/html/body/div[1]/div/div[2]/div/div/main/div/div/div/div/div[2]/div/div/div/div[1]/div[2]/div/div[1]/div[1]/div[2]/div/div/div/div/div/div[2]/div/div/div/div[1]/div/div[1]/span')).getText()
let power_today_unit = await driver.findElement(By.xpath('/html/body/div[1]/div/div[2]/div/div/main/div/div/div/div/div[2]/div/div/div/div[1]/div[2]/div/div[1]/div[1]/div[2]/div/div/div/div/div/div[2]/div/div/div/div[1]/div/div[2]')).getText()
setState('0_userdata.0.power_mgnt.PV1.power_today',power_today_unit.toLowerCase().includes('kwh') ? parseFloat(power_today) * 1000 : parseFloat(power_today),true);
let needed_power = await driver.findElement(By.xpath('/html/body/div[1]/div/div[2]/div/div/main/div/div/div/div/div[2]/div/div/div/div[1]/div[2]/div/div[1]/div[2]/div/div/div/div[5]/div[1]/div[1]/span[1]/span[1]')).getText()
let needed_power_unit = await driver.findElement(By.xpath('/html/body/div[1]/div/div[2]/div/div/main/div/div/div/div/div[2]/div/div/div/div[1]/div[2]/div/div[1]/div[2]/div/div/div/div[5]/div[1]/div[1]/span[1]/span[2]')).getText()
setState('0_userdata.0.power_mgnt.PV1.needed_power',needed_power_unit!='W' ? parseFloat(needed_power) * 1000 : parseFloat(needed_power),true);
mylogging >= 1 && console.log('fetched all values, done');
} catch (e) {
console.error(e);
} finally {
await driver.quit();
}
}
schedule("0 */15 8-23 * * *", async function () {
run();
});