[APP][Pro] Wallbox Charger - Smart EV charging technology made simple

Hi, not that I’m aware off. Unfortunately my Wallbox internet connection failed for quite some time and I haven’t got around to fixing it. So unfortunately I don’t use my own app :P. So notifications like these are important. I hope that I find some time soon to look into it.

1 Like

Thanks Roy! I would be happy to grant you temporary access to my Wallbox if that helps in any way.

I have the same problem.

Hey @rkokkelk the app is really unusable mate. Even without any flow I get the 429 error.

I know you’re busy and I respect that, just wonder what would take for you to have a quick look at this diagnosis report: 1b494101-1e3f-413a-a1ba-813589bebfef

Happy to give you access to my Wallbox.

Many thanks!

It’s an easy fix. I’ve updated my homey script for the wallbox api with two lines to make it work.

What is the hold-up?

Same problem here. Since a few weeks (probably also january…) often get errors and now even a non-resolvable “apparaat onbeschikbaar” (device not available).

This is of course not likely just at the time the sun starts shining :wink:

@rkokkelk You think you’ll find time in the near future to look into this issue? I don’t know if it’s an option for you (if it’s even possible?) to appoint a co-developper?

Kind regards!

Do you use homeyscript as a supplement for the wallbox app, or rather as a replacement? What are your actions you use the script for?

(sorry for my curiosity :wink: )

No problem..

I currently use it, as the app is not working for me, to lock and unlock. It can pause charging, but I do not use it. I just want to hookup the car and then Google to start charging.

Might look into this. I like to work with scripts (more self-control compared to an app), but I don’t know how to write them… Nowadays Gemini & Grok already wrote some really usefull scripts for me, so I might challenge them for this… :slight_smile:

Thanks !

Yeah I really need to find some time to work on it. You are correct. Unfortunately I haven’t fixed my own Wallbox yet, so I simply don’t have an option to test any new development until that is fixed. So kinda relying on other contributions for this issue.

Assigning a co-developer is a possibility, but given the fact that the app is open source any can contribute. But in the last couple of years I have only received a single attribution. So in general there is not much effort from within this community to aid the development.

@rkokkelk Thanks for your response. I understand.

Too bad that there’s very little contribution. I would love to help myself, but I don’t know **** about programming. I’m now looking into Homeyscripts (with the help of AI) for doing basic things with the charger (starting stopping status ampere).

I will post my succes or fail here later…

@Sen-Sai Do you run your script for a status update regularly? If yes: How often without running into the limits of the Wallbox API?

In the Forum there already is a homey script that does that. It’s just need two extra lines to work with new api restrictions. I don’t repeatedly call the api, from this topic here I think I remember once a minute is fine, not sure though.

When I’m back home I’ll have a look what those two extra lines were, might help the developer here as well.

Met onderstaand script lukt het me om de dingen te doen die ik wil.
Status opvragen, laden starten en stoppen, Amperes instellen.
Gemaakt met behulp van Grok (AI).

Het wordt allemaal aangestuurd via flows en gemonitord via het Dashboard van @Satoer . Ik heb er dus geen Virtual Device voor aangemaakt. Maar wellicht is dit ook mogelijk.
Status flow loopt iedere 2 minuten, meer kan waarschijnlijk, maar voor mij volstaat het en loopt het momenteel zonder errors :slight_smile:

// === WALLBOX PULSAR PLUS - HOMEYSCRIPT (volledig werkend 2026) ===
// Vul je gegevens in:
const username = 'hidden';          // myWallbox e-mail
const password = 'hidden';         // myWallbox wachtwoord
const MYCHARGERID = hidden;                // Numeriek ID uit je JSON: 417955

const BASEURL = "https://api.wall-box.com/";
const URL_AUTH = 'auth/token/user';
const URL_GROUPS = 'v3/chargers/groups';       // Voor status ophalen
const URL_REMOTE = `v3/chargers/${MYCHARGERID}/remote-action`;
const URL_SET_CURRENT = `v2/charger/${MYCHARGERID}`;

// Handmatige base64 (nodig in HomeyScript)
function toBase64(str) {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
  let output = '';
  let i = 0;
  str = unescape(encodeURIComponent(str));
  while (i < str.length) {
    const a = str.charCodeAt(i++);
    const b = str.charCodeAt(i++);
    const c = str.charCodeAt(i++);
    const triplet = (a << 16) | (isNaN(b) ? 0 : b << 8) | (isNaN(c) ? 0 : c);
    output += chars.charAt((triplet >> 18) & 63) +
              chars.charAt((triplet >> 12) & 63) +
              (isNaN(b) ? '=' : chars.charAt((triplet >> 6) & 63)) +
              (isNaN(c) ? '=' : chars.charAt(triplet & 63));
  }
  return output;
}

async function getToken() {
  const authString = username + ':' + password;
  const base64Auth = toBase64(authString);

  const response = await fetch(BASEURL + URL_AUTH, {
    method: 'POST',
    headers: {
      'Authorization': 'Basic ' + base64Auth,
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    }
  });

  if (!response.ok) {
    const err = 'Auth fout: HTTP ' + response.status;
    console.log(err);
    await tag('Wallbox_error', err);
    throw new Error(err);
  }

  const data = await response.json();
  if (!data.jwt) {
    const err = 'Geen JWT in response';
    console.log(err);
    await tag('Wallbox_error', err);
    throw new Error(err);
  }
  return data.jwt;
}

// Status ophalen via groups (meest betrouwbaar)
async function getStatus(token) {
  const response = await fetch(BASEURL + URL_GROUPS, {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer ' + token,
      'Accept': 'application/json'
    }
  });

  if (!response.ok) {
    const err = 'Groups fout: HTTP ' + response.status;
    console.log(err);
    await tag('Wallbox_error', err);
    throw new Error(err);
  }

  const data = await response.json();
  let chargerStatus = {
    status: 0,
    chargingPower: 0,
    maxChargingCurrent: 0,
    addedEnergy: 0,
    locked: false,
    connected: false
  };

  if (data.result && data.result.groups) {
    for (const group of data.result.groups) {
      if (group.chargers) {
        for (const ch of group.chargers) {
          if (ch.id === MYCHARGERID) {
            chargerStatus = {
              status: ch.status || 0,
              chargingPower: ch.chargingPower || 0,
              maxChargingCurrent: ch.maxChargingCurrent || 0,
              addedEnergy: ch.addedEnergy || 0,
              locked: ch.locked === 1,
              connected: ch.ocppConnectionStatus === 1
            };
            break;
          }
        }
      }
    }
  }

  if (chargerStatus.status === 0) {
    const err = 'Charger niet gevonden in groups';
    console.log(err);
    await tag('Wallbox_error', err);
    throw new Error(err);
  }

  return chargerStatus;
}

// Start / resume opladen
async function startCharging(token) {
  const response = await fetch(BASEURL + URL_REMOTE, {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer ' + token,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ action: 1 })  // 1 = resume/start
  });

  if (!response.ok) {
    const err = 'Start fout: HTTP ' + response.status;
    console.log(err);
    await tag('Wallbox_error', err);
    throw new Error(err);
  }
}

// Stop / pause opladen
async function stopCharging(token) {
  const response = await fetch(BASEURL + URL_REMOTE, {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer ' + token,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ action: 2 })  // 2 = pause/stop
  });

  if (!response.ok) {
    const err = 'Stop fout: HTTP ' + response.status;
    console.log(err);
    await tag('Wallbox_error', err);
    throw new Error(err);
  }
}

// Set max laadvermogen (amps)
async function setAmps(token, amps) {
  if (amps < 6 || amps > 32) {
    const err = 'Amps moet tussen 6 en 32 liggen';
    console.log(err);
    await tag('Wallbox_error', err);
    throw new Error(err);
  }
  const response = await fetch(BASEURL + URL_SET_CURRENT, {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer ' + token,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ maxChargingCurrent: amps })
  });

  if (!response.ok) {
    const err = 'Set amps fout: HTTP ' + response.status;
    console.log(err);
    await tag('Wallbox_error', err);
    throw new Error(err);
  }
}

// === Hoofdscript: run met argument via Flow ===
if (!args || args.length === 0 || typeof args[0] !== 'string') {
  const err = 'Geef een argument: status | start | stop | set 6 | set 10';
  console.log(err);
  await tag('Wallbox_error', err);
  throw new Error(err);
}

const arg = args[0].trim().toLowerCase();

try {
  const token = await getToken();

  if (arg === 'status') {
    const status = await getStatus(token);

    // Maak expliciete tags (nu verschijnen ze echt!)
    await tag('Wallbox_status', status.status);                  // Number: bijv. 182
    await tag('Wallbox_chargingPower', status.chargingPower);    // Number: kW
    await tag('Wallbox_maxCurrent', status.maxChargingCurrent);  // Number: A
    await tag('Wallbox_addedEnergy', status.addedEnergy);        // Number: kWh deze sessie
    await tag('Wallbox_locked', status.locked ? 'true' : 'false');
    await tag('Wallbox_connected', status.connected ? 'true' : 'false');
    await tag('Wallbox_lastUpdate', new Date().toLocaleString()); // Text: wanneer laatste update

    console.log('Status tags aangemaakt:', status);
    return 'Status opgehaald en tags gezet';

  } else if (arg === 'start') {
    await startCharging(token);
    await tag('Wallbox_lastAction', 'Gestart');
    await tag('Wallbox_error', '');  // Reset error
    console.log('Opladen gestart / hervat');
    return 'Gestart';

  } else if (arg === 'stop') {
    await stopCharging(token);
    await tag('Wallbox_lastAction', 'Gestopt');
    await tag('Wallbox_error', '');  // Reset error
    console.log('Opladen gestopt / gepauzeerd');
    return 'Gestopt';

  } else if (arg.startsWith('set ')) {
    const ampsStr = arg.split(' ')[1];
    const amps = parseInt(ampsStr, 10);
    if (isNaN(amps)) throw new Error('Ongeldig amps: ' + ampsStr);

    await setAmps(token, amps);
    await tag('Wallbox_lastAction', `Set ${amps}A`);
    await tag('Wallbox_maxCurrent', amps);  // Update direct
    await tag('Wallbox_error', '');  // Reset error
    console.log(`Max current gezet op ${amps}A`);
    return `Set ${amps}A`;

  } else {
    throw new Error('Ongeldig argument: ' + arg);
  }
} catch (err) {
  console.log('Hoofdfout:', err.message);
  await tag('Wallbox_error', err.message);
  throw err;
}