CJNE / pymyenergi

An async python library for interfacing with MyEnergi devices
MIT License
22 stars 16 forks source link

Support libbi dual tariff #20

Open plord12 opened 1 year ago

plord12 commented 1 year 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 11 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 7 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.

HLFCode commented 2 months ago

Once home assistant supports charge from grid then charging/export can be managed by home assistant.

Not sure what you mean by this, will you explain please.

AFAIUI HA uses pymyenergi, so setting anything in the libbi has to be provided by this repository doesn't it?

I really want to do what you're doing (charge the libbi when Go uses "day" times) but there's no myenergi api to say "charge now" is there? If there isn't, the only way is to set a temporary tariff as you describe above.