Receive IR Command with Zigbee Blaster

Hey everybody,

I am trying to trigger an action based on button pressed on an IR-remote in openhab 4. I read about LIRC a bit but tried another way which would suit my setup better as I have a ZigBee network already in place: I bought this IR ZigBee Blaster, see [1] and [2], which returns you a, I guess, the received base64 encoded IR data. However, I am struggling to match any pattern in this data if pressing the same button again and again to reliably trigger an action if the button was pressed. I collected some data if pressing the same button, see below. Has anybody an idea if I could realize my use case this this setting? I was thinking about maybe interpreting the data with LIRC lib but have not yet the required level of knowledge if this is possible. Thanks a lot!

Each line is the data received if pressing the same button once again.

B8EjbhFoAiUCgAMDlgZoAsALQAcFlgYlAiUCgAfgCwsDJQJoAkAXQAMBJQLgBQtAD+ADA0AjQAMDJQJoAsADB5YGJQIlAiUC
CaUjmxEfAh8CYwJAAweWBh8CHwJjAsADA5YGYwJAC0AHBZYGHwIfAoAHwAsDHwJjAkALB5YGYwIfAmMCQAcHlgYfAh8CYwLgBwNAF0ADAx8CYwLAAw+WBmMCHwJjAj+npSPVCB8C
B6ojhRFqAi0CgAMIjwYtAi0CagItYAEBagLAD0AHQANAAUAHQAMDLQJqAkADQAtAAwEtAkALQAMBLQKAAQFqAoADQAEBagJAF0ADAy0CagLAA8APByinqiOqCC0C
B8wjUhFwAgECgAMDfgZwAsALQAfAD0AHQAPAE8AL4AcPQBdAA0AX4AcDQBcHfgYBAgECcALAAw9+BnACAQJwAuimzCOlCHAC
B8ojZxFrAgECgAMDfQZrAsALQAfAD0AHQAPAE8AL4AcPQBdAA0AX4AcDQBdAA+ADF8APB/mmyiPBCGsC
B74jZxFvAgMCgAMDgAZvAsALA3kBbwLAD0AHQANAG0AHQANAC0ADQAtAA+AHC0AP4AMDQCNAA+AHEwsDAm8C+aa+I8AIAwI=
B7IjdBFkAi0CgAMDkQZkAoALQAEHZAKRBi0CLQKAB4ALAS0CQAdAAwMtAmQCQANAC0ADAS0C4AULQA/gAwNAI0ADAy0CZALAA4APCS0CDqeyI78ILQI=
B9EjbRFtAhACQAMDEAJ4BoAHARACQAcBbQKAD4AH4AsL4BcbQB/AAwJ4BhAgAwNtAhAC4AEDwA8H9KbRI6oIbQI=
B7sjaRFsAgYCgAMFewZsAgYC4AEDwA9AB0ADQBtAB0ADQAtAA0ALQAPgBwtAD+ADA0AjQAPgBxMLBgJsAuKmuyOoCAYC
B8UjiBFvAgYCgAMFewZvAgYC4AEDBXsGBgIGAkAHgAMDBgJvAuADC+AHD+AHG0AfwAPgBRtAAYATCwYCbwIUp8UjowhvAg==

[1] 12.76€ 49% OFF|Tuya Zigbee Smart IR Fernbedienung Universal Infrarot Fernbedienung für Smart Home für AC TV DVD arbeitet mit Alexa Google hause| | - AliExpress
[2] TuYa ZS06 control via MQTT | Zigbee2MQTT

Found a solution which works fine for me. I was not able to decode the binary data from the IR receiver in the mqtt message. However, there is a lot of structure in there but I could not map it to any of the IR encodings I assessed (NEC, RC6 modes etc.). So I used more a brute force method, see below, with sufficient results for my use case). The only real drawback is that the false negative detection rate for a pressed button greatly increases if you point the remote not straight to the receiver which is not a problem usually.

Steps:

  1. Collect example base64 data of all buttons you want to assign an action to and of those buttons used on other IR remotes being in use to avoid false positive detection if those are pressed. I collected about 10 events per button. Copy all base64 encoded events to a text file grouped by buttons and separated by an empty line.
  2. Pipe the text file to the python script, see below, to get the longest common bit pattern per button events which is not included in any of the other button’s data.
  3. Set up a cron rule to enable the IR learn function of the blaster regularly (it times out).
  4. Parse the base64 data in a rule and check for your learned bit pattern of the button and trigger the desired action.

If anybody finds a smarter / more robust way, let me know :slight_smile:

Example data text file.

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
B9wiFxL4AXYC4A0DAeYG4BUD4AM34AMr4AMXQAtAG0AHwANAD+ADAwf9m9wieQn4AQ==
B9giIhIMAmQC4A0DAdUG4BUD4AM34AMr4AMXQAFAG+ADE0AP4AMDB+mb2CKTCQwC
CeIiJxICAm0CAgLgCwMD3AYCAuATA+ADM+ADJ+ADF0ALQBtAB8ADQA/gAwMH/pviImoJAgI=
B+oiJRIIAmYC4A0DAdcG4BUD4AM34AMr4AMXQAtAG0AHwANAD+ADAwfvm+oibAkIAg==
B+oiVBL8AVMC4A0DAd8G4A8DB1MC3wb8AVMCQANAAQf8Ad8GUwLfBkAHA/wBUwLAA0ABCfwB3wZTAlMC/AHAAwHfBkADA1MC3wZABwn8Aeib6iJvCfwB
B8giORL8AXQC4A0DAeEG4BUD4AM34AMr4AMXQAtAG0AHwANAD+ADAwcPnMgieQn8AQ==
B/AiJBL3AXgC4A0DAecG4BUD4AM34AMr4AMXQAtAG0AHwANAD+ADAwfQm/Aibwn3AQ==

B7wiuxHrAXcC4A0DAdAG4BUDwDdAJ0ALQAdAA0AL4AcD4AMXQAvgAwMPmZ28Iv4I6wH//7wi/gjrAQ==
B5YirBHeAYEC4A0DAeEG4BUDwDdAJ0ALQAdAA0AL4AcD4AMXQAvgAwMPrJ2WIhMJ3gH//5YiEwneAQ==
B7oizhHiAXoC4A0DAdwG4BUDwDdAJ0ALQAdAA0AL4AcD4AMXQAvgAwMPmJ26IgIJ4gH//7oiAgniAQ==
B6wisBHcAYUC4A0DAeEG4BUDwDdAJ0ALQAdAA0AL4AcD4AMXQAvgAwMPy52sIgUJ3AH//6wiBQncAQ==
B7Mi1BHfAX8C4A0DAt8G3+AUA8A3AN8gJ0ALAN8gBwDfIANAC+AHAwDf4AIXAN8gCwDf4AIDD5OdsyL+CN8B//+zIv4I3wE=
B6MitBHkAXMC4A0DAuQG5OAUA8A3AOQgJ0ALAOQgBwDkIANAC+AHAwDk4AIXAOQgCwDk4AIDD6+doyL4COQB//+jIvgI5AE=
B7IizBHcAYMC4A0DAd8G4BUDwDdAJ0ALQAdAA0AL4AcD4AMXQAvgAwMPop2yIgMJ3AH//7IiAwncAQ==
B7QiwBHkAXoC4A0DAdwG4BUDwDdAJ0ALQAdAA0AL4AcD4AMXQAvgAwMPmp20IvkI5AH//7Qi+QjkAQ==
B6Mi0BHeAYUC4A0DAd0G4BUDwDdAJ0ALQAdAA0AL4AcD4AMXQAvgAwMPuJ2jIvMI3gH//6Mi8wjeAQ==
B50isRHnAXUC4A0DAdgG4BUDwDdAJ0ALQAdAA0AL4AcD4AMXQAvgAwMPt52dIhAJ5wH//50iEAnnAQ==

B6wiwxHzAWwC4A0DAcwG4BUD4Ac3wC/gFxfAJ8AHD32drCIKCfMB//+sIgoJ8wE=
B64isxHwAWsC4A0DAdMG4BUD4Ac3wC/gFxfAJ8AHD5OdriISCfAB//+uIhIJ8AE=
B60ipRHmAWgCgAMAlKAHwA8BzQZAAwNoAs0GQAfgCQMDaALmAUAzQANAC8AjQAtAE0ADQAvAF0APQAPAD8AHD52drSIQCeYB//+tIhAJ5gE=
A+cBagLgAQMB5AaAA+ADE0AL4AcXwA/ABw+ynaYiEAnnAf//piIQCecB
B7EirBHoAWcC4A0DAdsG4BUD4Ac3wC/gCRcDZwLbBuABF0AL4AMDD5edsSIVCegB//+xIhUJ6AE=
B5AirBHlAXkC4A0DAdsG4BUD4Ac3wC/gFxfAJ8AHD7ydkCIJCeUB//+QIgkJ5QE=
B6oiwBHlAX4C4A0DAdMG4BUD4Ac3wC/gFxfAJ8AHD4ydqiIYCeUB//+qIhgJ5QE=
B6Ii0xHeAYYC4A0DAdoG4BUD4Ac3wC/gFxfAJ8AHD62doiILCd4B//+iIgsJ3gE=
B6gi5BHiAXIC4A0DAeUG4BUD4Ac3wC/gFxfAJ8AHD6+dqCIICeIB//+oIggJ4gE=
B5wiwBHmAXMC4A0DAd8G4BUD4Ac3wC/gFxfAJ8AHD5idnCIcCeYB//+cIhwJ5gE=

B+EiFxL4AXUC4A0DAekG4BUD4AM3QCvAD+ADC0ATwA9AB0ADwBNACwvpBvgB+5vhInkJ+AE=
B+0iERIIAmsC4A0DAdIG4BUD4AM3QCvAD+ADC0ATwA9AB0ADwBNACwvSBggC5ZvtImAJCAI=
CdkiLBICAmwCAgLgCwMD3QYCAuATA+ADM0AnwA/gAwtAE8APQAdAA8ATQAsL3QYCAvyb2SJ7CQIC
B9wiRRIAAm4C4A0DAd4G4BUD4AM3QCvAD+ADC0ATwA9AB0ADwBNACwveBgAC4ZvcIncJAAI=
B+wiEBIGAmwC4A0DAtQGBuAUA+ADN0ArwA/gAwtAE8APQAdAA8ATQAsL1AYGAuib7CJ3CQYC
B+AiGRL4AXMC4A0DAeoG4BUD4AM3QCvAD+ADC0ATwA9AB0ADwBNACwvqBvgB+5vgInkJ+AE=
B+oiMhL7AXEC4A0DAeUG4BUD4AM3QCvAD+ADC0ATwA9AB0ADwBNACwvlBvsB5JvqIn8J+wE=
CtUiOxL0AZMC9AFioANAC0ADQA8F4wZiAuMGQAfgAwPgARMBYgLgAQMD4wb0AeABN+ABC0AjQA/AB+AHCwvjBvQBI5zVIpQJ9AE=
B+kiHRL9AXEC4A0DAeIG4BUD4AM3QCvAD+ADC0ATwA9AB0ADwBNACwviBv0B+pvpImoJ/QE=

B68irRHyAW0C4A0DAc0G4BUDwDdAJ8ALQAfgBw/AE0AXQAPgBw8PtJ2vIvsI8gH//68i+wjyAQ==
A+YB3gbgAQMBcQKAA0ATwAtAB+AHD8ATQBdAA+AHDw+SnZoiBwnmAf//miIHCeYB
B50i2xHnAXgC4A0DAdYG4BUDwDdAJ8ALQAfgBw/AE0AXQAPgBw8Pr52dIgUJ5wH//50iBQnnAQ==
B5Ui3RHjAXwC4A0DAdoG4BUDwDdAJ8ALQAfgBw/AE0AXQAPgBw8PzZ2VIhEJ4wH//5UiEQnjAQ==
B6QitBHsAXUC4A0DAc0G4BUDwDdAJ8ALQAfgBw/AE0AXQAPgBw8Pr52kIiAJ7AH//6QiIAnsAQ==
Cq0iwBHrAYwC6wFn4AoDAdIG4BUDwDdAJ+ADPwfSBmcCZwLrAeADAwHSBuABA0AX4AMPD4WdrSIcCesB//+tIhwJ6wE=
B6kizxHpAWcC4A0DAdkG4BUDAJxgNwFnAkAnAWcC4AED4AcPQBtAE8AD4AcPD4udqSITCekB//+pIhMJ6QE=
B5kithHsAXIC4A0DAdMG4BUDwDdAJ8ALQAfgBw/AE0AXQAPgBw8Ppp2ZIg0J7AH//5kiDQnsAQ==
B60i1xHzAWcC4A0DAc4G4BUDwDdAJ8ALQAfgBw/AE0AXQAPgBw8PmJ2tIgUJ8wH//60iBQnzAQ==

BxEj4BEJAmQC4A0DAdgG4BUD4BM34AMb4AdHQBvgAxMH2psRI1EJCQI=
BxcjDxIDAm4C4A0DAdkG4BUD4BM34AMb4AdHQBvgAxMH4psXIz4JAwI=
B/8i+xEHAnEC4A0DAdUG4BUD4BM3QBtAAUAH4AdH4AcTBxyc/yI4CQcC
CAQj+REHAmoCB2ABQAfgAwMB2wbgFQPgAyvgAwtAN+AHD0ATwANAG8ALC9sGBwLsmwQjXQkHAg==
B/Ui+xEAAm4C4A0DAd8G4BUD4BM34AMb4AdHQBvgAxMHD5z1IkUJAAI=
CRQj/hFeAl4C+QHgAQNAAYAPAeUG4BUDAV4CQAFAB+AFA0A34AMTQA/gAQMDXgJeAuADDwn5AeqbFCNICfkB
BxMj3hH8AXMC4A0DAeMG4BUD4BM34AMb4AdHQBvgAxMH9JsTI1kJ/AE=
BxEjGxL8AW8C4A0DAeUG4BUD4BM34AMb4AdHQBvgAxMH/ZsRI08J/AE=
B/4i/BH4AXMC4A0DAewG4BUD4BM34AMb4AdHQBvgAxMH6Jv+InAJ+AE=
BwgjEhL3AXgC4A0DAekG4BUD4BM34AMb4AdHQBvgAxMH6psII14J9wE=

B60isxHvAWoC4A0DAdUG4BUD4AM3wCtAE0ALQAfAA+ADD8ALQAfAAw+lna0i7AjvAf//rSLsCO8B
B6AitBHgAX4C4A0DAeMG4BUD4AM3wCtAE0ALQAfAA+ADD8ALQAfAAw+bnaAiBwngAf//oCIHCeAB
B8AiuhHqAXIC4A0DAdMG4BUD4AM3wCtAE0ALQAfAA+ADDwnTBiPdwCIqCeoB
B8AirhHqAXgC4A0DAc0G4BUD4AM3wCtAE0ALQAfAA+ADD8ALQAfAAw+gncAiAQnqAf//wCIBCeoB
B7AivBHeAYUC4A0DAt4G3uAUA+ADNwDeoCtAEwDeIAtAB8ADAN7gAg8A3qALAN4gBwDeoAMPu52wIgMJ3gH//7AiAwneAQ==
B6wizRHkAXcC4A0DAdwG4BUD4AM3wCtAE0ALQAfAA+ADD8ALQAfAAw+inawiDAnkAf//rCIMCeQB
B6QiyhHlAXIC4A0DAd0G4BUD4AM3wCtAE0ALQAfAA+ADD8ALQAfAAw+4naQiDwnlAf//pCIPCeUB
B6ci1RHpAXYC4A0DAdIG4BUD4AM3wCtAE0ALQAfAA+ADD8ALQAfAAw+1naciAQnpAf//pyIBCekB
B6Ii5RHfAX0C4A0DAd0G4BUD4AM3wCtAE0ALQAfAA+ADD8ALQAfAAw+TnaIiHQnfAf//oiIdCd8B

B5givxHjAXsC4A0DAdoG4BUD4AM3QCtAD0AHQAPAC+ALB+AHEw/CnZgiEAnjAf//mCIQCeMB
MotionGartengeschossTerasse_motion changed to OPEN
B6Yi4RHpAXEC4A0DAdYG4BUD4AM3QCtAD0AHQAPAC+ALB+AHEw+pnaYiBQnpAf//piIFCekB
B6EivRHlAXsC4A0DAdYG4BUD4AM3QCtAD0AHQAPAC+ALB+AHEw+ZnaEiDgnlAf//oSIOCeUB
B7ciqxHlAXsC4A0DAdcG4BUD4AM3QCtAD0AHQAPAC+ALB+AHEw+ZnbciCwnlAf//tyILCeUB
B7oi6RHhAX4C4A0DAdwG4BUD4AM3QCtAD0AHQAPAC+ALB+AHEw+dnboi9wjhAf//uiL3COEB
A+IBdgLgBQMAjiAPQAMB1gbAAwN2AtYGwAvgAQcBdgLgAQNAF0APQAdAA8AL4AcHQFfgBxMPuJ2sIgYJ4gH//6wiBgniAQ==
A+QBfwLgDQMB1AbgFQPgAzdAK0APQAdAA8AL4AsH4AcTD8KdnCIPCeQB//+cIg8J5AE=
B7Mi0xHnAXMC4A0DAdwG4BUD4AM3QCtAD0AHQAPAC+ALB+AHEw+bnbMi+wjnAf//syL7COcB

BwMjFhL/AW4C4A0DAeIG4BUD4AM3QCvgAw/gAwvAG0AH4AsDB/CbAyNhCf8B
BxUjABIQAmMC4AEDQAHADwHSBuAVA0AB4AMrwAvgBwdAR0ATQAfgCwMH55sVIzIJEAI=
CRwjEBICAm8CAgLgCwMD2AYCAuATA+ADM0An4AMP4AMLwBtAB+ALAwfjmxwjUQkCAg==
B/MiERL2AXwC4A0DAeQG4BUD4AM3QCvgAw/gAwvAG0AH4AsDB/2b8yJPCfYB
BwUjABIAAnIC4A0DAd0G4BUD4AM3QCvgAw/gAwvAG0AH4AsDB+ybBSNnCQAC
B/kiFBL5AXUC4A0DAeUG4BUD4AM3QCvgAw/gAwvAG0AH4AsDBxac+SI6CfkB
Cf8i+RECAmwCAgLgCwMD1gYCAuATA+ADM0An4AMP4AELAWwCwBtAB+ALAwcYnP8iOwkCAg==
BwYjFRL2AXgC4A0DAeoG4BUD4AM3QCvgAw/gAwvAG0AH4AwDBpsGI2gJ9gE=
B/gi5xEJAmIC4A0DAdkG4BUD4AM3QCvgAw/gAwvAG0AH4AsDB/2b+CJOCQkC
Bw4jEhIEAmgC4A0DAd0G4BUD4AM3QCvgAw/gAwvAG0AH4AsDB9ibDiMyCQQC

DM8EKzDkAPYjiwBlCOQgAwRXAfMG6eAIAwGKAuAJA0AnwBfAC0AHwANAG+AHCw/+m/YjZQjpAf//8wb2I1cB
FOsEBDAAAeIjpABdCAABXQhmAe4G9OAIAwF4AuAJA0AnwBfAC0AHwANAG+AHCw/5m+IjXQj0Af//7gbiI2YB
C9wEIDAkAeQjzABqCEADBCQB7gb34AgDAW8C4AkDQCfAF8ALQAfAA0Ab4AcLD/Wb5CNqCPcB///uBuQjYAE=
DOYEFDAuAeIjnQByCPAgAwQuAQIH5OAIAwGAAuAJAwACICfAF8ALQAfAA0Ab4AcLDw6c4iNyCOQB//8CB+IjLgE=
DNkEJzD4ADkkwAAPCPggAwRDAeMG+OAIAwd7AnsC+AH4AUAFwANAJ+AHC0ATwANAG+AHCwclveMGOSRDAQ==
C/IEMTDtAOsjxABqCEADBFgB7wbp4AgDAYsC4AkDQCfAF8ALQAfAA0Ab4AcLD/Gb6yNqCOkB///vBusjWAE=
DN4ELTDvAOkjwABaCO8gAwRQAf4G4eAIAwGKAuAJA0AnwBfAC0AHwANAG+AHCw8KnOkjWgjhAf///gbpI1AB
FO8EFjAVAe8jwABPCBUBTwhXAfoG4OAIAwGUAuAJA0AnwBfAC0AHwANAG+AHCw8cnO8jTwjgAf//+gbvIxUB
C/UEFTBAAdQjyABaCEADBEAB6wbx4AgDAYEC4AkDQCfAF8ALQAfAA0Ab4AcLDw+c1CNaCPEB///rBtQjYgE=
C/QENDDtAPEjwABrCEADBHYB7gbt4AgDAYUC4AkDQCfAF8ALQAfAA0Ab4AcLD+ub8SNrCO0B///uBvEjNgE=

Python script to get longest bit pattern for button recognition.

import sys
from collections import defaultdict

def all_common_substrings(strs, allowed_misses):
    """Returns all common substrings from a list of strings sorted by length (desc)."""
    if not strs:
        return []

    def substring_present_in_most(sub, strs):
        """
        Check if a substring is present in all but a defined number of strings.

        Returns True if the substring 'sub' is absent in 'allowed_misses' or fewer strings in 'strs'.
        Otherwise, it returns False.
        """
        misses = sum(1 for s in strs if sub not in s)
        return misses <= allowed_misses

    base = min(strs, key=len)
    substr_set = set()

    for length in range(len(base), 0, -1):
        for i in range(len(base) - length + 1):
            substring = base[i:i+length]
            if substring_present_in_most(substring, strs) and substring not in substr_set:
                substr_set.add(substring)

    return sorted(substr_set, key=len, reverse=True)

def main():
    groups = []
    current_group = []
    substring_frequency = defaultdict(int)

    for line in sys.stdin:
        line = line.strip()
        if not line and current_group:
            groups.append(current_group)
            current_group = []
        else:
            current_group.append(line)
    if current_group:
        groups.append(current_group)

    for group in groups:
        for line in group:
            for i in range(len(line)):
                for j in range(i+1, len(line)+1):
                    substring_frequency[line[i:j]] += 1

    for i, group in enumerate(groups):
        max_allowed_misses = len(group) // 2
        allowed_misses = 0
        unique_patterns = []

        # Adjust the allowed_misses for each group until a common substring is found or max_allowed_misses is reached
        while not unique_patterns and allowed_misses <= max_allowed_misses:
            patterns = all_common_substrings(group, allowed_misses)
            unique_patterns = [pattern for pattern in patterns if substring_frequency[pattern] == sum(pattern in line for line in group)]
            if not unique_patterns:
                allowed_misses += 1

        print(f"Group {i+1} unique common substrings (Allowed misses: {allowed_misses}):")
        for pattern in unique_patterns:
            print(f"  {pattern}")
        
        if not unique_patterns:
            print(f"  No unique common bit patterns found for this group.")
        print()

if __name__ == "__main__":
    main()

Rules to let IR blaster receive commands continuously.

rule "IR command received"
when
     Item IRremote received update
then
    val mqttActions = getActions("mqtt","mqtt:broker:MyMQTTBroker")

    mqttActions.publishMQTT("zigbee2mqtt/IRremote/set", "{\"learn_ir_code\": \"ON\"}")
end

rule "IR cron"
when
     Time cron "0/10 0/1 * 1/1 * ? *"
then
    val mqttActions = getActions("mqtt","mqtt:broker:MyMQTTBroker")

    mqttActions.publishMQTT("zigbee2mqtt/IRremote/set", "{\"learn_ir_code\": \"ON\"}")
end

Rule to parse IR command and trigger actions.


rule "Decode Base64 to Binary with Padding"
when
    Item IRRemoteWohnzimmer_lernedircode received update
then
    val base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    var binaryString = ""

    val String encoded = IRRemoteWohnzimmer_lernedircode.state.toString.trim
    for (var i = 0; i < encoded.length; i++) {
        val charIndex = base64chars.indexOf(encoded.charAt(i))
        if (charIndex != -1) {
            val charBinary = String::format("%6s", Integer::toBinaryString(charIndex)).replace(' ', '0')

            binaryString += charBinary
        }
    }

    // Handle padding
    if (encoded.endsWith("==")) {
        // Remove the last 4 bytes (32 bits) for 2 padding characters
        binaryString = binaryString.substring(0, binaryString.length - 32)
    } else if (encoded.endsWith("=")) {
        // Remove the last 2 bytes (16 bits) for 1 padding character
        binaryString = binaryString.substring(0, binaryString.length - 16)
    }


    val patternButton1 = "11000000000100111110000000000011000001110100000000001011110000000000001100001111" // Replace with your desired pattern
    val patternButton2 = "100111110000000000000" // Replace with your desired pattern

...
    
   if (binaryString.contains(patternButton1)) {
            // Add the desired action here
     
   } else {
              if (binaryString.contains(patternButton2)) {
              // Add the desired action here
              }
   } 

end