Substring separation from String

Hello,
I’m new to OpenHAB and thus I need to learn a lot of things. :grinning:
Up to now I created a generic MQTT Thing which is sbuscribed to an external MQTT broker.
The MQTT Thing is linked to an Item and there I store the MQTT payload (message).
(Connection to the broker and all that works, I get the payload.)
This has the form:

R1:ON

or e.g.

R1:OFF

and other numbers instead of “1”.
No I need to extract the text after the colon “:” and I need to know the number left from the colon.
this will be only a one digit number.

I’m trying to create a rule based on DSL to extract substrings but it does not work.
Could you please help me?
Thank you in advance.
Wolfgang

Why do you need to split them?

Without knowing anything more about your device than what you’ve written, I would just create separate Thing Channels for each R that you have, and then in the custom on/off value options just use the payload strings.

Hi,
I’m not familiar with channels. Sorry.
I do not understand your proposal.
Is it possible to have different channels activated depending on the content of the payload?
Sorry, if the question is on low level but OpenHAB is really new for me.
Thank you.
W.

But you say you linked your Thing to an Item - you can only do that via a Thing Channel.

Yes.

I’d take a step back and have a look through the documentation, especially the Getting Started guide. That should bring you up to speed on the concepts, and there’s an MQTT example or two in there too!

I read the Getting Started section and also the MQTT example.
There they have json messages but I don’t have this.
The message is really simple like I wrote before and I have not idea how I could separate the information in various channels I have one channel and that contains the complete MQTT message.

Show us this mystery Thing so we can work on it. Copy the YAML from the Code tab and share here in-between code fences.

This is my generic MQTT Thing.

UID: mqtt:topic:ce47d0e09b:900c9c2ed9
label: Generic MQTT Thing
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:ce47d0e09b
location: Test
channels:
  - id: channel_ID
    channelTypeUID: mqtt:string
    label: MyTestLabel_Inbound
    description: ""
    configuration:
      stateTopic: TEST

Does this help?
Thank you in any case.

Sending of MQTT messages is done directly in the shell with the Mosquitto publish command.
I mean I use the Mosquitto publish command to send a message. The Mosquitto publish command is to simulate the real device. In reality the message is send by a water irrigation based on an Arduino device (ESP32).
However, the payload is according to the pattern

R1:ON

or

R1:OFF

as written before.

Ah, just met…
Given a String Item mqttIn with the full payload:

rule "mqttIn auswerten"
when
    Item mqttIn received update
then
    val String strIn = mqttIn.state.toString
    if(strIn.length < 5) {
        logWarn("mqttIn","erwartete Länge verfehlt: {} ({})",strIn,strIn.length)
        return;
    }
    val String strLetter = strIn.charAt(0)
    val Integer iNumber  = Integer::parseInt(strIn.charAt(1))
    val Value = if(strIn.charAt(4) == "F") OFF else ON
    if(strLetter != "M" && strLetter != "R") {
        logWarn("mqttIn","1. Buchstabe falsch: {}",strLetter)
        return;
    }
    if(strLetter == "M") {
        switch(iNumber) {
            case 1: Item1.sendCommand(Value)
            case 2: Item2.sendCommand(Value)
            case 3: Item3.sendCommand(Value)
            case 4: Item4.sendCommand(Value)
            case 5: Item5.sendCommand(Value)
            case 6: Item6.sendCommand(Value)
            case 7: Item7.sendCommand(Value)
            case 8: Item8.sendCommand(Value)
            case 9: Item9.sendCommand(Value)
        }
    } else {
        switch(iNumber) {
            case 1: Item10.sendCommand(Value)
            case 2: Item11.sendCommand(Value)
            case 3: Item12.sendCommand(Value)
            case 4: Item13.sendCommand(Value)
            case 5: Item14.sendCommand(Value)
            case 6: Item15.sendCommand(Value)
            case 7: Item16.sendCommand(Value)
            case 8: Item17.sendCommand(Value)
            case 9: Item18.sendCommand(Value)
        }
    }
end

Of course there are many other ways to do this, it’s up to the exact job if this solution is ok or not…

@Udo_Hartmann has actually provided an answer to your OP, but I would still do all this within Channels, not requiring a rule at all. Again, though, we don’t know much about the application, so the following solution assumes:

  • Your device is a relay, switching things on and off only
  • You have no control over the code on your Arduino device
  • Your MQTT topic is TEST for all messages that get sent from your Arduino device
  • You are controlling four (4) switches.

For the following solution, make sure the RegEx Transformation Service is installed: SettingsBindingsSearch.

Then create a Generic MQTT Thing with the following Channels:

UID: mqtt:topic:ce47d0e09b:MysteryArduinoIrrigation
label: Mystery Arduino Irrigation
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:ce47d0e09b
channels:
  - id: R1
    channelTypeUID: mqtt:switch
    label: R1
    description: ""
    configuration:
      stateTopic: TEST
      transformationPattern: REGEX:(.*R1.*)
      off: R1:OFF
      on: R1:ON
  - id: R2
    channelTypeUID: mqtt:switch
    label: R2
    description: null
    configuration:
      stateTopic: TEST
      transformationPattern: REGEX:(.*R2.*)
      off: R2:OFF
      on: R2:ON
  - id: R3
    channelTypeUID: mqtt:switch
    label: R3
    description: null
    configuration:
      stateTopic: TEST
      transformationPattern: REGEX:(.*R3.*)
      off: R3:OFF
      on: R3:ON
  - id: R4
    channelTypeUID: mqtt:switch
    label: R4
    description: null
    configuration:
      stateTopic: TEST
      transformationPattern: REGEX:(.*R4.*)
      off: R4:OFF
      on: R4:ON

Notes:

  • Each Channel is of type Switch, and these are then linked through to Switch type Items.
  • Each Channel specifies a custom on/off value, relevant to the switch number.
  • To prevent warnings in the logs, the REGEX is used to filter the incoming message so only the relevant one is passed to the relevant Channel.
  • If there are more switches just add extra Channels.

If you do have control over the code on the Arduino device then I would just get each relay or switch to publish their on/off status on dedicated topics. For example:

myirrigationdevice/R1

You then use this in the State Topic of the relevant Channel, and you wouldn’t need the transformationPattern, on and off parameters at all.

Hello,
thank you for both replies I will try them today in the evening but during the day is spring time and work in the garden needs to be done. :slight_smile:

Till later.
Wolfgang

Hello Udo,
I started first with your proposal from above. I took your code, adapted it to my Item names etc.
I did this with Visual Studio Code and having the OpenHAB language support installed there.
(I read in book that this helps to have a good code with less errors.)

Then I saved the new rule in the given folder /etc/openhab/rules and it was recognized because I also do see it in the Rules section in the Paper UI. So far so good.
In the PaperUI I can run the rule (there is a link at the bottom to do this.)
Unfortunately now I get an error in the log file saying that some method can not be invoked.
This is the error:

022-03-19 19:20:07.174 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'MQTT_Eval_In-1' failed: An error occurred during the script execution: Could not invoke method: java.lang.Integer.parseInt(java.lang.String) on instance: null in MQTT_Eval_In

Do I need to import some libraries at the start of the rule and if yes which ones?
Thank you.
Wolfgang

I did a quick test, and there is a small issue in the rule :slight_smile: .charAt() is of Type Char, not String. So please add a .toString on every .charAt():

...
    val String strIn = mqttIn.state.toString
        if(strIn.length < 5) {
            logWarn("mqttIn","erwartete Länge verfehlt: {} ({})",strIn,strIn.length)
            return;
        }
        val String strLetter = strIn.charAt(0).toString
        val Integer iNumber  = Integer::parseInt(strIn.charAt(1).toString)
        val Value = if(strIn.charAt(4).toString == "F") OFF else ON
        if(strLetter != "M" && strLetter != "R") {
            logWarn("mqttIn","1. Buchstabe falsch: {}",strLetter)
            return;
        }
// for a short test:
        logInfo("mqttIn","Letter {} Number {} Value {}",strLetter,iNumber,Value)
...

Hello,
Thank you for the support again. You are great. :grinning:
I inserted the ".toString method and then
I tested the rule and intentionally I 've send a MQTT message being to short and this created an error entry in the openhab log as it was supposed to do.
Now, I will check the next things.
I will keep you informed.

The rule works fine. The Gordian knot is untied. (at least this one.) :wink:
Thank you!

Wolfgang

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.