Home Connect binding

Somehow I have a stupid question on this… Because it somehow worked, but it definitely isn’t right how I did it :slight_smile:

I try to work with openhab3 GUI as much as I can… Always before I try to do complicated things with items, things and rules files.

I did setup the binding and connected it with the developers account and my home connect account… Authorizes everything and autodetected my Dishwasherthing.

this is the JSON I would have to send to the dishwasher in order to start the dishwasher with the settings I want (already formatted as “oneliner”):

{"data": {"key": "Dishcare.Dishwasher.Program.Auto2","options": [{"key": "Dishcare.Dishwasher.Option.IntensivZone","value": false},{"key": "Dishcare.Dishwasher.Option.VarioSpeedPlus","value": true},{"key": "Dishcare.Dishwasher.Option.BrillianceDry","value": true},{"key": "BSH.Common.Option.StartInRelative","value": 0,"unit": "seconds"}]}}

on the basic_action_state channel. Obviously in a rule I would have to send that to the item connected with the basic_action_state channel :

Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_ProgrammAktionen.sendCommand('{"data": {"key": "Dishcare.Dishwasher.Program.Auto2","options": [{"key": "Dishcare.Dishwasher.Option.IntensivZone","value": false},{"key": "Dishcare.Dishwasher.Option.VarioSpeedPlus","value": true},{"key": "Dishcare.Dishwasher.Option.BrillianceDry","value": true},{"key": "BSH.Common.Option.StartInRelative","value": 0,"unit": "seconds"}]}}')

And yes, I could create a rule (and most probably I will, where I have some items representing the different options and a item representing Start and a rule, once start is triggered, that will build the proper JSON and send it like above). But that’s not what I am looking for at the moment.

So what we have from gui config:

The api_bridge thing, working fine:

UID: homeconnect:api_bridge:e2602e0bee
label: Home Connect API
thingTypeUID: homeconnect:api_bridge
configuration:
  clientSecret: <wildNumber>
  clientId: <anotherWildNumber>
  simulator: false

The dishwasher thing, also working fine:

UID: homeconnect:Dishwasher:e2602e0bee:SIEMENS-SN558S06TE-XXXXXXXXXXXX
label: Siemens Geschirrspüler (SIEMENS-SN558S06TE-XXXXXXXXXXXX)
thingTypeUID: homeconnect:dishwasher
configuration:
  haId: SIEMENS-SN558S06TE-XXXXXXXXXXXX
bridgeUID: homeconnect:api_bridge:e2602e0bee

This thing has channels, I connect all the channels to individual items, except the channels regarding ambient light, as in my opinion it doesn’t have that and no need to control it :slight_smile:
those Items i grouped in the Model in an item of type Group Equipment>Dishwasher

so this is from jsonDB two of the most interesting channels I have (the others work very fine):

  "Siemens_Geschirrspuler_SIEMENSSN558S06TEXXXXXXXXXXXXX_Betrieb -\u003e homeconnect:Dishwasher:e2602e0bee:SIEMENS-SN558S06TE-XXXXXXXXXXXXX:power_state": {
    "class": "org.openhab.core.thing.link.ItemChannelLink",
    "value": {
      "channelUID": {
        "segments": [
          "homeconnect",
          "Dishwasher",
          "e2602e0bee",
          "SIEMENS-SN558S06TE-XXXXXXXXXXXXX",
          "power_state"
        ],
        "uid": "homeconnect:Dishwasher:e2602e0bee:SIEMENS-SN558S06TE-XXXXXXXXXXXXX:power_state"
      },
      "configuration": {
        "properties": {}
      },
      "itemName": "Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_Betrieb"
    }
  },
  "Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_ProgrammAktionen -\u003e homeconnect:Dishwasher:e2602e0bee:SIEMENS-SN558S06TE-68A40E141554:basic_actions_state": {
    "class": "org.openhab.core.thing.link.ItemChannelLink",
    "value": {
      "channelUID": {
        "segments": [
          "homeconnect",
          "Dishwasher",
          "e2602e0bee",
          "SIEMENS-SN558S06TE-68A40E141554",
          "basic_actions_state"
        ],
        "uid": "homeconnect:Dishwasher:e2602e0bee:SIEMENS-SN558S06TE-68A40E141554:basic_actions_state"
      },
      "configuration": {
        "properties": {}
      },
      "itemName": "Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_ProgrammAktionen"
    }
  },

the first one represents the power state and i can just switch it as i want… Works well
the second would start a programm and needs the command to be sent to

here are the two items fom jsonDB those channels of the thing are linked to:

  "Siemens_Geschirrspuler_SIEMENSSN558S06TEXXXXXXXXXXXXX_Betrieb": {
    "class": "org.openhab.core.items.ManagedItemProvider$PersistedItem",
    "value": {
      "groupNames": [
        "Siemens_Geschirrspuler_SIEMENSSN558S06TEXXXXXXXXXXXXX"
      ],
      "itemType": "Switch",
      "tags": [
        "Power",
        "Switch"
      ],
      "label": "Betrieb",
      "category": "Switch"
    }
  },
  "Siemens_Geschirrspuler_SIEMENSSN558S06TEXXXXXXXXXXXX_ProgrammAktionen": {
    "class": "org.openhab.core.items.ManagedItemProvider$PersistedItem",
    "value": {
      "groupNames": [
        "Siemens_Geschirrspuler_SIEMENSSN558S06TEXXXXXXXXXXXX"
      ],
      "itemType": "String",
      "tags": [
        "Point"
      ],
      "label": "Programm-Aktionen",
      "category": ""
    }
  },

and now comes the bit strange thing… I defined meta data for the Item “ProgrammAktionen” linked with basic_action_state:

  "widget:Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_ProgrammAktionen": {
    "class": "org.openhab.core.items.Metadata",
    "value": {
      "key": {
        "segments": [
          "widget",
          "Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_ProgrammAktionen"
        ],
        "uid": "widget:Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_ProgrammAktionen"
      },
      "value": " ",
      "configuration": {
        "action": "command",
        "actionCommand": "{\"data\": {\"key\": \"Dishcare.Dishwasher.Program.Auto2\",\"options\": [{\"key\": \"Dishcare.Dishwasher.Option.IntensivZone\",\"value\": false},{\"key\": \"Dishcare.Dishwasher.Option.VarioSpeedPlus\",\"value\": true},{\"key\": \"Dishcare.Dishwasher.Option.BrillianceDry\",\"value\": true},{\"key\": \"BSH.Common.Option.StartInRelative\",\"value\": 0,\"unit\": \"seconds\"}]}}",
        "actionOptions": "\u0027{\"data\":{\"key\":\"Dishcare.Dishwasher.Program.Auto2\",\"options\":[{\"key\": \"Dishcare.Dishwasher.Option.IntensivZone\",\"value\":false},{\"key\":\"Dishcare.Dishwasher.Option.VarioSpeedPlus\",\"value\":true},{\"key\":\"Dishcare.Dishwasher.Option.BrillianceDry\",\"value\": true},{\"key\":\"BSH.Common.Option.StartInRelative\",\"value\":0,\"unit\": \"seconds\"}]}}\u0027"
      }
    }
  },

So in GUI I tried to defined via metadata the Default Standalone widged, where I only did decide for a Default oh-label-card and in Action section I did choose for “Send Command” and entered the JSON I want to command in the Action Command field. Sadly for some reason it seems, that this gets somehow interpreted as Coma separated, at least if i choose command options as a setting, which I would prefer, to have choice between different programms… But not at that time being… So yes, you see the outcome n JSON DB above and here what’s in the YAML

value: ""
config:
  action: command
  actionCommand: '{"data": {"key": "Dishcare.Dishwasher.Program.Auto2","options":
    [{"key": "Dishcare.Dishwasher.Option.IntensivZone","value": false},{"key":
    "Dishcare.Dishwasher.Option.VarioSpeedPlus","value": true},{"key":
    "Dishcare.Dishwasher.Option.BrillianceDry","value": true},{"key":
    "BSH.Common.Option.StartInRelative","value": 0,"unit": "seconds"}]}}'
  actionOptions: "'{\"data\":{\"key\":\"Dishcare.Dishwasher.Program.Auto2\",\"opt\
    ions\":[{\"key\":
    \"Dishcare.Dishwasher.Option.IntensivZone\",\"value\":false},{\"key\":\"Dis\
    hcare.Dishwasher.Option.VarioSpeedPlus\",\"value\":true},{\"key\":\"Dishcar\
    e.Dishwasher.Option.BrillianceDry\",\"value\":
    true},{\"key\":\"BSH.Common.Option.StartInRelative\",\"value\":0,\"unit\":
    \"seconds\"}]}}'"

I have no idea, why it also did set actionOptions, nor why there are is ’ in the command to be added (this may make sense) and "’ added in actionOptions… But it leads to the jsonDB entrie above.

And now it gets a bit strange… :slight_smile:

In the pages I did click the pkus of a cell and said add from model, and added it… gave it a name and this was created (and yes i stopped blinding the serialnumber :slight_smile: :

component: oh-label-card
config:
  action: command
  actionItem: Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_ProgrammAktionen
  actionCommand: '{"data": {"key": "Dishcare.Dishwasher.Program.Auto2","options":
    [{"key": "Dishcare.Dishwasher.Option.IntensivZone","value": false},{"key":
    "Dishcare.Dishwasher.Option.VarioSpeedPlus","value": true},{"key":
    "Dishcare.Dishwasher.Option.BrillianceDry","value": true},{"key":
    "BSH.Common.Option.StartInRelative","value": 0,"unit": "seconds"}]}}'
  actionOptions: "'{\"data\":{\"key\":\"Dishcare.Dishwasher.Program.Auto2\",\"opt\
    ions\":[{\"key\":
    \"Dishcare.Dishwasher.Option.IntensivZone\",\"value\":false},{\"key\":\"Dis\
    hcare.Dishwasher.Option.VarioSpeedPlus\",\"value\":true},{\"key\":\"Dishcar\
    e.Dishwasher.Option.BrillianceDry\",\"value\":
    true},{\"key\":\"BSH.Common.Option.StartInRelative\",\"value\":0,\"unit\":
    \"seconds\"}]}}'"
  item: Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_ProgrammAktionen
  title: Programm-Aktionen

(i don’t know why, in first try it reacted a bit strange) and for some wired reason, this does exactly what i want, sending the start command for the programm with the whished options, when I click the label… but i dont understand why, as it got interpreteted as options when I did it first time… And it when first time successfully started the dishwasher, it definitely did not send the complete thing.

but now it sends and the api reacts as follows, as the dishwasher is running already, but I dont understand why it works :slight_smile:

the entry in API requests:

PUT https://api.home-connect.com/api/homeappliances/SIEMENS-SN558S06TE-68A40E141554/programs/active
×
Request Body
{
  "data": {
    "key": "Dishcare.Dishwasher.Program.Auto2",
    "options": [
      {
        "key": "Dishcare.Dishwasher.Option.IntensivZone",
        "value": false
      },
      {
        "key": "Dishcare.Dishwasher.Option.VarioSpeedPlus",
        "value": true
      },
      {
        "key": "Dishcare.Dishwasher.Option.BrillianceDry",
        "value": true
      },
      {
        "key": "BSH.Common.Option.StartInRelative",
        "value": 0,
        "unit": "seconds"
      }
    ]
  }
}
Response Body
{
  "error": {
    "description": "Request cannot be performed since OperationState is not Ready",
    "key": "SDK.Error.WrongOperationState"
  }
}

(response is obvious, as it is already running…)

And I don’t find the succesfull start in the API Log… So here is the confusing point…

Can someone help me with idea, how to do it the very right way with the GUI? (the way by .things, .items and maybe .rules files is obvious and taking a ready something from internet also maybe easy) and is not what I am looking for

Ok, I figured out, for the thing I really want to do is, you can shorten the command to the basic_action_state channel in order to start exactly the program that was set on the dishwasher… (which is the way I intend to use it)…

I put in dishes, I select the program that shall start once there is the right moment to start, i push the RemoteControlStartAllowed and then if the right moment has come (in my case, if there is enough solar energy aviable) openhab sends the start command to the basic_action_state.

which is in principle following JSON:

{
 "data": 
  {
   "key": "Dishcare.Dishwasher.Program.Auto2",
   "options": [
    {
     "key": "BSH.Common.Option.StartInRelative",
     "value": 0,
     "unit": "seconds"
     }
    ]
  }
}

but the name of the program has to be replaced, by the Name of program that is choosen and found in selected_program_state

so the rule has to execute following:

var slectedProgramm, commandJSON, retValue;

// building JSON to start a home connect Dishwasher with a variable program name
function buildStartCommandString(slectedProgramm) {
  retValue = ['{"data": {"key": "',slectedProgramm,'", "options": [{"key": "BSH.Common.Option.StartInRelative", "value": 0, "unit": "seconds"}]}}'].join('');
  return retValue;
}

var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);


commandJSON = buildStartCommandString(itemRegistry.getItem('Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_Ausgewahltes_Programm').getState());
logger.info(('command to send: ' + String(commandJSON)));
events.sendCommand('Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_ProgrammAktionen', commandJSON);

and the complete rule, including the checks suggested by API documentation the looks like:

configuration: {}
triggers:
  - id: "8"
    configuration:
      cronExpression: 0/15 * * * * ? *
    type: timer.GenericCronTrigger
conditions:
  - inputs: {}
    id: "2"
    configuration:
      itemName: testItem
      state: -2000 W
      operator: <=
    type: core.ItemStateCondition
  - inputs: {}
    id: "4"
    configuration:
      itemName: Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_Aktivierungsstatus_fur_Fernsteuerung
      state: ON
      operator: =
    type: core.ItemStateCondition
  - inputs: {}
    id: "5"
    configuration:
      itemName: Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_FernstartStatus_erlaubt
      state: ON
      operator: =
    type: core.ItemStateCondition
  - inputs: {}
    id: "6"
    configuration:
      itemName: Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_Betriebsmodus
      state: Ready
      operator: =
    type: core.ItemStateCondition
  - inputs: {}
    id: "7"
    configuration:
      itemName: Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_TurStatus
      state: CLOSED
      operator: =
    type: core.ItemStateCondition
actions:
  - inputs: {}
    id: "3"
    label: Spuelmaschine Starten
    configuration:
      type: application/javascript
      script: >
        var slectedProgramm, commandJSON, retValue;


        // building JSON to start a home connect Dishwasher with a variable program name

        function buildStartCommandString(slectedProgramm) {
          retValue = ['{"data": {"key": "',slectedProgramm,'", "options": [{"key": "BSH.Common.Option.StartInRelative", "value": 0, "unit": "seconds"}]}}'].join('');
          return retValue;
        }


        var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);



        commandJSON = buildStartCommandString(itemRegistry.getItem('Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_Ausgewahltes_Programm').getState());

        logger.info(('command to send: ' + String(commandJSON)));

        events.sendCommand('Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_ProgrammAktionen', commandJSON);
    type: script.ScriptAction

If someone has a good idea, what else to be used as a trigger instead of the 15 seconds cronjob… a change of testItem triggers too often once the state is <= -2000 W.

No need to check for PowerState, as it checks for OperationState, which would be inactive, if PowerState is not ON.

Hope I am using the API right now :slight_smile:

And then two small rules to take control of the power state:

turning it on, if remoteStart would be possible and there is a minimum power amount aviable, which is a bit smaller than the power amount to start the dishwasher:

configuration: {}
triggers:
  - id: "1"
    configuration:
      cronExpression: 0/15 * * * * ? *
    type: timer.GenericCronTrigger
conditions:
  - inputs: {}
    id: "2"
    configuration:
      itemName: Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_Betrieb
      state: OFF
      operator: =
    type: core.ItemStateCondition
  - inputs: {}
    id: "3"
    configuration:
      itemName: Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_FernstartStatus_erlaubt
      state: ON
      operator: =
    type: core.ItemStateCondition
  - inputs: {}
    id: "4"
    configuration:
      itemName: KSEM_Wirkleistungsbezug_Value_as_Number
      state: "-500"
      operator: <
    type: core.ItemStateCondition
actions:
  - inputs: {}
    id: "5"
    configuration:
      itemName: Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_Betrieb
      command: ON
    type: core.ItemCommandAction

and turning the machine off, whenever there are certain conditions met:

  • power state is “ON”
  • power state didn’t change within the last 2 minutes
    and (
  • no aviable solar power
    or
  • a remote start would not be possible and it’s Operation state is ready
    or
  • the program has finished and that’s more than two minutes ago
    )
configuration: {}
triggers:
  - id: "1"
    configuration:
      cronExpression: 0/15 * * * * ? *
    type: timer.GenericCronTrigger
conditions:
  - inputs: {}
    id: "2"
    configuration:
      itemName: Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_Betrieb
      state: ON
      operator: =
    type: core.ItemStateCondition
actions:
  - inputs: {}
    id: "4"
    configuration:
      type: application/javascript
      script: >
        var wirkleistungsbezug;


        var dtf = Java.type("java.time.format.DateTimeFormatter");


        var zdt = Java.type("java.time.ZonedDateTime");


        function getZonedDateTime(datetime) {
          datetime = String(datetime).replace('T', ' ')
          var regex_time_min =         /^\d{2}:\d{2}$/;
          var regex_time_sec =         /^\d{2}:\d{2}:\d{2}$/;
          var regex_date =             /^\d{4}-\d{2}-\d{2}$/;
          var regex_date_time_min =    /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/;
          var regex_date_time_sec =    /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
          var regex_date_time_sec_tz = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}$/;
          var regex_date_time_ms =     /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.\d{3}$/;
          var regex_date_time_us =     /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.\d{6}$/;
          var regex_date_time_ms_tz =  /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.\d{3}[+-]\d{2}:\d{2}$/;
          var regex_date_time_us_tz =  /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.\d{6}[+-]\d{2}:\d{2}$/;
          var regex_oh =               /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.\d{3}[+-]\d{4}$/;
          var now = zdt.now();
          var now_year = now.getYear();
          var now_month = now.getMonthValue();
          var now_day = now.getDayOfMonth();
          var today = '' + now_year;
          today += '-' + ('0' + now_month).slice(-2);
          today += '-' + ('0' + now_day).slice(-2)+' ';
          switch (true) {
            case regex_time_min.test(datetime): return zdt.parse(today + datetime + ':00+00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ssz'));
            case regex_time_sec.test(datetime): return zdt.parse(today + datetime + '+00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ssz'));
            case regex_date.test(datetime): return zdt.parse(datetime + ' 00:00:00+00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ssz'));
            case regex_date_time_min.test(datetime): return zdt.parse(datetime + ':00+00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ssz'));
            case regex_date_time_sec.test(datetime): return zdt.parse(datetime + '+00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ssz'));
            case regex_date_time_sec_tz.test(datetime): return zdt.parse(datetime, dtf.ofPattern('yyyy-MM-dd HH:mm:ssz'));
            case regex_date_time_ms.test(datetime): return zdt.parse(datetime + ' +00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ss.SSS z'));
            case regex_date_time_us.test(datetime): return zdt.parse(datetime + ' +00:00', dtf.ofPattern('yyyy-MM-dd HH:mm:ss.SSSSSS z'));
            case regex_date_time_ms_tz.test(datetime): return zdt.parse(datetime, dtf.ofPattern('yyyy-MM-dd HH:mm:ss.SSSSz'));
            case regex_date_time_us_tz.test(datetime): return zdt.parse(datetime, dtf.ofPattern('yyyy-MM-dd HH:mm:ss.SSSSSSSz'));
            case regex_oh.test(datetime): return zdt.parse(datetime.slice(0,26) + ':' + datetime.slice(26,28), dtf.ofPattern('yyyy-MM-dd HH:mm:ss.SSSSz'));
            default: return zdt.parse(datetime);
          }
        }


        function createZonedDateTime(year, month, day, hour, minute, second, nano, offsetString, timezoneString) {
          stringToParse = '' + year;
          stringToParse += '-' + ('0' + month).slice(-2);
          stringToParse += '-' + ('0' + day).slice(-2);
          stringToParse += 'T' + ('0' + hour).slice(-2);
          stringToParse += ':' + ('0' + minute).slice(-2);
          stringToParse += ':' + ('0' + second).slice(-2);
          stringToParse += '.' + nano + offsetString + '[' + timezoneString + ']';
          return zdt.parse(stringToParse, dtf.ISO_ZONED_DATE_TIME);
        }


        var persistence = Java.type('org.openhab.core.persistence.extensions.PersistenceExtensions');


        var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);



        if (!(persistence.changedSince(itemRegistry.getItem('Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_Betrieb'), zdt.now().minusMinutes(2)))) {
          wirkleistungsbezug = itemRegistry.getItem('testItem').getState();
          if (wirkleistungsbezug > 0 || itemRegistry.getItem('Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_FernstartStatus_erlaubt').getState() != 'ON' && itemRegistry.getItem('Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_Betriebsmodus').getState() == 'Ready' || itemRegistry.getItem('Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_Betriebsmodus').getState() == 'Finished' && !(persistence.changedSince(itemRegistry.getItem('Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_Betriebsmodus'), zdt.now().minusMinutes(2)))) {
            events.sendCommand('Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_Betrieb', 'OFF');
          }
        } else {
          logger.info(([itemRegistry.getItem('Siemens_Geschirrspuler_SIEMENSSN558S06TE68A40E141554_Betrieb').getName(),'has changed since: ',zdt.now().minusMinutes(2)].join('')));
        }
    type: script.ScriptAction

So if someone is interested or interested in recheck this…
This rule intends to do following:

1.) if someone turned on the machine for whatever reason it shall never turn off within the next 2 minutes, giving enough time to do some settings on it
2.) if switch off is legal it shall switch off:
a.) whenever there is no solar power aviable… which means also during a running program!!
(Programs continue when PowerState is turning back to ON)
b.) whenever the machine is OperationState is ready and remoteStart is not allowed.
c.) whenever the machine has finished and this is two minutes ago

I think there is only one flaw in it now:
If a manually started Programm was “paused” due to no solar power, it will not continue automatically, when power is there again, as I think I can’t see that… Think could store it somewhere in an item that it did break a running manual programm and could add that to the auto turn on as a option

HI @Markus_Oliver_Thur

thanks for sharing your solution. I bet it will help others.

I run my OH setup completely text-based (configuration files), so unfortunately I can’t give you any tips.

Unfortunately I have no solution for the problem. From time to time the access data are no longer valid. It’s been happening to me very rarely lately.

I suspect as soon as the official Home Connect backend imports updates or carries out other maintenance work, it forgets the access data or sends incorrect response codes.

Thanks!
It‘s currently working again.

So I hope this occures only rearly, as you mentioned.

Yes it does, same **** with the official app… Sometimes it recovers sometimes it doesn’t… Seems most ppl don’t even recognize it :slight_smile: Or just reregister once the app wants them to :slight_smile: There are reasons I hate apps… Wheneever I read: “oh we have an app, but only for Android and iPhone, but not for PC2” I know I don’t like it :slight_smile:

Thaks, but I strongly suggest not to copy it plain…

There are still flaws in it, that I am working on…
One is, that when it breaks a manually started program, it doesn’t continue it. But I think it’s solved already, as I now just don’t stop manually started programms. (assuming user wanted to dishwash, at any cost, if he started manually and did not press remote start)
Anotherone is, that thanks to the low update rate it may happen, that it turns off to lack off solar energy after the program finished, but before openHAB did see that the porgramm was finished… This for some reason leads to a complete restart of the programm, instead of remote start allowed flag falls to off… I have to investigate what happened there a bit more and have to improve the timings. Maybe I should prevent turning of the machine if the running programm has a remaining runtime less than 300 seconds :slight_smile:

I got a new washer and installed the binding yesterday.

After the first try I stumbeled upon this:

2023-04-29 18:56:58.139 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Waschmaschine_K_LaundryCareWasherSpinSpeed' changed from NULL to LaundryCare.Washer.EnumType.SpinSpeed.RPM1200

Why is this a string?
And such a long string?

I would have expected a Number item with the value 1200.

Looks like this is on purpurse, because the documentation says this item is a string.
But I cannot understand why.

Can I create a feature request to get this changed in the binding?

Or do I have to create a proxy item that gets updated with the correct value?

The same goes for LaundryCareWasherTemp' changed from NULL to LaundryCare.Washer.EnumType.Temperature.GC40.
Why is this not Number:Temperature?

But thanks for the binding, anyway. :+1:

Even stranger:
I just realized the SpinSpeed is correctly shown in the sitemap. :hushed:
image

image

2023-05-02 21:43:50.771 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Waschmaschine_K_LaundryCareWasherSpinSpeed' changed from LaundryCare.Washer.EnumType.SpinSpeed.RPM1400 to LaundryCare.Washer.EnumType.SpinSpeed.RPM1200`

Where is this conversion happening?
I mean it is just a string item.
And why is it not working for the WasherTemp?

Hi Christoph,

Unfortunately, the value is not always numeric. For example, the following values are used in the USA:

  • No spinning Key: LaundryCare.Washer.EnumType.SpinSpeed.UlOff
  • Low Key: LaundryCare.Washer.EnumType.SpinSpeed.UlLow
  • Medium Key: LaundryCare.Washer.EnumType.SpinSpeed.UlMedium
  • High Key: LaundryCare.Washer.EnumType.SpinSpeed.UlHigh

The binding uses the same values as the Home Connect API.

The state descriptor is created dynamically in code. Sometimes it doesn’t work in the UI and you have to reload the page (e.g. in the sitemap).

    public static final String TEMPERATURE_PREFIX = "LaundryCare.Washer.EnumType.Temperature.";
    public static final String SPIN_SPEED_PREFIX = "LaundryCare.Washer.EnumType.SpinSpeed.";

    protected String convertWasherTemperature(String value) {
        if (value.startsWith(TEMPERATURE_PREFIX + "GC")) {
            return value.replace(TEMPERATURE_PREFIX + "GC", "") + "°C";
        }

        if (value.startsWith(TEMPERATURE_PREFIX + "Ul")) {
            return mapStringType(value.replace(TEMPERATURE_PREFIX + "Ul", ""));
        }

        return mapStringType(value);
    }

    protected String convertWasherSpinSpeed(String value) {
        if (value.startsWith(SPIN_SPEED_PREFIX + "RPM")) {
            return value.replace(SPIN_SPEED_PREFIX + "RPM", "") + " RPM";
        }

        if (value.startsWith(SPIN_SPEED_PREFIX + "Ul")) {
            return value.replace(SPIN_SPEED_PREFIX + "Ul", "");
        }

        return mapStringType(value);
    }
    /**
     * Map Home Connect key and value names to label.
     * e.g. Dishcare.Dishwasher.Program.Eco50 --> Eco50 or BSH.Common.EnumType.OperationState.DelayedStart --> Delayed
     * Start
     *
     * @param type type
     * @return human readable label
     */
    protected String mapStringType(String type) {
        int index = type.lastIndexOf(".");
        if (index > 0 && type.length() > index) {
            String sub = type.substring(index + 1);
            StringBuilder sb = new StringBuilder();
            for (String word : sub.split("(?<!(^|[A-Z]))(?=[A-Z])|(?<!^)(?=[A-Z][a-z])")) {
                sb.append(" ");
                sb.append(word);
            }
            return sb.toString().trim();
        }
        return type;
    }

Thanks for the clarification.

I will takle a closer look at it, when I am using the washer the next time. :slight_smile:

Hey,

i am using this binding for quite a while. As i couldn’t find a channel to set the alarm-clock of my oven i tried to do it with a custom command. I succeeded sending a raw PUT command to the path /api/homeappliances/<device_id>/settings/BSH.Common.Setting.AlarmClock with the following request body:

{
	"data": {
		"key": "BSH.Common.Setting.AlarmClock",
		"unit": "seconds",
		"type": "Int",
		"value": 10
	}
}

Is it possible to send this command via a channel? The channel basic_actions_state seems to be hard coded to the path /api/homeappliances/<device_id>/programs/active

Thanks alot,
Andre

Hi André,

I’ve checked it. You’re right it is hard coded to /api/homeappliances/{haID}/programs/active. I think we have to update the binding. Unfortunately, I do not have enough spare time at the moment.

In the fridge handler there is a similar case where a setting is changed.

if (CHANNEL_REFRIGERATOR_SETPOINT_TEMPERATURE.equals(channelUID.getId())
                    || CHANNEL_FREEZER_SETPOINT_TEMPERATURE.equals(channelUID.getId())) {
                handleTemperatureCommand(channelUID, command, apiClient);
            }
...
putSettings(haId, new Data(SETTING_REFRIGERATOR_SETPOINT_TEMPERATURE, state, unit), VALUE_TYPE_INT);

Hello,

→ OH Version 3.4.2 with Home Connect Binding

Since a few days I have no connection to th eAPI.
I can authorize the bridge, but the status stays on “UNKNOWN”:

WHat I have done so far:

  • New installation of OH Binding
  • Check logins from HomeConnect

Any hints to solve the problem?

thanks

KR
Michael

I solved the problem with restarting openhab instance…so now everthing works fine

Hi, I’m having a similiar issue where I would need to use a different path, therefore the basic actions item is not useable. But even if there is no update for now, I could write a small curl command that does the trick. The only question I still haven’t solved is what is the best way to get the Bearer Token from the binding? Any hints?

Maybe use a command line tool to use a json path query on userdata/jsondb/StorageHandler.For.OAuthClientService.json.

Yes, I’m playing around with that but the token does not seem to be stored there in plain text. At least when I use the auth token from the file I’m getting a malformed token error back. Any more hints would be of great help! Thanks

This worked for me:

cat StorageHandler.For.OAuthClientService.json | jq -r '."homeconnect:api_bridge:api_bridge.AccessTokenResponse".value' | jq -r '.accessToken'

Response:
9RrcZ8fXaTi350BofT0RbKaB...

Thanks but getting the Token was not the main issue - when I try to use that token with this curl command which works fine with the API web client token I’m getting a malformed token error:

curl -X ‘GET’
https://api.home-connect.com/api/homeappliances
-H ‘accept: application/vnd.bsh.sdk.v1+json’
-H ‘authorization: Bearer ’

Response:
{
“error”: {
“key”: “invalid_token”,
“description”: “The provided token is malformed.”
}
}

That was the reason why I was asking if the token in this file needs to be decrypted or decoded in any way?