How to Send Commands to Website to Automate Device Control?

I have a hot water controller that I can control its functions using the manufacture’s website. I want to be able to automate this control with sensors from my Tesla Powerwall (Installed and working with Tesla Fleet on my HA).

I used Chrome dev recorder to capture me logging in and performing the actions I want to perform. Is it possible to use this information in HA to send via an automation?

This is the login action with 3 events:

{
    const targetPage = page;
    await puppeteer.Locator.race([
        targetPage.locator('::-p-aria(Username or email address *)'),
        targetPage.locator('#username'),
        targetPage.locator('::-p-xpath(//*[@id=\\"username\\"])'),
        targetPage.locator(':scope >>> #username')
    ])
        .setTimeout(timeout)
        .fill('[email protected]');
}

{
    const targetPage = page;
    await puppeteer.Locator.race([
        targetPage.locator('::-p-aria(Password *)'),
        targetPage.locator('#password'),
        targetPage.locator('::-p-xpath(//*[@id=\\"password\\"])'),
        targetPage.locator(':scope >>> #password')
    ])
        .setTimeout(timeout)
        .fill('mypassword');
}

{
    const targetPage = page;
    const promises = [];
    const startWaitingForEvents = () => {
        promises.push(targetPage.waitForNavigation());
    }
    await puppeteer.Locator.race([
        targetPage.locator('::-p-aria(LOG IN)'),
        targetPage.locator('button'),
        targetPage.locator('::-p-xpath(//*[@id=\\"post-74\\"]/div/div/div/form/p[3]/button)'),
        targetPage.locator(':scope >>> button'),
        targetPage.locator('::-p-text(Log in)')
    ])
        .setTimeout(timeout)
        .on('action', () => startWaitingForEvents())
        .click({
          offset: {
            x: 57,
            y: 26.40625,
          },
        });
    await Promise.all(promises);
}

This is the action to switch the heater from solar only to heat now from mains with 3 events:

{
    "type": "click",
    "target": "main",
    "selectors": [
        [
            "div.col-md-2 > div:nth-of-type(4) img"
        ],
        [
            "xpath///*[@id=\"ccontrols\"]/div/catchcontrols/div/div[1]/div[4]/div/img"
        ],
        [
            "pierce/div.col-md-2 > div:nth-of-type(4) img"
        ]
    ],
    "offsetY": 32.609375,
    "offsetX": 102
}

{
    const targetPage = page;
    await puppeteer.Locator.race([
        targetPage.locator('div:nth-of-type(5) div.col-md-3 span'),
        targetPage.locator('::-p-xpath(//*[@id=\\"ccontrols\\"]/div/catchcontrols/div/div[5]/div[2]/div[1]/label/span)'),
        targetPage.locator(':scope >>> div:nth-of-type(5) div.col-md-3 span')
    ])
        .setTimeout(timeout)
        .click({
          offset: {
            x: 48,
            y: 14.921875,
          },
        });
}

{
    const targetPage = page;
    await puppeteer.Locator.race([
        targetPage.locator('::-p-aria(  Save)'),
        targetPage.locator('button:nth-of-type(1)'),
        targetPage.locator('::-p-xpath(//*[@id=\\"ccontrols\\"]/div/catchcontrols/div/div[1]/div[5]/div/button[1])'),
        targetPage.locator(':scope >>> button:nth-of-type(1)'),
        targetPage.locator('::-p-text(Save)')
    ])
        .setTimeout(timeout)
        .click({
          offset: {
            x: 82,
            y: 6.421875,
          },
        });
}

This is the action to switch the heater back to use solar only with 3 events

{
    const targetPage = page;
    await puppeteer.Locator.race([
        targetPage.locator('#ccontrols div:nth-of-type(2) img'),
        targetPage.locator('::-p-xpath(//*[@id=\\"ccontrols\\"]/div/catchcontrols/div/div[1]/div[2]/div/img)'),
        targetPage.locator(':scope >>> #ccontrols div:nth-of-type(2) img')
    ])
        .setTimeout(timeout)
        .click({
          offset: {
            x: 95,
            y: 33.921875,
          },
        });
}

{
    "type": "click",
    "target": "main",
    "selectors": [
        [
            "div:nth-of-type(3) div.col-md-3 span"
        ],
        [
            "xpath///*[@id=\"ccontrols\"]/div/catchcontrols/div/div[3]/div[2]/div[1]/label/span"
        ],
        [
            "pierce/div:nth-of-type(3) div.col-md-3 span"
        ]
    ],
    "offsetY": 8.296875,
    "offsetX": 37
}

{
    const targetPage = page;
    await puppeteer.Locator.race([
        targetPage.locator('::-p-aria(  Save)'),
        targetPage.locator('button:nth-of-type(1)'),
        targetPage.locator('::-p-xpath(//*[@id=\\"ccontrols\\"]/div/catchcontrols/div/div[1]/div[5]/div/button[1])'),
        targetPage.locator(':scope >>> button:nth-of-type(1)'),
        targetPage.locator('::-p-text(Save)')
    ])
        .setTimeout(timeout)
        .click({
          offset: {
            x: 92,
            y: 8.796875,
          },
        });
}

You won’t be able to run typescript/javascript directly in a HA automation, BUT you might me able to circumvent HA’s limitations and use something like Node-Red to run this code for an automation. Otherwise, you have the option to convert it into python (if possible) and use something like AppDaemon or Pyscript to run it.

Unfortunately, I don’t use Node-Red myself, so I can’t help you further in that regard. I prefer python.

Finally, you’re last option is to develop a custom component for it (plenty of walkthroughs on the interwebz you can find). You might want to try searching in GitHub if you haven’t already because it’s possible someone already has done it or attempted to.

1 Like