CJNE / pymyenergi

An async python library for interfacing with MyEnergi devices
MIT License
19 stars 15 forks source link

Support libbi dual tariff #20

Open plord12 opened 9 months ago

plord12 commented 9 months ago

It would be great if we could support libbi dual tariff ... for example, this would allow "charge from grid now" and "sync libbi tariff from dynamic tariff (such as Octopus Intelligent)"

API is

GET https://myaccount.myenergi.com/api/EnergySetup/GetDualTariffEnergyPrices?hubId=<hubid>

returns

{
    "content": [
        {
            "days": [
                0,
                1,
                2,
                3,
                4,
                5,
                6
            ],
            "energySetupId": "47a272a0-584d-ee11-abf4-0aa731bd900a",
            "tariffs": [
                {
                    "fromMinutes": 0,
                    "id": "3fc421ff-d283-ee11-abf4-0aa731bd900a",
                    "price": 7.5,
                    "toMinutes": 300
                },
                {
                    "fromMinutes": 1410,
                    "id": "40c421ff-d283-ee11-abf4-0aa731bd900a",
                    "price": 7.5,
                    "toMinutes": 1440
                },
                {
                    "fromMinutes": 360,
                    "id": "41c421ff-d283-ee11-abf4-0aa731bd900a",
                    "price": 30.6,
                    "toMinutes": 1410
                },
                {
                    "fromMinutes": 330,
                    "id": "42c421ff-d283-ee11-abf4-0aa731bd900a",
                    "price": 30.6,
                    "toMinutes": 360
                },
                {
                    "fromMinutes": 300,
                    "id": "43c421ff-d283-ee11-abf4-0aa731bd900a",
                    "price": 30.6,
                    "toMinutes": 330
                }
            ]
        }
    ],
    "field": "",
    "message": "",
    "status": true
}

then to update :

POST https://myaccount.myenergi.com/api/EnergySetup/SaveDualTariffEnergyPrices

with

[
    {
        "days": [
            0,
            1,
            2,
            3,
            4,
            5,
            6
        ],
        "energySetupId": "47a272a0-584d-ee11-abf4-0aa731bd900a",
        "tariffs": [
            {
                "fromMinutes": 0,
                "price": 7.5,
                "toMinutes": 300
            },
            {
                "fromMinutes": 1410,
                "price": 7.5,
                "toMinutes": 1440
            },
            {
                "fromMinutes": 360,
                "price": 30.6,
                "toMinutes": 1410
            },
            {
                "fromMinutes": 330,
                "price": 30.6,
                "toMinutes": 360
            },
            {
                "fromMinutes": 300,
                "price": 30.6,
                "toMinutes": 330
            }
        ]
    }
]
plord12 commented 8 months ago

For a quick hack, I added this to my linux server -

$ cat set-libbi-rates.py
#!libbi-venv/bin/python3

import requests
import json
import sys
from pycognito import Cognito

u = Cognito('eu-west-2_E57cCJB20','2fup0dhufn5vurmprjkj599041', username='XXX')
u.authenticate(password='XXX')
headers = {"Authorization": f"Bearer {u.access_token}"}

r = requests.get("https://myaccount.myenergi.com/api/AccountAccess/Hubs", headers=headers)
hubid = json.loads(r.text).get('content').get('hubs')[0].get('hubId')
serial = json.loads(r.text).get('content').get('hubs')[0].get('serialNo')

r = requests.get("https://myaccount.myenergi.com/api/EnergySetup/GetDualTariffEnergyPrices?hubId="+hubid, headers=headers)
id = json.loads(r.text).get('content')[0].get('energySetupId')

# parse args :
#
# 00:00-05:30,7.5 05:30-23:30,30.6 23:30-00:00,7.5

jsonString='[ { "days": [0,1,2,3,4,5,6], "energySetupId": "'+id+'", "tariffs": ['

for i in sys.argv[1:]:
    time,price=i.split(",")
    start,end=time.split("-")
    fromMinutes=int(start.split(":")[0])*60+int(start.split(":")[1])
    toMinutes=int(end.split(":")[0])*60+int(end.split(":")[1])
    if toMinutes == 0:
        toMinutes = 1440
    jsonString=jsonString+'{ "fromMinutes": '+str(fromMinutes)+', "price": '+price+', "toMinutes": '+str(toMinutes)+' },'

data=json.loads(jsonString[:-1]+'] } ]')

r = requests.post("https://myaccount.myenergi.com/api/EnergySetup/SaveDualTariffEnergyPrices", headers=headers, json=data)
print(json.loads(r.text).get('message'))

$ cat set-libbi-rates.sh 
#!/bin/sh
#

cd $(dirname $0)

echo $* > /tmp/libbi.txt
./set-libbi-rates.py $* 2>&1 | tee /tmp/libbi.log

And then in home assistant -

shell_command:
  libbi_octopus_rates: >
    ssh plord@arm3.lan -i /config/.ssh/id_rsa -o UserKnownHostsFile=/config/.ssh/known_hosts 
    "/home/plord/bin/set-libbi-rates.sh "
    {%- set rates=state_attr('event.octopus_energy_electricity_XXXX_current_day_rates','rates') -%} 
    {%- for rate in rates -%} 
    {%- set adjusted_rate=rate.value_inc_vat*100 -%}
    {{- '{:02}:{:02}-{:02}:{:02},{:.02f} '.format(rate.start.hour, rate.start.minute,rate.end.hour, rate.end.minute, adjusted_rate) -}} 
    {%- endfor -%}

To sync libbi rates from my octopus rates. Whats nice here is that when octopus creates boosts for intellegent go, the libi also charges up at the same time (cheap rates).

(lots of issues with this, of course, such as no error checking, assumes libbi has one tariff manually configured etc etc).

plord12 commented 3 months ago

I'm wondering if this is useful now. Once home assistant supports charge from grid then charging/export can be managed by home assistant.