gkreitz / homeassistant-grohe_sense

Grohe Sense integration for Home Assistant
MIT License
42 stars 25 forks source link

Grohe blue integration #5

Open motaker opened 4 years ago

motaker commented 4 years ago

Hi, first of all Thank you for your this great work !

I am just wondering is it also possible to integrate Grohe blue product which is appeared in Ondus app? Grohe Blue Home/Professional is able to control water on/off(still, sparkling, strong sparkling) and the amount.

API discussion has been made already here. https://github.com/FlorianSW/grohe-ondus-api-java/issues/12

gkreitz commented 4 years ago

Happy you like the project, and thanks for the pointer. Unfortunately, I'm unlikely to add support for Grohe Blue as I don't have one myself, and Grohe offers no development support (documentation, simulators, et.c.). Would be happy to accept pull requests if someone has a Blue and wants to try their hand at it though.

Buktahula commented 3 years ago

Hello , I have such a system and would like to help to get the blue system in Home Assistant up and running. Here is the API discussion. https://github.com/FlorianSW/grohe-ondus-api-java/issues/12

I could like to test the release and help out a bit if there are bugs

darkm20 commented 2 years ago

I can help on this topic...at least to provide some details:

Those are the methods: @p("/v3/iot/locations/{locationId}") @p("/v3/iot/locations/{locationId}/rooms/{roomId}") @o("/v3/iot/locations") @p("/v3/iot/locations/{locationId}/storage") @b("/v3/iot/locations/{locationId}") @f("/v3/iot/locations/{locationId}/storage") @b("/v3/iot/locations/{locationId}/rooms/{roomId}") @o("/v3/iot/locations/{locationId}/rooms") @o("/v3/iot/locations/{locationId}/rooms/{roomId}/appliances")

The interesting part is...when we request "rooms" there are 2 rooms. The 2nd room contains the information of the Blue Home:

[ { "appliance_id": "7722d243-2652-4359-a27a-b529b06eb37b", "installation_date": "2021-09-01T21:24:55.000+00:00", "name": "My GROHE Blue Home", "serial_number": "33356764", "type": 104, "version": "01.00.Z10.0300.0104", "tdt": "2021-09-24T09:58:07.000+02:00", "timezone": 60, "config": { "co2_type": 1, "hose_length": 87, "co2_consumption_medium": 48, "co2_consumption_carbonated": 65, "guest_mode_active": false, "auto_flush_active": false, "flush_confirmed": false, "f_parameter": 9, "l_parameter": 1, "flow_rate_still": 20, "flow_rate_medium": 25, "flow_rate_carbonated": 20 }, "role": "owner", "registration_complete": true, "presharedkey": "feCxi+9Rj3Pt8NfWbh7wpf+S+ACcSCURvI6dfZihWIs=", "params": { "water_hardness": 0, "carbon_hardness": 6, "filter_type": 1, "variant": 4, "auto_flush_reminder_notif": true, "consumables_low_notif": true, "product_information_notif": true }, "error": { "errors_1": false, "errors_2": false, "errors_3": false, "errors_4": false, "errors_5": false, "errors_6": false, "errors_7": false, "errors_8": false, "errors_9": false, "errors_10": false, "errors_11": false, "errors_12": false, "errors_13": false, "errors_14": false, "errors_15": false, "errors_16": false, "error1_counter": 256, "error2_counter": 256, "error3_counter": 256, "error4_counter": 0, "error5_counter": 0, "error6_counter": 0, "error7_counter": 0, "error8_counter": 0, "error9_counter": 0, "error10_counter": 0, "error11_counter": 0, "error12_counter": 3840, "error13_counter": 0, "error14_counter": 0, "error15_counter": 0, "error16_counter": 0 }, "state": { "start_time": 1632394679, "APPLIANCE_SUCCESSFUL_CONFIGURED": false, "co2_empty": false, "co2_20l_reached": true, "filter_empty": false, "filter_20l_reached": false, "cleaning_mode_active": false, "cleaning_needed": false, "flush_confirmation_required": false, "System_error_bitfield": 0 } } ]

@gkreitz Unfortunately I don't know how to code this part in python. If you need any help I can support. I'm a Java developer.

cg089 commented 2 years ago

I'm also happy to help with my Grohe Blue

darkm20 commented 2 years ago

I'm also happy to help with my Grohe Blue

need somebody who has knowledge with python...

JakobTewes commented 2 years ago

I would love this feature to be implemented ;-)

firstusing commented 1 year ago

Same for me, would love to have that possibility!

gnoffer commented 1 year ago

i would also like to get and support this.

MortenVinding commented 1 year ago

I have started development for Blue Home. Unfortunately I'm far from a python developer, so I'm struggling very hard to understand the code :(

Anyway my initial attempt is in my fork: MortenVinding/homeassistant-grohe_sense

For now it only adds some sensors for the Blue Home, but last time I looked at this (more than a year ago) I at least had a rudimentary support to tap water. Now I just don't remember what I did :(

My goal is to have automations to tap predefined amounts of water, so I can have a small panel next to the tap, with buttons to fill a 1L carafe with still or carbonated water.

You are all more than welcome to add to my code! ;)

dubmaker commented 1 year ago

Hi guys, I am new to Home Assistant and GitHub, and it has been years since I last coded (I know, the perfect trifecta of incompetence). However, I am also the owner of a Grohe Blue and am happy to learn. If you need someone to test anything, please reach out. From a feature perspective, my interest is to understand the state of the filter (next filter change, next cleaning, or last change/cleaning) and the state of the CO2 tank.

gnoffer commented 1 year ago

as you dont have the function to discuss on your gitrepo @MortenVinding - i tried it and for the beginning, the sensors work for my Grohe Blue Home

image

when i push the "valve" button it immediately starts to spend still water but did not stop

gnoffer commented 1 year ago

one Day later, i got:

Error during setup of component grohe_sense 07:13:53 – (FEHLER) Grohe Sense (benutzerdefinierte Integration) Grohe sense refresh token is invalid (or expired), please update your configuration with a new refresh token 07:13:53 – (FEHLER) Grohe Sense (benutzerdefinierte Integration)

MortenVinding commented 1 year ago

as you dont have the function to discuss on your gitrepo @MortenVinding - i tried it and for the beginning, the sensors work for my Grohe Blue Home

Sorry I'm a bit of a GitHub noob Discussions and issues is enabled now :)

when i push the "valve" button it immediately starts to spend still water but did not stop

I should stop after 20ml. at least it does for me 🤷

MortenVinding commented 1 year ago

one Day later, i got:

Error during setup of component grohe_sense 07:13:53 – (FEHLER) Grohe Sense (benutzerdefinierte Integration) Grohe sense refresh token is invalid (or expired), please update your configuration with a new refresh token 07:13:53 – (FEHLER) Grohe Sense (benutzerdefinierte Integration)

there seems to be general problems with refreshing. usually works for me if I restart HA. not ideal I know, but I hardly understand what's going on in the main part of this integration, so I'm afraid I will be no help in solving that. Hopefully @gkreitz will get to the bottom of that if he finds the time.

MortenVinding commented 1 year ago

Hi guys, I am new to Home Assistant and GitHub, and it has been years since I last coded (I know, the perfect trifecta of incompetence). However, I am also the owner of a Grohe Blue and am happy to learn. If you need someone to test anything, please reach out. From a feature perspective, my interest is to understand the state of the filter (next filter change, next cleaning, or last change/cleaning) and the state of the CO2 tank.

All you help is greatly appreciated! :) As i say, my knowledge about programming as a whole, and python i particular, is very limited. So if you have the skills to move on with this, I think many of us would be VERY happy :)

erikkt commented 1 year ago

Have anyone tried to reverse engineer the wires between the faucet and the carbonator? There are four wires, red/black, which I presume are power, and yellow/blue, which probably are some communication protocol. If one could find out how they speak, it would be easy to put a ESP in between. That way you could control all water flow, and also get alerts from the blinking light. That way everything is local, without having to send messages to Germany and back to fill a bottle.

MortenVinding commented 1 year ago

That way everything is local, without having to send messages to Germany and back to fill a bottle.

Good idea. Although I think I would be easier and less destructive to use bluetooth if you goal is to avoid the cloud.

erikkt commented 1 year ago

Perhaps, but my older version doesn't have bluetooth/WiFi. Even so, it's not very destructive to cut a four wire cable.

erikkt commented 1 year ago

I really wanted a button for filling up a jug with soda water and stop when full, and I hate cloud services in home automation. So I did a little hacking in my Blue. Found out which relay that controlled soda water and then attached an ESP relay to it. Now I have a zigbee button that, when pushed, supplies soda water for x amount of seconds and then stops. If anyone else needs it, the hack is quite simple. The ESP releay NO is connected via the blue wires to the solder points. If you want to power the ESP internally, there is unfortunately only 24 VAC available, so you'll need a converter. The supply is available where the white wires are soldered. I'm using this converter, works good: https://de.aliexpress.com/item/1005004924798895.html?gatewayAdapt=glo2deu Just remember to adjust correct voltage via the little pot meter.

2023-02-22 18 22 35

Greencollision commented 7 months ago

hello, following this thread for my grohe blue home, I finished doing another way 1st I found the location,room,appliance id with postman and manually

in config.yaml:

I created a command-line sensor to refresh token
command_line:
  - sensor:
      name: py3_grohe_refreshtoken
      unique_id: py3_grohe_refreshtoken
      scan_interval: 7689600 #any high interval
      command: "python3 /config/myscripts/pythonrequest.py"
      json_attributes:
        - access_token
        - expires_in
        - refresh_expires_in
        - refresh_token
      value_template: "{{ now() + timedelta(seconds = value_json.expires_in)}}"

/config/myscripts/pythonrequest.py

import requests
import json
import sys
import re

url = "https://idp2-apigw.cloud.grohe.com/v3/iot/oidc/refresh"
with open('/config/secrets.yaml', 'r') as secretfile:
    data = secretfile.readlines()
for line in data:
    if 'grohe_current_refresh_token' in line:
        refreshtoken = line.split('"')[1]
        if ('Bearer' in refreshtoken):
            refreshtoken = refreshtoken.split(' ')[1]
payload = json.dumps({ "refresh_token": refreshtoken})
headers = {'Content-Type': 'application/json'}
response = requests.request("POST", url, headers=headers, data=payload)
parsed_json = json.loads(response.text)
newactiv = parsed_json['access_token']
newrefresh = parsed_json['refresh_token']

with open('/config/secrets.yaml', 'r') as secretfile:
    data = secretfile.readlines()
new_data = []
for line in data:
    if 'grohe_current_activ_token' in line:
        new_data.append(f'grohe_current_activ_token: Bearer {newactiv}\n')
    elif 'grohe_current_refresh_token' in line:
        new_data.append(f'grohe_current_refresh_token: "{newrefresh}"\n')
    else:
        new_data.append(line)

with open('/config/secrets.yaml', 'w') as file:
    file.writelines(new_data)

print (response.text)

and a rest command to run water in config.yaml:

rest_command:
  grohe_runwater_command:
    url: https://idp2-apigw.cloud.grohe.com/v3/iot/locations/[MYID]/rooms/[MYROOMID]/appliances/[myapplianceID]/command
    method: "POST"
    headers:
      Authorization: Bearer {{ state_attr('sensor.py3_grohe_refreshtoken','access_token') }}
    content_type: "application/json"
    payload: '{"command": {"co2_status_reset": false,"tap_type":{{int(states("input_number.watertype"))}},"cleaning_mode": false,"filter_status_reset": false,"get_current_measurement": true,"tap_amount":{{int(states("input_number.waterquantity"))}},"factory_reset": false,"revoke_flush_confirmation": false,"exec_auto_flush": false}}'

I also created 2input_numbers: input_number.watertype which can be 1 for still, 3 for sparkling and 2 for half and input_number.waterquantity for the quantity in ml with minimum 50

and then an automation in the UI like:

trigger: on quantity changed to a number between 50 and 2000
conditions: type is not 0 and qty is more than 50
actions:
condition action: 
{% if as_local(states('sensor.py3_grohe_refreshtoken')| as_datetime) <= now()%}
true
{% else %}
false
{%- endif %}
then call py3_grohe_refreshtoken entity

then call grohe_runwater_command service
and finally set watertype and quantity to 0

or my yaml:

alias: testpour
description: ""
trigger:
  - platform: numeric_state
    entity_id:
      - input_number.waterquantity
    above: 50
    below: 9999999
condition:
  - condition: not
    conditions:
      - condition: state
        entity_id: input_number.watertype
        attribute: initial
        state: "0"
  - condition: not
    conditions:
      - condition: numeric_state
        entity_id: input_number.waterquantity
        attribute: initial
        above: 0
        below: 50
action:
  - if:
      - condition: template
        value_template: >-
          {% if as_local(states('sensor.py3_grohe_refreshtoken')| as_datetime)
          <= now()%}
          true
          {% else %}
          false
          {%- endif %}
    then:
      - service: switch.turn_on
        target:
          entity_id: switch.py3_notify_grohe_refreshtoken
        data: {}
        enabled: false
      - service: homeassistant.update_entity
        target:
          entity_id: sensor.py3_grohe_refreshtoken
        data: {}
  - delay:
      hours: 0
      minutes: 0
      seconds: 0
      milliseconds: 100
  - service: rest_command.grohe_runwater_command
    data: {}
  - service: input_number.set_value
    target:
      entity_id:
        - input_number.watertype
        - input_number.waterquantity
      device_id: []
      area_id: []
    data:
      value: 0
mode: single

finally any automation like when click on smartbutton, set water to 1 and qty to 500ml

JakobTewes commented 7 months ago

Heyhey @Greencollision,

can you give me (and surely others) a favor and work over your posts formatting? This would significantly increase readability :-)

MortenVinding commented 7 months ago

Interesting approach @Greencollision !

Certainly solves my biggest problem which is how to get the value of a number entity in to the integration.

I will definitely take a look at this once I get the time.

Asino123 commented 6 months ago

ciao, seguendo questo thread per la mia casa grohe blue, ho finito di fare un altro modo prima ho trovato la posizione, la stanza, l'ID dell'apparecchio con il postino e manualmente

nel file config.yaml:

I created a command-line sensor to refresh token
command_line:
  - sensor:
      name: py3_grohe_refreshtoken
      unique_id: py3_grohe_refreshtoken
      scan_interval: 7689600 #any high interval
      command: "python3 /config/myscripts/pythonrequest.py"
      json_attributes:
        - access_token
        - expires_in
        - refresh_expires_in
        - refresh_token
      value_template: "{{ now() + timedelta(seconds = value_json.expires_in)}}"

/config/myscripts/pythonrequest.py

import requests
import json
import sys
import re

url = "https://idp2-apigw.cloud.grohe.com/v3/iot/oidc/refresh"
with open('/config/secrets.yaml', 'r') as secretfile:
    data = secretfile.readlines()
for line in data:
    if 'grohe_current_refresh_token' in line:
        refreshtoken = line.split('"')[1]
        if ('Bearer' in refreshtoken):
            refreshtoken = refreshtoken.split(' ')[1]
payload = json.dumps({ "refresh_token": refreshtoken})
headers = {'Content-Type': 'application/json'}
response = requests.request("POST", url, headers=headers, data=payload)
parsed_json = json.loads(response.text)
newactiv = parsed_json['access_token']
newrefresh = parsed_json['refresh_token']

with open('/config/secrets.yaml', 'r') as secretfile:
    data = secretfile.readlines()
new_data = []
for line in data:
    if 'grohe_current_activ_token' in line:
        new_data.append(f'grohe_current_activ_token: Bearer {newactiv}\n')
    elif 'grohe_current_refresh_token' in line:
        new_data.append(f'grohe_current_refresh_token: "{newrefresh}"\n')
    else:
        new_data.append(line)

with open('/config/secrets.yaml', 'w') as file:
    file.writelines(new_data)

print (response.text)

e un comando rest per eseguire l'acqua in config.yaml:

rest_command:
  grohe_runwater_command:
    url: https://idp2-apigw.cloud.grohe.com/v3/iot/locations/[MYID]/rooms/[MYROOMID]/appliances/[myapplianceID]/command
    method: "POST"
    headers:
      Authorization: Bearer {{ state_attr('sensor.py3_grohe_refreshtoken','access_token') }}
    content_type: "application/json"
    payload: '{"command": {"co2_status_reset": false,"tap_type":{{int(states("input_number.watertype"))}},"cleaning_mode": false,"filter_status_reset": false,"get_current_measurement": true,"tap_amount":{{int(states("input_number.waterquantity"))}},"factory_reset": false,"revoke_flush_confirmation": false,"exec_auto_flush": false}}'

Ho creato anche 2input_numbers: input_number.watertype che può essere 1 per fermo, 3 per frizzante e 2 per mezzo e input_number.waterquantity per la quantità in ml con minimo 50

e poi un'automazione nell'interfaccia utente come:

trigger: on quantity changed to a number between 50 and 2000
conditions: type is not 0 and qty is more than 50
actions:
condition action: 
{% if as_local(states('sensor.py3_grohe_refreshtoken')| as_datetime) <= now()%}
true
{% else %}
false
{%- endif %}
then call py3_grohe_refreshtoken entity

then call grohe_runwater_command service
and finally set watertype and quantity to 0

o il mio yaml:

alias: testpour
description: ""
trigger:
  - platform: numeric_state
    entity_id:
      - input_number.waterquantity
    above: 50
    below: 9999999
condition:
  - condition: not
    conditions:
      - condition: state
        entity_id: input_number.watertype
        attribute: initial
        state: "0"
  - condition: not
    conditions:
      - condition: numeric_state
        entity_id: input_number.waterquantity
        attribute: initial
        above: 0
        below: 50
action:
  - if:
      - condition: template
        value_template: >-
          {% if as_local(states('sensor.py3_grohe_refreshtoken')| as_datetime)
          <= now()%}
          true
          {% else %}
          false
          {%- endif %}
    then:
      - service: switch.turn_on
        target:
          entity_id: switch.py3_notify_grohe_refreshtoken
        data: {}
        enabled: false
      - service: homeassistant.update_entity
        target:
          entity_id: sensor.py3_grohe_refreshtoken
        data: {}
  - delay:
      hours: 0
      minutes: 0
      seconds: 0
      milliseconds: 100
  - service: rest_command.grohe_runwater_command
    data: {}
  - service: input_number.set_value
    target:
      entity_id:
        - input_number.watertype
        - input_number.waterquantity
      device_id: []
      area_id: []
    data:
      value: 0
mode: single

infine qualsiasi automazione come quando si fa clic sullo smartbutton, si imposta l'acqua su 1 e la quantità su 500 ml

Thanks for your work, could you just tell me how to find the location, room, device ID with the postman and manually?

Greencollision commented 5 months ago

@Asino123 the link and the info you want are there https://github.com/gkreitz/homeassistant-grohe_sense/issues/5#issuecomment-831384828