Siemens/Bosch Home Connect Ecosystem

Topics (not sure which fora)
when not sure where to post, post here and mods will move it to right forum.

Moderators: leecollings, remb0

rgroothuis
Posts: 347
Joined: Friday 03 April 2015 17:09
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by rgroothuis »

Trying to get the plugin working as well but without any luck.

This is what I'm getting, any suggestions on how to fix it?

Code: Select all

2021-05-16 22:20:00.180 Error: (Domoticz-Home-Connect-Plugin) failed to load 'plugin.py', Python Path used was '/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/:/usr/lib/python37.zip:/usr/lib/python3.7:/usr/lib/python3.7/lib-dynload:/usr/local/lib/python3.7/dist-packages:/usr/lib/python3/dist-packages:/usr/lib/python3.7/dist-packages'.
2021-05-16 22:20:00.180 Error: (Dishwasher) Module Import failed, exception: 'ModuleNotFoundError'
2021-05-16 22:20:00.180 Error: (Dishwasher) Module Import failed: ' Name: sseclient'
2021-05-16 22:20:00.180 Error: (Dishwasher) Error Line details not available.
FYI, I went through this entire thread and could find the answer. Will read it again tomorrow, maybe I overlooked something.
rgroothuis
Posts: 347
Joined: Friday 03 April 2015 17:09
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by rgroothuis »

Oh, I just realised that I had to install SSECLIENT module also in Python. This above error is solved, now running into the next error:

Code: Select all

2021-05-16 22:30:19.645 Error: (Dishwasher) Device "" is not authorized by Home_Connect.
2021-05-16 22:30:19.790 Error: (Dishwasher) 'onStart' failed 'TypeError':'string indices must be integers'.
2021-05-16 22:30:19.790 Error: (Dishwasher) ----> Line 459 in '/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/plugin.py', function onStart
2021-05-16 22:30:19.790 Error: (Dishwasher) ----> Line 95 in '/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/plugin.py', function onStart
2021-05-16 22:30:19.790 Error: (Dishwasher) ----> Line 91 in '/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/homeconnecthelper.py', function gethaId
2021-05-16 22:30:23.003 Error: (Dishwasher) Device "" is not authorized by Home_Connect.
2021-05-16 22:30:23.149 Error: (Dishwasher) 'onStart' failed 'TypeError':'string indices must be integers'.
2021-05-16 22:30:23.149 Error: (Dishwasher) ----> Line 459 in '/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/plugin.py', function onStart
2021-05-16 22:30:23.149 Error: (Dishwasher) ----> Line 95 in '/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/plugin.py', function onStart
2021-05-16 22:30:23.149 Error: (Dishwasher) ----> Line 91 in '/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/homeconnecthelper.py', function gethaId
rgroothuis
Posts: 347
Joined: Friday 03 April 2015 17:09
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by rgroothuis »

Just checking, maybe somebody can confirm if I filled in the Siemens connect dev API correctly, see screenshot?

What do I need to fill in for the redirection URL?
Screenshot 2021-05-16 at 22.33.11.png
Screenshot 2021-05-16 at 22.33.11.png (183.83 KiB) Viewed 2710 times
rgroothuis
Posts: 347
Joined: Friday 03 April 2015 17:09
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by rgroothuis »

Anybody any suggestions?

What I don't understand is how to connect my Dishwasher into the account that I've created at https://developer.home-connect.com/! How do I connect my Dishwasher into this account? Any suggestions?

The errors in Domoticz are still:

Code: Select all

2021-05-17 22:02:44.121 Error: (Dishwasher) Device "" is not authorized by Home_Connect.
2021-05-17 22:02:44.321 Error: (Dishwasher) 'onStart' failed 'TypeError':'string indices must be integers'.
2021-05-17 22:02:44.321 Error: (Dishwasher) ----> Line 459 in '/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/plugin.py', function onStart
2021-05-17 22:02:44.321 Error: (Dishwasher) ----> Line 95 in '/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/plugin.py', function onStart
2021-05-17 22:02:44.321 Error: (Dishwasher) ----> Line 91 in '/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/homeconnecthelper.py', function gethaId
In the installation steps it is stated: "Register an application with the following parameters: ** OAuth Flow = "Device Flow"" what name do I need to fill in for the Device Flow? Or is this the actual string that I need to exactly copy when I'm registering? See also screenshot above.

So I guess that somehow to link to my Dishwasher is not setup correctly. I review all the install steps and cannot find what is wrong. Any suggestions?

If anybody can help me on this it would be appreciated. Even suggestions on how to debug this issue would be great. Thanks.
rgroothuis
Posts: 347
Joined: Friday 03 April 2015 17:09
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by rgroothuis »

Anybody who can help on this?
EscApe
Posts: 528
Joined: Thursday 02 April 2015 8:46
Target OS: Linux
Domoticz version: 2020+
Location: The Netherlands
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by EscApe »

rgroothuis wrote: Wednesday 19 May 2021 15:11 Anybody who can help on this?
Hi,

I don’t know if the plugin is being actively maintained. Tried it for a while but it would always stop updating values so I turned to ifttt instead.
rgroothuis
Posts: 347
Joined: Friday 03 April 2015 17:09
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by rgroothuis »

Thanks for the feedback. Indeed of the plugin is not maintained it is an issue.

How did you add the Siemens/Bosch device into the developer API account? THat is something I don't understand. Maybe that is the only issue I'm having. If that is solved, maybe the plugin is working.

I created an account, created an application etc, see also screenshot above. But I was not able to add my dishwasher into that account. Somehow you need to link the DishWasher at home into that account, correct?
EscApe
Posts: 528
Joined: Thursday 02 April 2015 8:46
Target OS: Linux
Domoticz version: 2020+
Location: The Netherlands
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by EscApe »

Sorry, it’s a while ago and I can’t remember this from the top of my mind. Otherwise I would have responded with a real answer ;)
rgroothuis
Posts: 347
Joined: Friday 03 April 2015 17:09
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by rgroothuis »

Decided to delete the application etc in the Siemens portal and redo the config. Seems that I'm one step further, this is the error code/logging now:

Code: Select all

2021-05-19 15:48:06.415 Status: (Dishwasher) Started.
2021-05-19 15:48:07.139 Status: (Dishwasher) Initialized version 3.2.1, author 'Mario Peters'
2021-05-19 15:48:07.138 Status: (Dishwasher) Entering work loop.
2021-05-19 15:48:09.029 Error: (Dishwasher) 'onStart' failed 'TypeError':'string indices must be integers'.
2021-05-19 15:48:09.029 Error: (Dishwasher) ----> Line 459 in '/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/plugin.py', function onStart
2021-05-19 15:48:09.029 Error: (Dishwasher) ----> Line 95 in '/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/plugin.py', function onStart
2021-05-19 15:48:09.029 Error: (Dishwasher) ----> Line 91 in '/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/homeconnecthelper.py', function gethaId
Next is I will check the lines 459, 95 and 91 to see if I see something strange.
garycooper
Posts: 21
Joined: Sunday 10 March 2019 20:50
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by garycooper »

hi ! No-one found how to use this plugin ? Unfortunately, it seems not maintained again ... I have a washer dryer and want to use it with domoticz.
User avatar
FireWizard
Posts: 1747
Joined: Tuesday 25 December 2018 12:11
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Voorthuizen (NL)
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by FireWizard »

Hi @garycooper,

You might want to have a look at this thread as well:

viewtopic.php?f=64&t=33586&hilit=Bosch

Regards
garycooper
Posts: 21
Joined: Sunday 10 March 2019 20:50
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by garycooper »

Hi FireWizard, I saw this thread but I don't understand how to do the same. It would be fun and easily with a plugin
User avatar
FireWizard
Posts: 1747
Joined: Tuesday 25 December 2018 12:11
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Voorthuizen (NL)
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by FireWizard »

Hello @garycooper

I do not have any experience with that plugin, so I'm afraid I cannot help you further.
If you need some help with the Node RED solution, let me know.

Regards
Last edited by FireWizard on Tuesday 26 April 2022 18:40, edited 1 time in total.
teha
Posts: 18
Joined: Wednesday 30 December 2015 20:23
Target OS: Raspberry Pi / ODroid
Domoticz version: Stable
Location: Lomma, Sweden
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by teha »

mario-peters is a star!

finally got my washer and dryer up and running, kind of amazing that this still works after this many years

There are some addons that need to work properly in python to make this happen

So I got things working in an ubuntu virtual environment, i wll in the next comming weeks try to implement this in my production pi environment, there are some differences to take care of with regards to the python install
RPi2 with RFXtrf433(E) at stable, RPi2 with AeonStick S2 on beta, 14*Sonos, Synology DS415play, Axis, D-link camera, PhilipsHue
teha
Posts: 18
Joined: Wednesday 30 December 2015 20:23
Target OS: Raspberry Pi / ODroid
Domoticz version: Stable
Location: Lomma, Sweden
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by teha »

So register an account at https://developer.home-connect.com/
create an application
1_homeconnect.jpg
1_homeconnect.jpg (62.81 KiB) Viewed 2211 times
in domoticz create harware with the home connect plugin
2_Domoticzhardware.jpg
2_Domoticzhardware.jpg (24.48 KiB) Viewed 2211 times
username/pwd should be the username in the app (not in developer.home-connect.com)
port number is your choice, I did choose 8399 for the washer hardware (matching below)

I cloned the homeconnectSSE.sh file to homeconnectSSE_washer.sh
following line should be edited

PYTHON_PATH=/usr/bin/python3
DIR=/home/teha/domoticz/plugins/Domoticz-Home-Connect-Plugin
DAEMON=$DIR/homeconnectSSE.py
DEVICE_NAME=Washer
DOMOTICZ_IP=YOUR_DOMITICZ_LOCAL_IP
DOMOTICZ_PORT=8399
DAEMON_NAME=homeconnectSSE_$DEVICE_NAME
DAEMON_LOG=/home/teha/logs/$DAEMON_NAME.log
# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you ar using the Raspberry Pi GPIO from Python.
DAEMON_USER=YOUR_USER_THAT_RUN_DOMOTICZ

copy homeconnectSSE_washer.sh from plugin to /etc/init.d
sudo update-rc.d homeconnectSSE_washer.sh defaults
sudo service homeconnectSSE_washer.sh start

restart domoticz
restart homeconnectSSE_washer.sh

last lines in the /home/USERNAME/logs/homeconnectSSE_Washer.log should now be some access token and then there will be a new line everytime domoticz make a call to the sseclient

maybe I skipped some of the steps with regards to instalkling python, python3, pip, pip3 and sseclient

hope this helps (remember this is for ubuntu and not for raspberry pi)

One more thing!
If you install the hardware in Domoticz and doing "update" on the harware and you get some data in to the devices (as your bosch device is running) but you don't get any continous updates, this is an indication on the everything is OK at https://developer.home-connect.com/ and also in Domoticz, however there is some problem with the communication to the sseclient, look in the logs at /home/USER/logs/xxxxx.log
RPi2 with RFXtrf433(E) at stable, RPi2 with AeonStick S2 on beta, 14*Sonos, Synology DS415play, Axis, D-link camera, PhilipsHue
mariopeters
Posts: 61
Joined: Wednesday 22 August 2018 12:18
Target OS: NAS (Synology & others)
Domoticz version:
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by mariopeters »

Currently I'm supporting a couple of Home Connect devices.
Shortly I want to implement some more.
Special the devices Hob and Fridge/Freezer or Refrigerator (with camera) are interesting me.
For testing purposes I'm searching for people who own these devices.
Please let me know by creating an issue in https://github.com/mario-peters/Domotic ... ect-Plugin
garycooper
Posts: 21
Joined: Sunday 10 March 2019 20:50
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by garycooper »

Hi Mario ! I don't have Fridge/Freezer or Refrigerator but I've got a washer-dryer machine to test the plugin.

I tried to install the plugin but when I type "sudo service homeconnectSSE_Washer.sh start", it returns "Failed to start homeconnectSSE_Washer.service: Unit homeconnectSSE_Washer.service not found."

Also have this error
"2022-09-25 21:45:27.424 Error: Lave linge: (Lave linge) 'onStart' failed 'TypeError':'can only concatenate str (not "NoneType") to str'.
2022-09-25 21:45:27.424 Error: Lave linge: (Lave linge) ----> Line 464 in '/home/pi/domoticz/plugins/Domoticz-Home-Connect/plugin.py', function onStart
2022-09-25 21:45:27.424 Error: Lave linge: (Lave linge) ----> Line 101 in '/home/pi/domoticz/plugins/Domoticz-Home-Connect/plugin.py', function onStart"
friso82
Posts: 25
Joined: Friday 04 February 2022 14:13
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by friso82 »

Hi,

Tried a lot and finally got something to work. Had to pip3 install the sseclient by the way :-)

Now I get the following in the log. How can this error be solved?

Code: Select all

2023-03-15 10:55:00.112 Status: Bosch Home Connect: Started.
2023-03-15 10:55:00.116 Status: Bosch Home Connect: Entering work loop.
2023-03-15 10:55:07.930 Bosch Home Connect: onStart called Domoticz-Home-Connect-Plugin
2023-03-15 10:55:07.918 Status: Bosch Home Connect: Initialized version 3.2.1, author 'Mario Peters'
2023-03-15 10:55:08.612 Bosch Home Connect: device_code: 1037d4c4-5b8a-4eb9-89a5-188b85dff000
2023-03-15 10:55:08.617 Bosch Home Connect: verification_uri_complete: https://api.home-connect.com/security/oauth/device_verify?user_code=H307-AMYU
2023-03-15 10:55:09.629 Bosch Home Connect: sessionid: html>
2023-03-15 10:55:09.629 <html>
2023-03-15 10:55:09.629
2023-03-15 10:55:09.629 <head>
2023-03-15 10:55:09.629
2023-03-15 10:55:09.629
2023-03-15 10:55:09.629
2023-03-15 10:55:09.629
2023-03-15 10:55:09.629
2023-03-15 10:55:09.629
2023-03-15 10:55:09.629
2023-03-15 10:55:09.629
2023-03-15 10:55:09.629
2023-03-15 10:55:09.629
2023-03-15 10:55:09.629
2023-03-15 10:55:09.629
2023-03-15 10:55:09.629 <meta http-equiv=
2023-03-15 10:55:09.879 Bosch Home Connect: Device "1037d4c4-5b8a-4eb9-89a5-188b85dff000" is authorized by Home-Connect.
2023-03-15 10:55:10.500 Bosch Home Connect: Device "1037d4c4-5b8a-4eb9-89a5-188b85dff000" has token:
2023-03-15 10:55:11.394 Bosch Home Connect: onHeartbeat called
2023-03-15 10:55:11.268 Error: Bosch Home Connect: Call to function 'onStart' failed, exception details:
2023-03-15 10:55:11.285 Error: Bosch Home Connect: Traceback (most recent call last):
2023-03-15 10:55:11.288 Error: Bosch Home Connect: File "/home/pi/domoticz/plugins/HomeConnect/plugin.py", line 459, in onStart
2023-03-15 10:55:11.290 Error: Bosch Home Connect: _plugin.onStart()
2023-03-15 10:55:11.292 Error: Bosch Home Connect: File "/home/pi/domoticz/plugins/HomeConnect/plugin.py", line 95, in onStart
2023-03-15 10:55:11.293 Error: Bosch Home Connect: self.haId = homeconnecthelper.gethaId(self,Parameters["Mode1"],Parameters["Mode4"])
2023-03-15 10:55:11.293 Error: Bosch Home Connect: File "/home/pi/domoticz/plugins/HomeConnect/homeconnecthelper.py", line 91, in gethaId
2023-03-15 10:55:11.293 Error: Bosch Home Connect: Domoticz.Debug(key + " --> " + str(item[key]))
2023-03-15 10:55:11.293 Error: Bosch Home Connect: TypeError: string indices must be integers
2023-03-15 10:55:21.066 Bosch Home Connect: onHeartbeat called
Xavier82
Posts: 178
Joined: Tuesday 07 June 2016 22:09
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Netherlands
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by Xavier82 »

Finally installed this plugin, I also missed the SSEclient, after installing I get this error in the logg:

Code: Select all

2023-03-29 14:21:42.281 Error: Siemens Home Connect: Call to function 'onStart' failed, exception details:
2023-03-29 14:21:42.284 Error: Siemens Home Connect: Traceback (most recent call last):
2023-03-29 14:21:42.284 Error: Siemens Home Connect: File "/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/plugin.py", line 459, in onStart
2023-03-29 14:21:42.284 Error: Siemens Home Connect: _plugin.onStart()
2023-03-29 14:21:42.284 Error: Siemens Home Connect: File "/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/plugin.py", line 95, in onStart
2023-03-29 14:21:42.284 Error: Siemens Home Connect: self.haId = homeconnecthelper.gethaId(self,Parameters["Mode1"],Parameters["Mode4"])
2023-03-29 14:21:42.284 Error: Siemens Home Connect: File "/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/homeconnecthelper.py", line 91, in gethaId
2023-03-29 14:21:42.285 Error: Siemens Home Connect: Domoticz.Debug(key + " --> " + str(item[key]))
2023-03-29 14:21:42.285 Error: Siemens Home Connect: TypeError: string indices must be integers
Domoticz version: 2022.2
Running on Raspberry Pi with OS "Buster"

UPDATE (31-3-2023 11:25)
Seems to be an issue with SingleKeyID?

What can I do to resolve this?
Xavier82
Posts: 178
Joined: Tuesday 07 June 2016 22:09
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Netherlands
Contact:

Re: Siemens/Bosch Home Connect Ecosystem

Post by Xavier82 »

Finally managed to fix the issue.

Important is to use an OTHER PORT!! in the plugin as the Domoticz port

file plugin.py:

Code: Select all

"""
"""
<plugin key="Domoticz-Home-Connect-Plugin" name="Home Connect Plugin" author="Mario Peters" version="3.2.1" wikilink="https://github.com/mario-peters/Domoticz-Home-Connect-Plugin/wiki" externallink="https://github.com/mario-peters/Domoticz-Home-Connect-Plugin">
    <description>
        <h2>Home Connect domoticz plugin 3.2.1</h2><br/>
        <h3>Features</h3>
        <ul style="list-style-type:square">
            <li>Dishwasher supported</li>
            <li>Washer supported</li>
            <li>Oven supported</li>
            <li>Dryer supported</li>
            <li>Hood supported</li>
        </ul>
        <h3>Configuration</h3>
        <ul style="list-style-type:square">
            <li>Username. This is the username which you use in the Home Connect app</li>
            <li>Password. This is the password which you use in the Home Connect app</li>
            <li>Port. This is the port on which the httplistener will listen for commands from the homeconnectSSE.sh script.</li>
            <li>Scope. This is the scope of the devices according to the Home Connect API (<a href="https://developer.home-connect.com/docs/authorization/scope">API Home Connect</a>).
                <ul style="list-style-type:square">
                    <li>Dishwasher</li>
                    <li>Washer</li>
                    <li>Oven</li>
                    <li>Dryer</li>
                    <li>Hood</li>
                </ul>
            </li>
            <li>Custom icons. Option for choosing custom icons. Default is False.</li>
            <li>Client ID: Client ID of the application as you registerd in your Home Connect Developer account.</li>
            <li>Device E-number: Unique E-number of the Siemens/Bosch device.</li>
        </ul>
        <br/><br/>
    </description>
    <params>
        <param field="Username" label="Username" width="150px" required="true"/>
        <param field="Password" label="Password" width="150px" required="true" password="true"/>
        <param field="Port" label="Port" width="150px" required="true"/>
        <param field="Mode1" label="Scope" width="150px" required="true">
            <options>
                <option label="Dishwasher" value="Dishwasher" default="true"/>
                <option label="Washer" value="Washer"/>
                <option label="Oven" value="Oven"/>
                <option label="Dryer" value="Dryer"/>
                <option label="Hood" value="Hood"/>
            </options>
        </param>
        <param field="Mode2" label="Custom icons" width="150px" required="false">
            <options>
                <option label="True" value="True"/>
                <option label="False" value="False" default="true"/>
            </options>
        </param>
        <param field="Mode3" label="Client ID" width="600px" required="true"/>
        <param field="Mode4" label="Device E-number" width="150px" required="true"/>
    </params>
</plugin>
"""
import Domoticz
import json
import base64
import homeconnecthelper
import datetime
import os

class BasePlugin:

    httpServerConn = None
    httpServerConns = {}
    httpClientConn = None
    clientid = ""
    haId = ""
    access_token = ""
    token_expired = datetime.datetime.now()
    refresh_token = ""
    selectedprogram = ""
    DRY_ICON = "Domoticz-Home-Connect-PluginAlt1"
    RINSE_ICON = "Domoticz-Home-Connect-PluginAlt2"
    SHINE_ICON = "Domoticz-Home-Connect-PluginAlt3"
    FINISH_ICON = "Domoticz-Home-Connect-PluginAlt4"
    CLEAN_ICON = "Domoticz-Home-Connect-PluginAlt5"
    HOMECONNECT_ICON = "Domoticz-Home-Connect-Plugin"
    DEVICE_DISHWASHER = "Dishwasher"
    DEVICE_WASHER = "Washer"
    DEVICE_OVEN = "Oven"
    DEVICE_DRYER = "Dryer"
    DEVICE_HOOD = "Hood"

    def __init__(self):
        #self.var = 123
        return

    def onStart(self):
        Domoticz.Log("onStart called "+Parameters["Key"])
        self.clientid = Parameters["Mode3"]
        homeconnecthelper.connectHomeConnect(self, Parameters["Username"], Parameters["Password"], Parameters["Mode1"])
        self.haId = homeconnecthelper.gethaId(self, Parameters["Mode1"], Parameters["Mode4"])
        Domoticz.Log("haId: " + (self.haId or ""))
        if Parameters["Mode2"] == "True":
            loadIcons(self, Images)
        
        #Create devices
        if len(Devices) == 0:
            Domoticz.Log("Create devices")
            self.haId = "blaat"
            if self.haId != None:
                #Generic devices
                ##Operation state
                if Parameters["Mode2"] == "True":
                    #Domoticz.Device(Name="Operation state", Unit=1, TypeName="Custom", Image=Images[self.HOMECONNECT_ICON].ID).Create()
                    Domoticz.Device(Name="Operation state", Unit=1, TypeName="Text", Image=Images[self.HOMECONNECT_ICON].ID).Create()
                else:
                    Domoticz.Device(Name="Operation state", Unit=1, TypeName="Text").Create()
                
                ##Power state
                Domoticz.Device(Name="Power state", Unit=2, Type=244, Subtype=73, Switchtype=0).Create()

                ##Active program
                if Parameters["Mode2"] == "True":
                    Domoticz.Device(Name="Active program", Unit=3, TypeName="Text", Image=Images[self.HOMECONNECT_ICON].ID).Create()
                else:
                    Domoticz.Device(Name="Active program", Unit=3, TypeName="Text").Create()

                ##Program progres
                Domoticz.Device(Name="Program progress", Unit=6, TypeName="Percentage").Create()

                ##Remaining program time
                #Domoticz.Device(Name="Remaining program time", Unit=7, TypeName="Text").Create()
                if Parameters["Mode2"] == "True":
                    Domoticz.Device(Name="Remaining program time", Unit=7, TypeName="Custom", Image=Images[self.HOMECONNECT_ICON].ID).Create()
                else:
                    Domoticz.Device(Name="Remaining program time", Unit=7, TypeName="Custom").Create()

                ##Estimated time
                if Parameters["Mode2"] == "True":
                    #Domoticz.Device(Name="Estimated time", Unit=8, TypeName="Custom", Image=Images[self.HOMECONNECT_ICON].ID).Create()
                    Domoticz.Device(Name="Estimated program time", Unit=8, TypeName="Text", Image=Images[self.HOMECONNECT_ICON].ID).Create()
                else:
                    Domoticz.Device(Name="Estimated program time", Unit=8, TypeName="Text").Create()

                ##Device specific devices
                if Parameters["Mode1"] == self.DEVICE_DISHWASHER:
                    #Custom Dishwasher devices
                    if Parameters["Mode2"] == "True":
                        Domoticz.Device(Name="Current program state", Unit=4, TypeName="Text", Image=Images[self.HOMECONNECT_ICON].ID).Create()
                    else:
                        Domoticz.Device(Name="Current program state", Unit=4, TypeName="Text").Create()

                    ##Door state
                    Domoticz.Device(Name="Door state", Unit=5, Type=244, Subtype=73, Switchtype=11).Create()

                if Parameters["Mode1"] == self.DEVICE_WASHER:
                    #Customer Washer devices
                    ##Door state
                    Domoticz.Device(Name="Door state", Unit=5, Type=244, Subtype=73, Switchtype=11).Create()

                if Parameters["Mode1"] == self.DEVICE_OVEN:
                    #Custom Oven devices
                    ##Door state
                    Domoticz.Device(Name="Door state", Unit=5, Type=244, Subtype=73, Switchtype=11).Create()

                    Domoticz.Device(Name="Current cavity temperature", Unit=9, TypeName="Temperature").Create()
                if Parameters["Mode1"] == self.DEVICE_DRYER:
                    #Custom Dryer devices
                    ##Door state
                    Domoticz.Device(Name="Door state", Unit=5, Type=244, Subtype=73, Switchtype=11).Create()

                if Parameters["Mode1"] == self.DEVICE_HOOD:
                    #Custom Hood devices
                    ##Elepsed program time
                    if Parameters["Mode2"] == "True":
                        #Domoticz.Device(Name="Elapesed program time", Unit=9, TypeName="Custom", Image=Images[self.HOMECONNECT_ICON].ID).Create()
                        Domoticz.Device(Name="Elapsed program time", Unit=9, TypeName="Text", Image=Images[self.HOMECONNECT_ICON].ID).Create()
                    else:
                        Domoticz.Device(Name="Elepsed program time", Unit=9, TypeName="Text").Create()

                    ##Venting level
                    OptionsVentingLevel = {"LevelActions": "||||", "LevelNames": "FanOff|FanStage01|FanStage02|FanStage03|FanStage04|FanStage05", "LevelOffHidden": "false", "SelectorStyle": "1"}
                    Domoticz.Device(Name="Venting level", Unit=10, TypeName="Selector Switch", Options=OptionsVentingLevel).Create()

                    ##Intensive level
                    OptionsIntensiveLevel = {"LevelActions": "||||", "LevelNames": "IntensiveStageOff|IntensiveStage1|IntensiveStage2", "LevelOffHidden": "false", "SelectorStyle": "1"}
                    Domoticz.Device(Name="Intensive level", Unit=11, TypeName="Selector Switch", Options=OptionsIntensiveLevel).Create()

        operationstate = "" 
        operationstate = homeconnecthelper.getOperationState(self,self.haId)
        if operationstate != "" and operationstate != None:
            #Devices[1].Update(nValue=Devices[1].nValue,sValue=operationstate.rpartition(".")[2],Options={"Custom": operationstate.rpartition(".")[2]})
            Devices[1].Update(nValue=Devices[1].nValue,sValue=operationstate.rpartition(".")[2])

        powerstate = ""
        powerstate = homeconnecthelper.getPowerState(self,self.haId)
        if powerstate != "" and powerstate != None:
            powerstate = powerstate.rpartition(".")[2]
            if powerstate == "On":
                Devices[2].Update(nValue=1,sValue="On")
            else:
                Devices[2].Update(nValue=0,sValue="Off")

        self.selectedprogram = ""
        self.selectedprogram = homeconnecthelper.getActiveProgram(self,self.haId)
        if self.selectedprogram != "" and self.selectedprogram != None:
            self.selectedprogram = self.selectedprogram.rpartition(".")[2]
            Devices[3].Update(nValue=Devices[3].nValue,sValue=self.selectedprogram)

        doorstate = ""
        doorstate = homeconnecthelper.getDoorState(self,self.haId)
        if doorstate != "" and doorstate != None:
            doorstate = doorstate.rpartition(".")[2]
            if doorstate == "Open":
                Devices[5].Update(nValue=1,sValue="Open")
            else:
                Devices[5].Update(nValue=0,sValue="Closed")

        self.httpServerConn = Domoticz.Connection(Name="Home-Connect "+Parameters["Mode1"]+" WebServer", Transport="TCP/IP", Protocol="HTTP", Port=Parameters["Port"])
        self.httpServerConn.Listen()
        Domoticz.Log("Listen on Home-Connect Webserver - Port: "+str(Parameters["Port"]))

    def onStop(self):
        Domoticz.Log("onStop called")

    def onConnect(self, Connection, Status, Description):
        Domoticz.Log("onConnect called")

        if (Status == 0):
            Domoticz.Debug("Connected successfully to "+Connection.Address+":"+Connection.Port)
        else:
            Domoticz.Log("Failed to connect ("+str(Status)+") to: "+Connection.Address+":"+Connection.Port+" with error: "+Description)
            Domoticz.Debug(str(Connection))
        if (Connection != self.httpClientConn):
            self.httpServerConns[Connection.Name] = Connection
            self.httpClientConn = Connection
        return

    def onMessage(self, Connection, Data):
        Domoticz.Log("onMessage called")
        
        data = ""
        for key_msg, value_msg in Data.items():
            Domoticz.Debug(str(key_msg)+" --> "+str(value_msg))
            if key_msg == "Data":
                a = value_msg.decode("utf-8")
                #Domoticz.Log(a)
                if a == "access_token":
                    if homeconnecthelper.isTokenValid(self) != True:
                        if homeconnecthelper.refreshToken(self) != True:
                            homeconnecthelper.connectHomeConnect(self,Parameters["Username"],Parameters["Password"],Parameters["Mode1"])
                    data = self.access_token
                elif a.startswith("haId:") == True:
                    data = self.haId
                else:
                    #Domoticz.Log(a)
                    json_items = json.loads(a)
                    deviceItems = []
                    for q,w in json_items.items():
                        Domoticz.Debug(q)
                        if q == "items":
                            deviceItems = w
                    for deviceItemList in deviceItems:
                        Domoticz.Debug(str(deviceItemList))
                        deviceKey = ""
                        deviceValue = ""
                        for k in deviceItemList:
                            Domoticz.Debug(k + " —> "+str(deviceItemList[k]))
                            if k == "key":
                                deviceKey = deviceItemList[k]
                            elif k == "value":
                                deviceValue = deviceItemList[k]
                        if (deviceKey != "") and (deviceValue != ""):
                            if deviceKey == "BSH.Common.Root.SelectedProgram":
                                Domoticz.Log(deviceKey+" —> "+str(deviceValue))
                                Devices[3].Update(nValue=Devices[3].nValue,sValue=deviceValue.rpartition(".")[2])
                            elif deviceKey == "BSH.Common.Option.Hood.IntensiveLevel":
                                Domoticz.Log(deviceKey+" --> "+str(deviceValue))
                                if Parameters["Mode1"] == self.DEVICE_HOOD:
                                    intensiveLevel = deviceValue.rpartition(".")[2]
                                    if intensiveLevel == "IntensiveStageOff":
                                        Devices[11].Update(nValue=0,sValue="0")
                                    elif intensiveLevel == "IntensiveStage1":
                                        Devices[11].Update(nValue=10,sValue="10")
                                    elif intensiveLevel == "IntensiveStage2":
                                        Devices[11].Update(nValue=20,sValue="20")
                            elif deviceKey == "BSH.Common.Option.Hood.VentingLevel":
                                Domoticz.Log(deviceKey+" --> "+str(deviceValue))
                                if Parameters["Mode1"] == self.DEVICE_HOOD:
                                    ventingLevel = deviceValue.rpartition(".")[2]
                                    if ventingLevel == "FanOff":
                                        Devices[10].Update(nValue=0,sValue="0")
                                    elif ventingLevel == "FanStage01":
                                        Devices[10].Update(nValue=10,sValue="10")
                                    elif ventingLevel == "FanStage02":
                                        Devices[10].Update(nValue=20,sValue="20")
                                    elif ventingLevel == "FanStage03":
                                        Devices[10].Update(nValue=30,sValue="30")
                                    elif ventingLevel == "FanStage04":
                                        Devices[10].Update(nValue=40,sValue="40")
                                    elif ventingLevel == "FanStage05":
                                        Devices[10].Update(nValue=50,sValue="50")
                            elif deviceKey == "BSH.Common.Option.ElapsedProgramTime":
                                Domoticz.Log(deviceKey+" --> "+str(deviceValue))
                                if Parameters["Mode1"] == self.DEVICE_HOOD:
                                    Devices[9].Update(nValue=0,sValue=str(deviceValue), Options={"Custom": "1;sec"})
                            elif deviceKey == "BSH.Common.Option.RemainingProgramTime":
                                Domoticz.Log(deviceKey+" —> "+str(deviceValue))
                                #Devices[7].Update(nValue=deviceValue,sValue=str(deviceValue)+" sec")
                                Devices[7].Update(nValue=0,sValue=str(deviceValue), Options={"Custom": "1;sec"})
                                if deviceValue > 0:
                                    remainingTime = datetime.datetime.now() + datetime.timedelta(seconds=deviceValue)
                                    Domoticz.Debug("remainingTime: "+str(remainingTime.strftime("%H:%M")))
                                    Devices[8].Update(nValue=Devices[8].nValue,sValue=str(remainingTime.strftime("%H:%M")))
                                    #Devices[8].Update(nValue=Devices[8].nValue,sValue=str(remainingTime.hour),Options={"Custom": str(remainingTime.hour)+"; : "+str(remainingTime.strftime("%M"))})
                            elif deviceKey == "BSH.Common.Option.ProgramProgress": 
                                Domoticz.Log(deviceKey+" —> "+str(deviceValue))
                                Devices[6].Update(nValue=deviceValue,sValue=str(deviceValue))
                                if Parameters["Mode1"] == self.DEVICE_DISHWASHER:
                                    if Devices[3].sValue == "PreRinse":
                                        if Parameters["Mode2"] == "True":
                                            Devices[4].Update(nValue=Devices[4].nValue,sValue="Rinse", Image=Images[self.RINSE_ICON].ID)
                                        else:
                                            Devices[4].Update(nValue=Devices[4].nValue,sValue="Rinse")
                                    #elif Devices[3].sValue == "Quick45":
                                        #TODO
                                    #elif Devices[3].sValue == "Glass48":
                                        #TODO
                                    #elif Devices[3].sValue == "Kurz40":
                                        #TODO
                                    #elif Devices[3].sValue == "NightWash":
                                        #TODO
                                    elif Devices[3].sValue == "Eco50":
                                        if deviceValue > 0 and deviceValue < 10:
                                            if Parameters["Mode2"] == "True":
                                                Devices[4].Update(nValue=Devices[4].nValue,sValue="Rinse", Image=Images[self.RINSE_ICON].ID)
                                            else:
                                                Devices[4].Update(nValue=Devices[4].nValue,sValue="Rinse")
                                        elif deviceValue >= 10 and deviceValue < 60:
                                            if Parameters["Mode2"] == "True":
                                                Devices[4].Update(nValue=Devices[4].nValue,sValue="Clean", Image=Images[self.CLEAN_ICON].ID)
                                            else:
                                                Devices[4].Update(nValue=Devices[4].nValue,sValue="Clean")
                                        elif deviceValue >= 60 and deviceValue < 70:
                                            if Parameters["Mode2"] == "True":
                                                Devices[4].Update(nValue=Devices[4].nValue,sValue="Shine", Image=Images[self.SHINE_ICON].ID)
                                            else:
                                                Devices[4].Update(nValue=Devices[4].nValue,sValue="Shine")
                                        else:
                                            if Parameters["Mode2"] == "True":
                                                Devices[4].Update(nValue=Devices[4].nValue,sValue="Dry", Image=Images[self.DRY_ICON].ID)
                                            else:
                                                Devices[4].Update(nValue=Devices[4].nValue,sValue="Dry")
                                    #elif Devices[3].sValue == "Auto2":
                                        #TODO
                                    #elif Devices[3].sValue == "Intensiv70":
                                        #TODO
                            elif deviceKey == "BSH.Common.Root.ActiveProgram":
                                Domoticz.Log(deviceKey+" —> "+str(deviceValue))
                                if "." in str(deviceValue):
                                    Devices[3].Update(nValue=Devices[3].nValue,sValue=str(deviceValue).rpartition(".")[2])
                                else:
                                    Devices[3].Update(nValue=Devices[3].nValue,sValue=str(deviceValue))
                            elif deviceKey == "BSH.Common.Status.OperationState":
                                Domoticz.Log(deviceKey+" —> "+str(deviceValue))
                                #Devices[1].Update(nValue=Devices[1].nValue,sValue=deviceValue.rpartition(".")[2],Options={"Custom": deviceValue.rpartition(".")[2]})
                                Devices[1].Update(nValue=Devices[1].nValue,sValue=deviceValue.rpartition(".")[2])
                            elif deviceKey == "BSH.Common.Setting.PowerState":
                                Domoticz.Log(deviceKey+" —> "+str(deviceValue))
                                powerstate = deviceValue.rpartition(".")[2]
                                if powerstate == "On":
                                    Devices[2].Update(nValue=1,sValue="On")
                                else:
                                    Devices[2].Update(nValue=0,sValue="Off")
                            elif deviceKey == "BSH.Common.Status.DoorState":
                                Domoticz.Log(deviceKey+" —> "+str(deviceValue))
                                doorstate = deviceValue.rpartition(".")[2]
                                if doorstate == "Open":
                                    Devices[5].Update(nValue=1,sValue="Open")
                                else:
                                    Devices[5].Update(nValue=0,sValue="Closed")
                            elif deviceKey == "BSH.Common.Event.ProgramFinished":
                                Domoticz.Log(deviceKey+" —> "+str(deviceValue))
                                Devices[1].Update(nValue=Devices[1].nValue,sValue="")
                                Devices[3].Update(nValue=Devices[3].nValue,sValue="")
                                if Parameters["Mode1"] == self.DEVICE_DISHWASHER:
                                    Devices[4].Update(nValue=Devices[4].nValue,sValue="")
                                Devices[6].Update(nValue=100,sValue=str(100))
                                #Devices[7].Update(nValue=0,sValue="0 sec")
                                Devices[7].Update(nValue=0,sValue="0", Options= {"Custom": "1;sec"})
                                Devices[8].Update(nValue=0,sValue="")
                            elif deviceKey == "Cooking.Oven.Status.CurrentCavityTemperature":
                                Domoticz.Log(deviceKey+" —> "+str(deviceValue))
                                if Parameters["Mode1"] == self.DEVICE_OVEN:
                                    Domoticz.Debug("Temp: "+str(deviceValue))
                                    Devices[9].Update(nValue=0,sValue=str(deviceValue))
                            else:
                                Domoticz.Log(deviceKey+" —> "+str(deviceValue))
        self.httpClientConn.Send({"Status":"200 OK", "Headers": {"Connection": "keep-alive", "Accept": "Content-Type: text/html; charset=UTF-8"}, "Data": data})

    def onCommand(self, Unit, Command, Level, Hue):
        Domoticz.Log("onCommand called for Unit " + str(Unit) + ": Parameter '" + str(Command) + "', Level: " + str(Level))
        if Parameters["Mode1"] == self.DEVICE_DISHWASHER:
            if str(Command) == "On":
                if homeconnecthelper.setPowerState(self, self.DEVICE_DISHWASHER, str(Command)) == True:
                    Devices[Unit].Update(nValue=1,sValue="On")
            elif str(Command) == "Off":
                if homeconnecthelper.setPowerState(self, self.DEVICE_DISHWASHER, str(Command)) == True:
                    Devices[Unit].Update(nValue=1,sValue="Off")
        elif Parameters["Mode1"] == self.DEVICE_OVEN:
            if str(Command) == "On":
                if homeconnecthelper.setPowerState(self, self.DEVICE_OVEN, str(Command)) == True:
                    Devices[Unit].Update(nValue=1,sValue="On")
            elif str(Command) == "Off":
                if homeconnecthelper.setPowerState(self, self.DEVICE_OVEN, str("Standby")) == True:
                    Devices[Unit].Update(nValue=0,sValue="Off")
        elif Parameters["Mode1"] == self.DEVICE_HOOD:
            if str(Command) == "Set Level" and Unit == 10:
                if Level == 0:
                    if homeconnecthelper.setVentingLevel(self,"FanOff") == True:
                        Devices[10].Update(nValue=0,sValue="0")
                elif Level == 10:
                    if homeconnecthelper.setVentingLevel(self,"FanStage01") == True:
                        Devices[10].Update(nValue=10,sValue="10")
                elif Level == 20:
                    if homeconnecthelper.setVentingLevel(self,"FanStage02") == True:
                        Devices[10].Update(nValue=20,sValue="20")
                elif Level == 30:
                    if homeconnecthelper.setVentingLevel(self,"FanStage03") == True:
                        Devices[10].Update(nValue=30,sValue="30")
                elif Level == 40:
                    if homeconnecthelper.setVentingLevel(self,"FanStage04") == True:
                        Devices[10].Update(nValue=40,sValue="40")
                elif Level == 50:
                    if homeconnecthelper.setVentingLevel(self,"FanStage05") == True:
                        Devices[10].Update(nValue=50,sValue="50")
            elif str(Command) == "Set Level" and Unit == 11:
                if Level == 0:
                    if homeconnecthelper.setIntensiveLevel(self,"IntensiveStageOff") == True:
                        Devices[11].Update(nValue=0,sValue="0")
                elif Level == 10:
                    if homeconnecthelper.setIntensiveLevel(self,"IntensiveStage1") == True:
                        Devices[11].Update(nValue=10,sValue="10")
                elif Level == 20:
                    if homeconnecthelper.setIntensiveLevel(self,"IntensiveStage2") == True:
                        Devices[11].Update(nValue=20,sValue="20")

    def onNotification(self, Name, Subject, Text, Status, Priority, Sound, ImageFile):
        Domoticz.Log("Notification: " + Name + "," + Subject + "," + Text + "," + Status + "," + str(Priority) + "," + Sound + "," + ImageFile)

    def onDisconnect(self, Connection):
        Domoticz.Log("onDisconnect called")

        if (Connection.Name in self.httpServerConns):
            del self.httpServerConns[Connection.Name]

    def onHeartbeat(self):
        Domoticz.Log("onHeartbeat called")

global _plugin
_plugin = BasePlugin()

def onStart():
    global _plugin
    _plugin.onStart()

def onStop():
    global _plugin
    _plugin.onStop()

def onConnect(Connection, Status, Description):
    global _plugin
    _plugin.onConnect(Connection, Status, Description)

def onMessage(Connection, Data):
    global _plugin
    _plugin.onMessage(Connection, Data)

def onCommand(Unit, Command, Level, Hue):
    global _plugin
    _plugin.onCommand(Unit, Command, Level, Hue)

def onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile):
    global _plugin
    _plugin.onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile)

def onDisconnect(Connection):
    global _plugin
    _plugin.onDisconnect(Connection)

def onHeartbeat():
    global _plugin
    _plugin.onHeartbeat()

    # Generic helper functions
def DumpConfigToLog():
    for x in Parameters:
        if Parameters[x] != "":
            Domoticz.Debug( "'" + x + "':'" + str(Parameters[x]) + "'")
    Domoticz.Debug("Device count: " + str(len(Devices)))
    for x in Devices:
        Domoticz.Debug("Device:           " + str(x) + " - " + str(Devices[x]))
        Domoticz.Debug("Device ID:       '" + str(Devices[x].ID) + "'")
        Domoticz.Debug("Device Name:     '" + Devices[x].Name + "'")
        Domoticz.Debug("Device nValue:    " + str(Devices[x].nValue))
        Domoticz.Debug("Device sValue:   '" + Devices[x].sValue + "'")
        Domoticz.Debug("Device LastLevel: " + str(Devices[x].LastLevel))
    return

def loadIcons(self, Images):
    #Home-Connect Logo
    if self.HOMECONNECT_ICON in Images:
        Domoticz.Debug("ID: "+str(Images[self.HOMECONNECT_ICON].ID))
    else:
        Domoticz.Debug("no Home-Connect Image")
        Domoticz.Image("Home-Connect-Plugin Icons.zip").Create()

    #Dry Logo
    if self.DRY_ICON in Images:
        Domoticz.Debug("ID: "+str(Images[self.DRY_ICON].ID))
    else:
        Domoticz.Debug("no Home-Connect dry Image")
        Domoticz.Image("Home-Connect-Plugin1 Icons.zip").Create()

    #Rinse Logo
    if self.RINSE_ICON in Images:
        Domoticz.Debug("ID: "+str(Images[self.RINSE_ICON].ID))
    else:
        Domoticz.Debug("no Home-Connect rinse Image")
        Domoticz.Image("Home-Connect-Plugin2 Icons.zip").Create()

    #Shine Logo
    if self.SHINE_ICON in Images:
        Domoticz.Debug("ID: "+str(Images[self.SHINE_ICON].ID))
    else:
        Domoticz.Debug("no Home-Connect shine Image")
        Domoticz.Image("Home-Connect-Plugin3 Icons.zip").Create()

    #Finish Logo
    if self.FINISH_ICON in Images:
        Domoticz.Debug("ID: "+str(Images[self.FINISH_ICON].ID))
    else:
        Domoticz.Debug("no Home-Connect finish Image")
        Domoticz.Image("Home-Connect-Plugin4 Icons.zip").Create()

    #Clean Logo
    if self.CLEAN_ICON in Images:
        Domoticz.Debug("ID: "+str(Images[self.CLEAN_ICON].ID))
    else:
        Domoticz.Debug("no Home-Connect clean Image")
        Domoticz.Image("Home-Connect-Plugin5 Icons.zip").Create()

    Domoticz.Log(str(Images))
and file homeconnecthelper.py:

Code: Select all

import Domoticz
import datetime
import requests
import json
from sseclient import SSEClient
from requests.exceptions import HTTPError
import traceback

BASEURL = "https://api.home-connect.com"
HEADER_URLENCODED = {"content-type": "application/x-www-form-urlencoded"}
CLIENT_ID = "EB32287B74E25B85212E25C2A6A3793B48CB2B4361F742101XXXXXXXXXX"
APP_NAME = "Domoticz connection"

"""
Method for checking if a oauth2 token is still valid
 
Parameters
----------
self : BasePlugin
    for getting plugin variables
"""
def isTokenValid(self):
    if datetime.datetime.now() < self.token_expired:
        return True
    return False

"""
Method for refreshing the token after token is invalid (24 hours)

Parameters
----------
self : BasePlugin
    for getting plugin variables

Return values
-------------
True : Token correctly refreshed
False : Token not correctly refreshed
"""
def refreshToken(self):
    url_refresh_token = BASEURL + "/security/oauth/token"
    data_refresh_token = {"refresh_token": self.refresh_token, "grant_type": "refresh_token"}
    response_refresh_token = requests.post(url_refresh_token,data_refresh_token,HEADER_URLENCODED)
    json_refresh_token = json.loads(response_refresh_token.text)
    response_refresh_token.close()
    self.access_token = ""
    self.refresh_token = ""
    for key, value in json_refresh_token.items():
        if key == "access_token":
            self.access_token = value
        if key == "expires_in":
            self.token_expires = datetime.datetime.now() + datetime.timedelta(seconds=value)
        if key == "refresh_token":
            self.refresh_token = value

    if (self.access_token == "") or (self.token_expired < datetime.datetime.now()) or (self.refresh_token == ""):
        return False
    return True

"""
Method for getting the Home-Connect Appliance ID

Parameters
----------
self : BasePlugin
    for getting plugin variables
scope : String
    Devide for wich the haId must be retrieved

Return
------
haId : Retrieved String or None
"""
def gethaId(self, scope, enumber):
    url_homeappliances = BASEURL + "/api/homeappliances"
    header = {"Accept": "application/vnd.bsh.sdk.v1+json", "Authorization": "Bearer " + self.access_token}
    response_homeappliances = requests.get(url_homeappliances, headers=header)
    Domoticz.Debug(response_homeappliances.text)
    json_homeappliances = json.loads(response_homeappliances.text)
    response_homeappliances.close()

    if "data" in json_homeappliances:
        homeappliances_data = json_homeappliances["data"]
        for item in homeappliances_data:
            if "haId" in item and "type" in item and "enumber" in item:
                haId = item["haId"]
                scopeType = item["type"]
                en = item["enumber"]

                if scopeType == scope or (scopeType + "-Monitor") == scope:
                    if enumber == en:
                        Domoticz.Log("Enumber: " + enumber)
                        return haId

    return None

def getActiveProgram(self,haId):
    Domoticz.Debug("getActiveProgram")
    url_getActiveProgram = BASEURL + "/api/homeappliances/" + (haId or "") + "/programs/active"
    header = {"Accept": "application/vnd.bsh.sdk.v1+json", "Authorization": "Bearer " + self.access_token}
    response_getActiveProgram = requests.get(url_getActiveProgram, headers=header)
    json_items = json.loads(str(response_getActiveProgram.text))
    response_getActiveProgram.close()
    Domoticz.Debug(response_getActiveProgram.text)
    for key_item, value_item in json_items.items():
        Domoticz.Debug(str(key_item)+" --> "+str(value_item))
        for data in value_item:
            if data == "key":
                Domoticz.Debug(data+" --> "+str(value_item[data]))
                return str(value_item[data])
    return ""

def getDoorState(self,haId):
    Domoticz.Debug("getDoorState")
    url_getDoorState = BASEURL + "/api/homeappliances/" + (haId or "") + "/status/BSH.Common.Status.DoorState"
    header = {"Accept": "application/vnd.bsh.sdk.v1+json", "Authorization": "Bearer " + self.access_token}
    response_getDoorState = requests.get(url_getDoorState, headers=header)
    json_items = json.loads(str(response_getDoorState.text))
    response_getDoorState.close()
    Domoticz.Debug(response_getDoorState.text)
    for key_item, value_item in json_items.items():
        Domoticz.Debug(str(key_item)+" --> "+str(value_item))
        for data in value_item:
            if data == "value":
                Domoticz.Debug(data+" --> "+str(value_item[data]))
                return str(value_item[data])

def getPowerState(self, haId):
    Domoticz.Debug("getPowerState")
    if self.haId is not None:
        url_setPowerState = BASEURL + "/api/homeappliances/" + self.haId + "/settings/BSH.Common.Setting.PowerState"
    else:
        Domoticz.Log("Home Appliance ID is not available.")
        return

    header = {"Accept": "application/vnd.bsh.sdk.v1+json", "Authorization": "Bearer " + self.access_token}
    response_getPowerState = requests.get(url_getPowerState, headers=header)
    json_items = json.loads(str(response_getPowerState.text))
    response_getPowerState.close()
    Domoticz.Debug(response_getPowerState.text)

    for key_item, value_item in json_items.items():
        Domoticz.Debug(str(key_item)+" --> "+str(value_item))
        for data in value_item:
            if data == "value":
                Domoticz.Debug(data+" --> "+str(value_item[data]))
                return str(value_item[data])
def setVentingLevel(self,level):
    Domoticz.Debug("setVentingLevel")
    url_setVentingLevel = BASEURL + "/api/homeappliances/"+ self.haId + "/programs/active/options/Cooking.Common.Option.Hood.VentingLevel"
    header = {"Content-Type": "application/vnd.bsh.sdk.v1+json", "Authorization": "Bearer " + self.access_token}
    data = json.dumps({
      'data': {
        'key': 'Cooking.Common.Option.Hood.VentingLevel',
        'value': 'Cooking.Hood.EnumType.Stage.'+level,
        'type': 'Cooking.Hood.EnumType.Stage',
        'constrains': {
           'allowedvalues': ['Cooking.Hood.EnumType.Stage.FanOff', 'Cooking.Hood.EnumType.Stage.FanStage01', 'Cooking.Hood.EnumType.Stage.FanStage02', 'Cooking.Hood.EnumType.Stage.FanStage03', 'Cooking.Hood.EnumType.Stage.FanStage04', 'Cooking.Hood.EnumType.Stage.FanStage05']
        }
      }
    })
    response = requests.put(url_setVentingLevel, headers=header, data=data)
    Domoticz.Log(str(response.status_code))
    if str(response.status_code) == "204":
        response.close()
        return True
    response.close()
    return False 

def setIntensiveLevel(self,level):
    Domoticz.Debug("setIntensiveLevel")
    url_setIntentsiveLevel = BASEURL + "/api/homeappliances/"+ self.haId + "/programs/active/options/Cooking.Common.Option.Hood.IntensiveLevel"
    header = {"Content-Type": "application/vnd.bsh.sdk.v1+json", "Authorization": "Bearer " + self.access_token}
    data = json.dumps({
      'data': {
        'key': 'Cooking.Common.Option.Hood.IntensiveLevel',
        'value': 'Cooking.Hood.EnumType.IntensiveStage.'+level,
        'type': 'Cooking.Hood.EnumType.IntensiveStage',
        'constrains': {
           'allowedvalues': ['Cooking.Hood.EnumType.IntensiveStage.IntensiveStageOff', 'Cooking.Hood.EnumType.IntensiveStage.IntensiveStage1', 'Cooking.Hood.EnumType.IntensiveStage.IntensiveStage2']
        }
      }
    })
    response = requests.put(url_setIntensiveLevel, headers=header, data=data)
    Domoticz.Log(str(response.status_code))
    if str(response.status_code) == "204":
        response.close()
        return True
    response.close()
    return False 

def setPowerState(self,devicetype,state):
    Domoticz.Debug("setPowerState")
    url_setPowerState = BASEURL + "/api/homeappliances/" + self.haId + "/settings/BSH.Common.Setting.PowerState"
    header = {"Content-Type": "application/vnd.bsh.sdk.v1+json", "Authorization": "Bearer " + self.access_token}
    data = None 
    if state == "On":
        l1 = [self.DEVICE_DISHWASHER, self.DEVICE_HOOD]
        if devicetype in l1:
            data = json.dumps({
              'data': {
                'key': 'BSH.Common.Setting.PowerState',
                'value': 'BSH.Common.EnumType.PowerState.On',
                'type': 'BSH.Common.EnumType.PowerState',
                'constraints': {
                  'allowedvalues': ['BSH.Common.EnumType.Powerstate.On', 'BSH.Common.EnumType.PowerState.Off']
                }
              }
            })
        elif devicetype == self.DEVICE_OVEN:
            data = json.dumps({
              'data': {
                'key': 'BSH.Common.Setting.PowerState',
                'value': 'BSH.Common.EnumType.PowerState.On',
                'type': 'BSH.Common.EnumType.PowerState',
                'constraints': {
                  'allowedvalues': ['BSH.Common.EnumType.Powerstate.On', 'BSH.Common.EnumType.PowerState.Standby']
                }
              }
            })
    elif state == "Off":
        data = json.dumps({
          'data': {
            'key': 'BSH.Common.Setting.PowerState',
            'value': 'BSH.Common.EnumType.PowerState.Off',
            'type': 'BSH.Common.EnumType.PowerState',
            'constraints': {
              'allowedvalues': ['BSH.Common.EnumType.Powerstate.On', 'BSH.Common.EnumType.PowerState.Off']
            }
          }
        })
    elif state == "Standby":
        data = json.dumps({
          'data': {
            'key': 'BSH.Common.Setting.PowerState',
            'value': 'BSH.Common.EnumType.PowerState.Standby',
            'type': 'BSH.Common.EnumType.PowerState',
            'constraints': {
              'allowedvalues': ['BSH.Common.EnumType.Powerstate.On', 'BSH.Common.EnumType.PowerState.Standby']
            }
          }
        })
 
    response = requests.put(url_setPowerState, headers=header, data=data)
    Domoticz.Debug(str(response.status_code))
    if str(response.status_code) == "204":
        response.close()
        return True
    response.close()
    return False

def getOperationState(self,haId):
    Domoticz.Debug("getOperationState")
    url_getOperationState = BASEURL + "/api/homeappliances/" + (haId or "") + "/status/BSH.Common.Status.OperationState"
    header = {"Accept": "application/vnd.bsh.sdk.v1+json", "Authorization": "Bearer " + self.access_token}
    response_getOperationState = requests.get(url_getOperationState, headers=header)
    json_items = json.loads(str(response_getOperationState.text))
    response_getOperationState.close()
    Domoticz.Debug(response_getOperationState.text)
    for key_item, value_item in json_items.items():
        Domoticz.Debug(str(key_item)+" --> "+str(value_item))
        for data in value_item:
            if data == "value":
                Domoticz.Debug(data+" --> "+str(value_item[data]))
                return str(value_item[data])

"""
Method for device authorization and getting a token

Parameters
----------
self : BasePlugin
    for getting plugin variables
username : String
    Home-Connect username
password : String
    Home-Connect password
ascope : String
    Scope for which authorization is requested

Return
------
None
"""
def connectHomeConnect(self,username,password,ascope):
    #'Request authorization to access home appliance" and "Return device code, user code, verification uri, ..."
    url_authorization = BASEURL + "/security/oauth/device_authorization"
    scope = "IdentifyAppliance "+ascope+"-Monitor "+ascope+"-Settings"
    data_authorization = {"client_id": self.clientid, "scope": scope}
    response_authorization = requests.post(url_authorization,data_authorization,HEADER_URLENCODED)
    Domoticz.Debug(response_authorization.text)
    json_data_authorization = json.loads(response_authorization.text)
    response_authorization.close()
    device_code = ""
    verification_uri_complete = ""
    user_code = ""
    for key, value in json_data_authorization.items():
        Domoticz.Debug(key + " --> " + str(value))
        if key == "device_code":
            device_code = value
        if key == "verification_uri_complete":
            verification_uri_complete = value
        if key == "user_code":
            user_code = value
    Domoticz.Log("device_code: "+device_code)
    Domoticz.Log("verification_uri_complete: "+verification_uri_complete)
    Domoticz.Debug("user_code: "+user_code)

    #Enter user code, log in and authorize access
    authorized = False
    
    if(device_code != "") and (verification_uri_complete != "") and (user_code != ""):
        session = requests.Session()

        #log in part
        payload_login = {"client_id": self.clientid, "user_code": user_code, "email": username, "password": password}
        url_login = BASEURL + "/security/oauth/device_login"
        response_login = session.post(url_login, data=payload_login)
        Domoticz.Debug(response_login.text)
        sessionid = response_login.text[response_login.text.find("session_id\" value=\"")+len("session_id\" value=\""):]
        sessionid = sessionid[:sessionid.find("\"")]
        Domoticz.Log("sessionid: "+sessionid)
        response_login.close()
    
        #authorize part
        #payload_grant = {"session_id": sessionid, "client_id": self.clientid, "user_code": user_code, "email": username, "app_name": APP_NAME, "scope": scope}
        payload_grant = {"user_code": user_code, "session_id": sessionid, "input_aborted": "false", "app_name": APP_NAME, "accept_language": "nl", "client_id": self.clientid, "email": username, "scope": scope, "region": "EU", "environment": "PRD"}
        url_grant = BASEURL + "/security/oauth/device_grant"
        response_grant = session.post(url_grant, data=payload_grant)
        Domoticz.Debug("response_grant: "+response_grant.text)
        authorized = True
        response_grant.close()
    
    #Token request
    if authorized:
        Domoticz.Log("Device \"" + device_code + "\" is authorized by Home-Connect.")
        url_tokenrequest = BASEURL + "/security/oauth/token"
        payload_tokenrequest = {"grant_type": "device_code", "device_code": device_code, "client_id": self.clientid}
        response_tokenrequest = requests.post(url_tokenrequest,payload_tokenrequest, HEADER_URLENCODED)
        Domoticz.Debug("response_tokenrequest: "+response_tokenrequest.text)
        json_tokenrequest = json.loads(response_tokenrequest.text)
        response_tokenrequest.close()
        for key, value in json_tokenrequest.items():
            Domoticz.Debug(key + " --> " + str(value))
            if key == "access_token":
                self.access_token = value
            if key == "expires_in":
                self.token_expired = datetime.datetime.now() + datetime.timedelta(seconds=value) #default 86400 seconds (=24h)
            if key == "refresh_token":
                self.refresh_token = value
        Domoticz.Log("Device \"" + device_code + "\" has token: " + self.access_token)
    else:
        Domoticz.Error("Device \"" + device_code + "\" is not authorized by Home_Connect.")

    return
file "homeconnectSSE_dishwasher.sh" code:

Code: Select all

#!/bin/sh

### BEGIN INIT INFO
# Provides:          myservice
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Put a short description of the service here
### END INIT INFO

# Change the next 3 lines to suit where you install your script and what you want to call it
PYTHON_PATH=/usr/bin/python3
DIR=/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin
DAEMON=/home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin/homeconnectSSE.py
DEVICE_NAME=Dishwasher
DOMOTICZ_IP=IP address of Domoticz
DOMOTICZ_PORT=Same IP address as configured in Domoticz but NOT the port of Domoticz itself!!
DAEMON_NAME=homeconnectSSE_$DEVICE_NAME
DAEMON_LOG=/home/pi/domoticz/log/$DAEMON_NAME.log
# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=pi

# Add any command line options for your daemon here
DAEMON_OPTS="$DAEMON $DEVICE_NAME $DOMOTICZ_IP $DOMOTICZ_PORT $DAEMON_LOG"

# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/$DAEMON_NAME.pid

. /lib/lsb/init-functions

do_start () {
    log_daemon_msg "Starting system $DAEMON_NAME daemon"
    start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --exec $PYTHON_PATH -- $DAEMON_OPTS
    log_end_msg $?
}

do_stop () {
    log_daemon_msg "Stopping system $DAEMON_NAME daemon"
    start-stop-daemon --stop --pidfile $PIDFILE --retry 10
    log_end_msg $?
}

case "$1" in
    start|stop)
        do_"$1"
        ;;
    restart|reload|force-reload)
        do_stop
        do_start
        ;;
    status)
        status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
        ;;
    *)
        echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
        exit 1
        ;;
esac

exit 0

After this:
On Raspberry PI:
Go to folder /home/pi/domoticz/plugins/Domoticz-Home-Connect-Plugin
then:
sudo cp homeconnectSSE_DEVICENAME!!.sh /etc/init.d
then
sudo update-rc.d homeconnectSSE_DEVICENAME!!.sh defaults
then
sudo service homeconnectSSE_DEVICENAME!!.sh start
then
sudo service domoticz.sh restart
then
sudo service homeconnectSSE_dishwasher.sh restart

I have tested the dishwasher and it works, devices are being created now, I have no more error on start up, or error of api token.
But now I get this message:
2023-06-20 16:10:59.472 Siemens Home Connect: haId:
2023-06-20 16:10:59.660 Siemens Home Connect: Home Appliance ID is not available.

It seems I don't get the haID (HomeAppliance ID).
Probably because of SingleKeyId...

Anybody a sollution for this?
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest