How to get the state (formatted string), change it and publish to MQTT if item Switch (OnOff)?

  • Platform information:
    • Hardware: Intel
    • OS: Windows Server 2022
    • Java Runtime Environment: zulu17.46.19-ca-jdk17.0.9-win_x64
    • openHAB version: 4.0.3

Hi, guru! I really need your help!

I’m trying to connect a Zanussi I-09/HB/A23/N8 air conditioner to OpenHAB.
It is controlled via MQTT.
Some functions are controlled through a topic in the form of a regular string 00000000, where the value can be 0 or 1. Binary flags, but in the form of a string.
For example,

  1. if I want to set ECO mode, I must send a line in the form 01000000
  2. if I want to set UV mode, I must send a line in the form 00000001

It’s simple, but these are flags and some bits can already be set or cleared.
When sending a command, I must get the current state, set/uncheck the desired flag, and send the command.

For example:

  1. Current state 00000001 - UV mode enabled
  2. I set the mode to Eco and leave the UV mode running: 01000001, and send the command.
  3. Current state 01000001 - UV mode enabled

But I don’t understand how I can implement this in OpenHab.

To control and display states, I made two ordinary switches and associated them with thing channels.
Third item for diagnostics (ac_ctrl_data)

Things channels

  - id: ac_ctrl_data
    channelTypeUID: mqtt:string
    label: "AC control data: for diag and debug"
    description: null
    configuration:
      postCommand: true
      stateTopic:  ac/dev01/state/data
      commandTopic: ac/dev01/control/data
  - id: control_mode_eco
    channelTypeUID: mqtt:switch
    label: "ECO mode: 01000000"
    configuration:
      postCommand: true
      stateTopic: ac/dev01/state/data
      transformationPattern: JS:hommyn\zacs-data-state.js?idx=1
      commandTopic: ac/dev01/control/data
      transformationPatternOut: JS:hommyn\zacs-data-command.js&idx=1
  - id: control_mode_uvc
    channelTypeUID: mqtt:switch
    label: "UV mode: 00000001"
    configuration:
      postCommand: true
      stateTopic: ac/dev01/state/data
      transformationPattern: JS:hommyn\zacs-data-state.js?idx=1
      commandTopic: ac/dev01/control/data
      transformationPatternOut: JS:hommyn\zacs-data-command.js&idx=1

Scripts:

// zacs-data-state.js: Check flag and return switch state
(function(data /* String XXXXXXXX  */, index /* order from left */) {
   return (8 == data.length && '1' == data.charAt(index) ? 'ON' : 'OFF');
})(input, index)

// zacs-data-command.js: Set flag and publish command (OnOffType to String)
(function(command /* OH4 Switch: OnOffType  */, index /* order from left */) {
    const setAt = (where, idx, what) => {  return (where.slice(0, idx) + what + where.slice(idx + what.length)); }

    // HOW I CAN GET STATE OF CONTROL DATA: items.ac_ctrl_data channel.state???!!!!
    let _state = '00000000';

    // Return '01000000' if Command=ON and index=1
    return setAt(_state, parseInt(index), ('ON' == command ? '1': '0'));
})(input, index)

As far as I understand, I cannot access items or things in transformations. Then how can I take the current state and mark the flag when sending a command (zacs-data-state.js)?

I hope I explained it clearly)) Perhaps there is some other way!!!

Help me!

You can’t use transformationPatternout for the switch channel and send anything other than ON or OFF.

Your best bet is to use a profile on the item channel link. You only need one channel.

You may need to create a channel for each of the 8 functions and update them accordingly dependent on change using a rule.

OpenHAB is not great on grouping data to send. Can you send link to docs

I tried to connect a channel between an object and a thing using:

For example: ECO mode item/thing
Profile: SCRIPT ECMAScript (ECMAScript 262 Edition 11)
Item To Thing Transformation: hommyn\zacs-item2thing-command.js?index=1

// zacs-item2thing-command.js
(function(command /* OH4 Switch: OnOffType  */, index /* order from left */) {
    const _setAt = (where, idx, what) => { return ((0 > index || _current.length <= index) ? null : (where.slice(0, idx) + what + where.slice(idx + what.length))); }

    // Get current state and check/uncheck by index
    let _current = items.ac_ctrl_data.state;
    let _result = _setAt(_current, parseInt(index), ('ON' == command ? '1': '0'));

    const log = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.zacs');
    log.info('command: ' + command + ' / index: ' + index + '=> code: ' + _current + ' => ' + _result);

    return _result; /* String 'XXXXXXXX' or null on error */
})(input, index)

I thought that from Item of type Switch with OnOffType to Thing Сhannel of type switch goes ‘ON’ or ‘OFF’ as string and I thought that my Profile Transformation could send a string in the format ‘XXXXXXXX’ to the Thing channel of type switch. But it seems to me that a Thing Channel of type switch will not accept anything as input that is not similar to OnOffType (or similar)

Now, I’m thinking of trying to make

  1. Item of type Switch
  2. Thing Channel of type String (for mqtt state and control) as channel ac_ctrl_data
  3. Profile SCRIPT ECMAScript (ECMAScript 262 Edition 11) convert OnOffType ↔ String in both directions.

I don’t know if it’s possible to do this. Will this work?

I have 5 function (items) and 5 channels (1 thing). But when they set their flag, for example 0100000, then they reset all the others, so they do not know the current state (00000001).

Link to AC docs?

You can have an openHAB rule monitor all your Items and update the Aircon with the latest states. However it gets tricky of you still want to use the remote. It will work

If you can link to more information please do

There are 2 ways to do this that I can think of:

  1. Write two rules:
    a. One to trigger on the control data changes, and update all the related virtual items
    b. One with multiple triggers, acting on commands on any of the virtual items, and construct the control data and then send it out using mqtt publish action.

  2. Write a profile instead of those rules above, which will handle data in both directions (received control data, and received commands from items).

I wouldn’t like to make rules, I understand what you mean.
But perhaps this will be the only solution.

I don’t have any additional information. There is a original HOMMYN HDN/WFN-02-01 module based on ESP, which is connected to a Zanussi air conditioner (Zanussis/Electrolux/Toshiba/Balu). The module transmits data to the cloud using the MQTT protocol; I replaced the DNS address of the manufacturer’s server with my local one. Now all control goes through my server. The manufacturer’s application (when connected via my wireless network) also works through my server.

I changed modes through the IR remote control and through the Android application and figured out how to control AC. Well, I added it to OpenHAB and everything works, except for this problem.

For this, you need to build the _state string based on the current state of all the relevant items, instead of starting with zeroes.

Or just do

let _state = items.ac_ctrl_data.state.toString();

Remove the two channels, just have one channel: ac_ctrl_data

Then link your items to this one channel, and use toItemScript and toHandlerScript

Heh! toString was my problem!