Closed redlefloh closed 3 months ago
Hi @redlefloh, unfortunately the Total Energy is not exposed over Modbus (it is not listed in Mennekes Modbus Description). The only Energy that is exposed is the Energy per Session (from plug-in to plug-out) which I named "Amtron Energy" and is named "Charging session meter count" in the Modbus Documentation. If found it to be the more interesting value anyway and adding up the sessions in HA or other tools is easy.
@mfaust78 yes, agree, I actually created a utility meter based on "Charging session meter count". And scarping the Mennekes website is actually quite challenging, it's pretty bad HTML/JS code code, multiscrape is failing with the login, but I was able to do it via puppeteer. I also created a pupeteer script that can automatically reboot the wallbox since sometimes the modbus connection actually dies.
Here are the two puppeteer scripts:
// Puppeteer script to scrape the total energy value from the Mennekes Amtron XTRA Wallbox
// by going to the internal website of the wallbox and then scraping the "dataElementHCME" value
// Install node.js and puppeteer and then run this scriot with "node mennekes_total_energy.js"
const mennekes_url = 'http://192.168.xxx.xxx:25000' // URL of your Mennekes Amtron Xtra Wallbox
const mennekes_pin = 'xxxxxx' // PIN of your Mennekes Amtron Xtra Wallbox
const puppeteer = require('puppeteer'); // v22.0.0 or later
(async () => {
const browser = await puppeteer.launch({
executablePath: '/usr/bin/chromium-browser',
headless: true
});
const page = await browser.newPage();
const timeout = 5000;
page.setDefaultTimeout(timeout);
{
const targetPage = page;
await targetPage.setViewport({
width: 1038,
height: 1102
})
const promises = [];
const startWaitingForEvents = () => {
promises.push(targetPage.waitForNavigation());
}
startWaitingForEvents();
await targetPage.goto(mennekes_url);
await Promise.all(promises);
await puppeteer.Locator.race([
targetPage.locator('::-p-aria(User or Installation PIN)'),
targetPage.locator('#loginPinInput'),
targetPage.locator('::-p-xpath(//*[@id=\\"loginPinInput\\"])'),
targetPage.locator(':scope >>> #loginPinInput')
])
.setTimeout(timeout)
.click({
offset: {
x: 88.5,
y: 4.34375,
},
});
await puppeteer.Locator.race([
targetPage.locator('::-p-aria(User or Installation PIN)'),
targetPage.locator('#loginPinInput'),
targetPage.locator('::-p-xpath(//*[@id=\\"loginPinInput\\"])'),
targetPage.locator(':scope >>> #loginPinInput')
])
.setTimeout(timeout)
.fill(mennekes_pin);
await puppeteer.Locator.race([
targetPage.locator('::-p-aria(Login[role=\\"button\\"])'),
targetPage.locator('#loginFormSubmit'),
targetPage.locator('::-p-xpath(//*[@id=\\"loginFormSubmit\\"])'),
targetPage.locator(':scope >>> #loginFormSubmit')
])
.setTimeout(timeout)
.click({
offset: {
x: 51.6640625,
y: 18.84375,
},
});
const sleep = ms => new Promise(res => setTimeout(res, ms));
await sleep(3000);
const text = await page.evaluate(() => {
const el = document.querySelector('#dataElementHCME')
return el.innerText
})
console.log(text)
const fs = require('fs');
fs.writeFileSync('/home/pi/docker/homeassistant/mennekes_amtron_total_energy.txt', text);
await browser.close();
}
})().catch(err => {
console.error(err);
process.exit(1);
});
// Puppeteer script to automatically reboot a Mennekes Amtron XTRA Wallbox by going to the internal
// website of the wallbox and then to the Systems page and clicking on "Reboot AMTRON"
//
// Install node.js and puppeteer and then run this scriot with "node mennekes_reboot.js"
const mennekes_url = 'http://192.168.xxx.xxx:25000' // URL of your Mennekes Amtron Xtra Wallbox
const mennekes_pin = 'xxxxxx' // PIN of your Mennekes Amtron Xtra Wallbox
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
executablePath: '/usr/bin/chromium-browser',
headless: true
});
const page = await browser.newPage();
const timeout = 5000;
page.setDefaultTimeout(timeout);
{
const targetPage = page;
await targetPage.setViewport({
width: 1038,
height: 1102
})
const promises = [];
const startWaitingForEvents = () => {
promises.push(targetPage.waitForNavigation());
}
startWaitingForEvents();
console.log("Open Page...");
await targetPage.goto(mennekes_url);
await Promise.all(promises);
console.log("Goto Login...");
await puppeteer.Locator.race([
targetPage.locator('::-p-aria(User or Installation PIN)'),
targetPage.locator('#loginPinInput'),
targetPage.locator('::-p-xpath(//*[@id=\\"loginPinInput\\"])'),
targetPage.locator(':scope >>> #loginPinInput')
])
.setTimeout(timeout)
.click({
offset: {
x: 88.5,
y: 4.34375,
},
});
console.log("Entering Password...");
await puppeteer.Locator.race([
targetPage.locator('::-p-aria(User or Installation PIN)'),
targetPage.locator('#loginPinInput'),
targetPage.locator('::-p-xpath(//*[@id=\\"loginPinInput\\"])'),
targetPage.locator(':scope >>> #loginPinInput')
])
.setTimeout(timeout)
.fill(mennekes_pin);
console.log("Clicking Login...");
await puppeteer.Locator.race([
targetPage.locator('::-p-aria(Login[role=\\"button\\"])'),
targetPage.locator('#loginFormSubmit'),
targetPage.locator('::-p-xpath(//*[@id=\\"loginFormSubmit\\"])'),
targetPage.locator(':scope >>> #loginFormSubmit')
])
.setTimeout(timeout)
.click({
offset: {
x: 51.6640625,
y: 18.84375,
},
});
console.log("Going to the Systems Page...");
await puppeteer.Locator.race([
targetPage.locator('::-p-aria(System)'),
targetPage.locator('#header li:nth-of-type(5) > a'),
targetPage.locator('::-p-xpath(//*[@id=\\"primaryNav\\"]/ul/li[5]/a)'),
targetPage.locator(':scope >>> #header li:nth-of-type(5) > a')
])
.setTimeout(timeout)
.click({
offset: {
x: 23.7265625,
y: 10.875,
},
});
console.log("Showing Systems Page...");
await page.evaluate(`showPage("System")`);
const sleep = ms => new Promise(res => setTimeout(res, ms));
console.log("Waiting for page to finish loading...");
await sleep(3000);
console.log("Clicking Reboot Button...");
await targetPage.click('input[value="Reboot AMTRON"]');
await page.screenshot({
path: 'screenshot.jpg'
});
await browser.close();
console.log("Done.");
}
})().catch(err => {
console.error(err);
process.exit(1);
});
Create a puppeteer directory in /config
cd /home/pi/docker/homeassistant
mkdir puppeteer
cd puppeteer
Download and run the node install script:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
nvm install 20
Install Puppeteer:
npm -i puppeteer
Important, in order to run on a RasPi you need:
const browser = await puppeteer.launch({
executablePath: '/usr/bin/chromium-browser',
headless: true
});
If you run Home Assistant in a docker container, you can't run scripts on the host computer. Therefore you need to use the trick to ssh from the docker container into your hostcontainer and then execute a script. See instructions here
Hi @mfaust78, just a quick question, maybe you know, is the "Total Energy" of the Wallbox also somewhere available over modbus? It is available on the Service Interface (internal webpage) of the Wallbox, so I could also scrape it there, but I thought I ask the expert first if it maybe is also available via modbus, just not documented. Thanks!