Slack integration: how to integrate

I’d like to use slack as a communication hub between openHAB and my family.
So I set up a slack channel and followed the instructions here: Slack integration · openhab/openhab1-addons Wiki · GitHub and here sumnerboy12’s gists · GitHub from @ben_jones12

So far i got the communication between slack and the python library up and running, the sample “repeat”-Plugin works fine. So I pasted the slackhab.py in my plugins-folder. What I did come across: the “repeat.py” example, python uses a class, which is referenced in rtmbot.conf - the slackhab.py isn’t, it’s just plain in the plugins.folder.

I’m using openHABian and OH2, if this has some Impact also.

rtmbot.conf

# Add the following to rtmbot.conf
DEBUG: True # make this False in production
SLACK_TOKEN: "xoxb-xxxx"
ACTIVE_PLUGINS:
#    - plugins.repeat.RepeatPlugin
#    - plugins.slackhab.openHABPlugin

rtmbot.log

2016-12-09 12:13:12,287 Initialized in: /usr/local/bin
2016-12-09 12:13:12,314 Starting new HTTPS connection (1): slack.com
2016-12-09 12:13:12,749 "POST /api/rtm.start HTTP/1.1" 200 4534
2016-12-09 12:13:13,401 Loading plugins
2016-12-09 12:13:13,405 No plugins specified in conf file
2016-12-09 12:13:13,407 got process_hello
2016-12-09 12:13:13,510 got process_presence_change
2016-12-09 12:13:13,613 got process_message
2016-12-09 12:13:13,717 got process_reconnect_url
2016-12-09 12:13:13,819 got process_presence_change
2016-12-09 12:13:13,921 got process_pong
2016-12-09 12:13:17,247 got process_pong
2016-12-09 12:13:21,278 got process_pong
2016-12-09 12:13:25,208 got process_pong
2016-12-09 12:13:29,240 got process_pong
2016-12-09 12:13:33,267 got process_pong
2016-12-09 12:13:37,299 got process_pong
2016-12-09 12:13:41,228 got process_pong
2016-12-09 12:13:45,254 got process_pong

at around 12:13:30 i sent: “update USB_EG_Windfang_01 OFF
.item

Switch USB_EG_Windfang_01 	"USB: Hausnummer"

slackhab.py

import time
import xml.etree.ElementTree as xml

crontable = []
outputs = []

debug            = True
openhab_url      = 'http://192.168.xxx.xxx:8080' // my openHAB-URL
slackhab_user_id = "Uxxx" // the Userid from the bot in slack

headers          = { 'Content-Type': 'text/plain' }

def process_message(data):
    print_debug(str(data))

    # check we have sufficient details
    if 'channel' not in data or 'user' not in data or 'text' not in data:
        return

    channel = data['channel']
(...)

My guess is, the Connection between slack and the RTM-bot isn’t configured? I tried to pack all defs in slackhab.py in a class and reference it in rtmbot.conf (see escaped pluginname in rtmbot.conf)

Now I get an error in the rtmbot.log like this:

2016-12-09 12:22:21,087 Initialized in: /usr/local/bin
2016-12-09 12:22:21,111 Starting new HTTPS connection (1): slack.com
2016-12-09 12:22:21,763 "POST /api/rtm.start HTTP/1.1" 200 4529
2016-12-09 12:22:22,402 Loading plugins
2016-12-09 12:22:22,406 Importing plugins.slackhab.openHABPlugin
2016-12-09 12:22:22,429 Plugin registered: <plugins.slackhab.openHABPlugin object at 0x76231ed0>
2016-12-09 12:22:22,430 Registering jobs for openHABPlugin
2016-12-09 12:22:22,430 No jobs registered for openHABPlugin
2016-12-09 12:22:22,432 got process_hello
2016-12-09 12:22:22,534 got process_presence_change
2016-12-09 12:22:22,638 got process_message
2016-12-09 12:22:22,639 Problem in Plugin Class: openHABPlugin: process_message 
{u'text': u'from repeat1 "update USB_EG_Windfang_01 OFF" in channel Dxxx', u'ts': u'14xx.xx', u'user': u'Uxx', u'reply_to': None, u'type': u'message', u'channel': u'Dxx}
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/rtmbot/core.py", line 205, in do
    func(data)
TypeError: process_message() takes exactly 1 argument (2 given)
2016-12-09 12:22:22,743 got process_reconnect_url
2016-12-09 12:22:22,845 got process_presence_change
2016-12-09 12:22:22,947 got process_pong
2016-12-09 12:22:26,271 got process_pong
2016-12-09 12:22:30,299 got process_pong
2016-12-09 12:22:34,226 got process_pong
2016-12-09 12:22:38,257 got process_pong
2016-12-09 12:22:42,285 got process_pong
2016-12-09 12:22:46,213 got process_pong
2016-12-09 12:22:50,241 got process_pong
2016-12-09 12:22:54,270 got process_pong
2016-12-09 12:22:58,299 got process_pong
2016-12-09 12:23:02,223 got process_pong
2016-12-09 12:23:06,254 got process_pong
2016-12-09 12:23:10,282 got process_pong
2016-12-09 12:23:14,208 got process_pong
2016-12-09 12:23:18,238 got process_pong
2016-12-09 12:23:22,261 got process_pong
2016-12-09 12:23:26,292 got process_pong
2016-12-09 12:23:30,219 got process_pong
2016-12-09 12:23:34,247 got process_pong
2016-12-09 12:23:38,277 got process_pong
2016-12-09 12:23:42,300 got process_pong
2016-12-09 12:23:46,230 got process_pong
2016-12-09 12:23:48,949 got process_user_typing
2016-12-09 12:23:50,260 got process_pong
2016-12-09 12:23:54,288 got process_pong
2016-12-09 12:23:55,198 got process_user_typing
2016-12-09 12:23:57,318 got process_message
2016-12-09 12:23:57,319 Problem in Plugin Class: openHABPlugin: process_message 
{u'text': u'update Sensoren_Temp_SpOben 54.1', u'ts': u'1xx.xx', u'user': u'Uxx', u'team': u'Txx', u'type': u'message', u'channel': u'Dxx'}
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/rtmbot/core.py", line 205, in do
    func(data)
TypeError: process_message() takes exactly 1 argument (2 given)
2016-12-09 12:23:58,229 got process_pong

first item “USB_EG_Windfang_01” is a SWITCH item, second item “Sensoren_Temp_SpOben” is a NUMBER item.

So, where’s my error here? Thanks for help!

Hi - not sure what the problem is there sorry - where did openHABPlugin come from?

The script, you provided at github didn’t work for me. i guessed, it was because, it didn’t come as a class and the class wasn’t referenced in the conf.

So, what I did was:

  1. Changing rtmbot.conf - adding the class openHABPlugin
  2. changing slackbot.py - moving everything in a class

ad 1)

# Add the following to rtmbot.conf
DEBUG: True # make this False in production
SLACK_TOKEN: "xoxb-xxx-yyy"
ACTIVE_PLUGINS:
#    - plugins.repeat.RepeatPlugin
    - plugins.slackhab.openHABPlugin

ad 2)

import requests
import time
import xml.etree.ElementTree as xml

crontable = []
outputs = []

debug            = True

openhab_url      = 'http://192.168.xx.xx:8080'
slackhab_user_id = "xxxx"

headers          = { 'Content-Type': 'text/plain' }

from rtmbot.core import Plugin

class openHABPlugin(Plugin):

	def process_message(data):
		print_debug(str(data))

		# check we have sufficient details
		if 'channel' not in data or 'user' not in data or 'text' not in data:
			return

		channel = data['channel']
		user = data['user']
		text = data['text']

		# first check if we are interested in this command
		command_text = get_command_text(channel, user, text)

		if command_text is None:
			return

		tokens = command_text.split()
		if len(tokens) == 0:
			return

		command = tokens[0].lower()

		if command == "send" and len(tokens) >= 3:
			item = tokens[1]
			value = " ".join(tokens[2:])
			url = openhab_url + '/rest/items/' + item
			r = requests.post(url, headers=headers, data=value)

			if check_response(r, channel):
				outputs.append([ channel, "```Sent %s command to %s```" % (value, item) ])

		elif command == "update" and len(tokens) >= 3:
			item = tokens[1]
			value = " ".join(tokens[2:])
			url = openhab_url + '/rest/items/' + item + '/state'
			r = requests.put(url, headers=headers, data=value)

			if check_response(r, channel):
			   outputs.append([ channel, "```Sent %s update to %s```" % (value, item) ])

		elif command == "status" and len(tokens) >= 2:
			item = tokens[1]
			url = openhab_url + '/rest/items/' + item + '/state'
			r = requests.get(url, headers=headers)

			if check_response(r, channel):
				outputs.append([ channel, "```%s is %s```" % (item, r.text) ])

		elif command == "items":
			filter = None
			if len(tokens) > 1:
				filter = tokens[1].lower()

			url = openhab_url + '/rest/items'
			r = requests.get(url, headers=headers)

			if check_response(r, channel):
				items = []
				output = ""
				maxtypelen = 0
				maxnamelen = 0

				for item in xml.fromstring(r.content).findall('item'):
					name = item.find('name').text
					type = item.find('type').text
					if filter is None or filter in name.lower():
						items.append(item)
						if len(type) > maxtypelen:
							maxtypelen = len(type)
						if len(name) > maxnamelen:
							maxnamelen = len(name)

				for item in items:
					name  = item.find('name').text
					state = item.find('state').text                
					type  = item.find('type').text
					output = output + "%s%s%s\n" % (type.ljust(maxtypelen+5), name.ljust(maxnamelen+5), state) 
					if len(output) >= 8000:
						output = output + "... (too much output, please specify a filter)"
						break

				if len(items) == 0:
					if filter is None:
						outputs.append([ channel, "```No items found```" ])
					else:
						outputs.append([ channel, "```No items found matching '%s'```" % (filter) ])
				else:
					outputs.append([ channel, "```%s```" % (output) ])

	def get_command_text(channel, user, text):
		if channel == "" or channel is None:
			return None
		if user == "" or user is None:
			return None
		if text == "" or text is None:
			return None

		# check for a message directed at our bot
		user_tag = "<@%s>:" % (slackhab_user_id)

		if text.startswith(user_tag):
			return text[len(user_tag):]

		# check for a DM to our bot
		if channel.startswith("D"):
			return text

		return None

	def check_response(r, channel):
		# check our rest api call was successful
		if r.status_code == 200:
			return True
		if r.status_code == 201:
			return True

		# log the response code/reason back to our slack channel
		outputs.append([ channel, "```%d: %s```" % (r.status_code, r.reason) ])
		return False

	def print_debug(message):
		if debug:
			print message

and that’s getting me some log-entries after all. Just saving slackbot.py in the /plugins directory didn’t work for me…?

Thanks for your help!

Yep - I finally got a chance to look at this. Seems the rtmbot has changed a bit since I wrote that integration. I have updated my GIST so try it out now and see if you have any luck.

works like a charm now! (as I use the script on the same openHABian as OH2, I had to replace the IP-address of my OH2 in slackbot.py with “localhost”, otherwise I got connection refused errrors with the API).

Thanks a lot!

Do you use some actions or rules to send updates from openHAB to slack? e.g. I’d like to have a notification, if my son’s home from school, or the temperature of my heating storage tank is low, …

For that I use mqttwarn - so I publish the message to an MQTT topic (e.g. /openhab/notification/info) and have mqttwarn configured to watch that topic and publish the message to various endpoints (one of which is a Slack channel).

mqttwarn supports dozens of different services for sending messages to.

OK, MQTT is on my to do list to check. Thanks.

Hey Thomas,
it’s always nice to see an idea work out in the end! :wink:
Do you think you can rephrase your first posting as instructions rather than a question so we can move this thread over to the Tutorials & Examples category? That would be amazing!

ok. I can do that. But first, I have to ask @ben_jones12 two more Things! :wink:

for now I just used send, which worked with Switches (ON/OFF) and Numbers (e.g. 0-100 for light dimmers) and Strings.

From your readme, I get two more Options: “update” and “items”. Can you please explain the difference between send and update? In my cases, they had the same effect. :wink:

Unfortunately the command “items” threw some Errors:

items [Light_EG_WoZi_LG4]

2016-12-13 21:12:47,573 got process_message
2016-12-13 21:12:47,579 Starting new HTTP connection (1): localhost
2016-12-13 21:12:47,714 "GET /rest/items HTTP/1.1" 200 None
2016-12-13 21:12:47,721 Problem in Plugin Class: openHABPlugin: process_message 
{u'text': u'items [Light_EG_WoZi_LG4]', u'ts': u'1xxx.xxx', u'user': u'Uxxx', u'team': u'Txxx', u'type': u'message', u'channel': u'Dxxx'}
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/rtmbot/core.py", line 205, in do
    func(data)
  File "/home/pi/binderhaus/plugins/slackhab.py", line 82, in process_message
    for item in xml.fromstring(r.content).findall('item'):
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1300, in XML
    parser.feed(text)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1642, in feed
    self._raiseerror(v)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1506, in _raiseerror
    raise err
ParseError: syntax error: line 1, column 0

I guess, it should write out some items and their states?
http://localhost:8080/rest/items works for me…

Thanks!

FYI - I have just made some changes to my script to make it easier to config and use.

Hi @ben_jones12,

I changed my config as described:

  • added slackhab.ini
  • changed slackhab.py

unfortunately I get this Errors, did I miss something?

2016-12-17 12:59:27,774 got process_user_typing
2016-12-17 12:59:27,877 got process_message
2016-12-17 12:59:27,892 Starting new HTTP connection (1): localhost
2016-12-17 12:59:28,026 "GET /rest/items HTTP/1.1" 200 None
2016-12-17 12:59:28,039 Problem in Plugin Class: SlackhabPlugin: process_message 
{u'text': u'status Binder_Vacation', u'ts': u'1xxx.000010', u'user': u'U3CMCHKJN', u'team': u'Txxx', u'type': u'message', u'channel': u'Dxxx'}
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/rtmbot/core.py", line 205, in do
    func(data)
  File "/home/pi/binderhaus/plugins/slackhab.py", line 81, in process_message
    item = self.get_single_item(filter, channel)
  File "/home/pi/binderhaus/plugins/slackhab.py", line 112, in get_single_item
    items = self.get_items(filter, channel)
  File "/home/pi/binderhaus/plugins/slackhab.py", line 137, in get_items
    for item in xml.fromstring(r.content).findall('item'):
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1300, in XML
    parser.feed(text)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1642, in feed
    self._raiseerror(v)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1506, in _raiseerror
    raise err
ParseError: syntax error: line 1, column 0
2016-12-17 12:59:28,150 got process_desktop_notification
2016-12-17 12:59:31,274 got process_pong
2016-12-17 12:59:32,081 got process_user_typing
2016-12-17 12:59:32,184 got process_message
2016-12-17 12:59:32,191 Starting new HTTP connection (1): localhost
2016-12-17 12:59:32,353 "GET /rest/items HTTP/1.1" 200 None
2016-12-17 12:59:32,361 Problem in Plugin Class: SlackhabPlugin: process_message 
{u'text': u'send Binder_Vacation OFF', u'ts': u'1xxx.000011', u'user': u'Uxxx', u'team': u'Txxx', u'type': u'message', u'channel': u'Dxxx'}
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/rtmbot/core.py", line 205, in do
    func(data)
  File "/home/pi/binderhaus/plugins/slackhab.py", line 54, in process_message
    item = self.get_single_item(filter, channel)
  File "/home/pi/binderhaus/plugins/slackhab.py", line 112, in get_single_item
    items = self.get_items(filter, channel)
  File "/home/pi/binderhaus/plugins/slackhab.py", line 137, in get_items
    for item in xml.fromstring(r.content).findall('item'):
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1300, in XML
    parser.feed(text)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1642, in feed
    self._raiseerror(v)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1506, in _raiseerror
    raise err
ParseError: syntax error: line 1, column 0
2016-12-17 12:59:32,468 got process_desktop_notification
2016-12-17 12:59:35,284 got process_pong

items
Switch Binder_Vacation "Urlaub" (gBinder)

rtmbot.conf:

# Add the following to rtmbot.conf
DEBUG: True # make this False in production
SLACK_TOKEN: "xoxb-114746204098-xxx"
ACTIVE_PLUGINS:
#    - plugins.repeat.RepeatPlugin
    - plugins.slackhab.SlackhabPlugin

./plugins/slackhab.ini:

[slackhab]
debug            = True
openhab_url      = http://localhost:8080
slackhab_user_id = Uxxx

./plugins/slackhab.py (copied from your gist):

import ConfigParser
import os
import requests
import time
import xml.etree.ElementTree as xml

from rtmbot.core import Plugin

SCRIPTDIR  = os.path.dirname(__file__)
SCRIPTNAME = os.path.splitext(os.path.basename(__file__))[0]
CONFIGFILE = os.getenv(SCRIPTNAME.upper() + 'INI', os.path.join(SCRIPTDIR, SCRIPTNAME + '.ini'))

# parse our config/ini file
config = ConfigParser.ConfigParser()
config.read(CONFIGFILE)

debug            = config.get('slackhab', 'debug')
openhab_url      = config.get('slackhab', 'openhab_url')
slackhab_user_id = config.get('slackhab', 'slackhab_user_id')

# headers required for openhab REST API requests
headers          = { 'Content-Type': 'text/plain' }

class SlackhabPlugin(Plugin):

    def process_message(self, data):
        print_debug("rx'd message: %s" % (str(data)))

        # check we have sufficient details
        if 'channel' not in data or 'user' not in data or 'text' not in data:
            return

        channel = data['channel']
        user = data['user']
        text = data['text']

        # first check if we are interested in this command
        command_text = get_command_text(channel, user, text)

        if command_text is None:
            return

        tokens = command_text.split()
        if len(tokens) == 0:
            return

        command = tokens[0].lower()
        print_debug("command: %s" % (command))

        if command == "send" and len(tokens) >= 3:
            filter = tokens[1]
            value = " ".join(tokens[2:])
            
            item = self.get_single_item(filter, channel)
            if item is None:
                return
                
            url = openhab_url + '/rest/items/' + get_item_attr(item, 'name')
            r = requests.post(url, headers=headers, data=normalise_value(value))
            
            if self.check_response(r, channel):
                self.outputs.append([ channel, "```Sent %s command to %s```" % (value, get_item_attr(item, 'name')) ])

        elif command == "update" and len(tokens) >= 3:
            filter = tokens[1]
            value = " ".join(tokens[2:])
            
            item = self.get_single_item(filter, channel)
            if item is None:
                return
            
            url = openhab_url + '/rest/items/' + get_item_attr(item, 'name') + '/state'
            r = requests.put(url, headers=headers, data=normalise_value(value))

            if self.check_response(r, channel):
               self.outputs.append([ channel, "```Sent %s update to %s```" % (value, get_item_attr(item, 'name')) ])

        elif command == "status" and len(tokens) >= 2:
            filter = tokens[1]

            item = self.get_single_item(filter, channel)
            if item is None:
                return
            
            url = openhab_url + '/rest/items/' + get_item_attr(item, 'name') + '/state'
            r = requests.get(url, headers=headers)

            if self.check_response(r, channel):
                self.outputs.append([ channel, "```%s is %s```" % (get_item_attr(item, 'name'), r.text) ])

        elif command == "items":
            filter = None
            if len(tokens) > 1:
                filter = tokens[1]

            output = ""
            maxtypelen = 0
            maxnamelen = 0

            items = self.get_items(filter, channel)
            print_debug("%d items match %s" % (len(items), filter))

            if len(items) == 0:
                if filter is None:
                    self.outputs.append([ channel, "```No items found```" ])
                else:
                    self.outputs.append([ channel, "```No items found matching '%s'```" % (filter) ])
            else:
                self.print_items(items, channel)

    def get_single_item(self, filter, channel):    
        items = self.get_items(filter, channel)
        items_count = len(items)
        
        if items_count == 1:
            print_debug("found single matching item: %s" % (get_item_attr(items[0], 'name')))
            return items[0]

        if items_count > 1:
            self.outputs.append([ channel, "```Found %d items matching '%s', please restrict your filter```" % (items_count, filter) ])
            self.print_items(items, channel)
        else:
            self.outputs.append([ channel, "```No item found matching '%s'```" % (filter) ])
        return None
        
    def get_items(self, filter, channel):
        # cache this maybe?
        url = openhab_url + '/rest/items'
        r = requests.get(url, headers=headers)

        if not self.check_response(r, channel):
            return []
            
        filter = filter.lower()
        items = []

        for item in xml.fromstring(r.content).findall('item'):
            name = get_item_attr(item, 'name').lower()
            if filter is None or filter in name:
                items.append(item)

        return items

    def print_items(self, items, channel):
        output = ""
        maxtypelen = 0
        maxnamelen = 0

        # get the max name and type lengths so we can format our output nicely
        for item in items:
            name  = get_item_attr(item, 'name')
            type  = get_item_attr(item, 'type')
            if len(type) > maxtypelen:
                maxtypelen = len(type)
            if len(name) > maxnamelen:
                maxnamelen = len(name)

        for item in items:
            name  = get_item_attr(item, 'name')
            state = get_item_attr(item, 'state')
            type  = get_item_attr(item, 'type')
            output = output + "%s%s%s\n" % ( type.ljust( maxtypelen + 5 ), name.ljust( maxnamelen + 5 ), state )
            if len(output) >= 8000:
                output = output + "... (too much output, please specify a filter)"
                break

        self.outputs.append([ channel, "```%s```" % (output) ])


    def check_response(self, r, channel):
        # check our rest api call was successful
        if r.status_code == 200:
            return True
        if r.status_code == 201:
            return True

        # log the response code/reason back to our slack channel
        self.outputs.append([ channel, "```%d: %s```" % (r.status_code, r.reason) ])
        return False

def normalise_value(state):
    if state.lower() == "on":
        return "ON"
    if state.lower() == "off":
        return "OFF"
    if state.lower() == "open":
        return "OPEN"
    if state.lower() == "closed":
        return "CLOSED"

    return state

def get_command_text(channel, user, text):
    if channel == "" or channel is None:
        return None
    if user == "" or user is None:
        return None
    if text == "" or text is None:
        return None

    # check for a message directed at our bot
    user_tag = "<@%s>:" % (slackhab_user_id)
    if text.startswith(user_tag):
        return text[len(user_tag):]

    user_tag = "<@%s>" % (slackhab_user_id)
    if text.startswith(user_tag):
        return text[len(user_tag):]

    # check for a DM to our bot
    if channel.startswith("D"):
        return text

    return None

def get_item_names(items):
    return ", ".join(get_item_attr(item, 'name') for item in items)
        
def get_item_attr(item, attr):
    return item.find(attr).text

def print_debug(message):
    if debug:
        print message

curl http://localhost:8080/rest/items in the console brings up the item:

[(...){"link":"http://localhost:8080/rest/items/Binder_Vacation","state":"OFF","type":"Switch","name":"Binder_Vacation","label":"Urlaub","tags":[],"groupNames":["gBinder"]} (...)]

What do you see if you put http://<openhab-ip>:8080/rest/items in your browser? Looks like the XML parser is having trouble with the XML returned.

Hi Ben. I posted it above. Of course there are more items than this. But does “send” need this, too?

That is JSON, not XML. My script is expecting XML. I didn’t realise OH2 had changed the REST API format to JSON - sorry!!

You will need to update my script to parse the JSON (pretty easy in Python with some Googling).

I added a diff to your gist here that makes your excellent Slack integration work under openHAB 2 (parse JSON and not XML). The wiki still needs a bit of an update, though. :wink:

Awesome - thanks John - I will be sure to pick this up when I upgrade to OH2!!

That’s so great! Thanks @watou!!!
I’ll finish my docu over the next days - and will post it then.

Ben can you share you mqttwarn.ini ? My config won’t post to slack.

item file

Switch	Wohnzimmer		{ channel="hue:0100:xxxxxxxxxxx:1:brightness" }

String      VT_Notify_Trace                     { mqtt=">[broker:/openhab/notification/trace:state:*:default]" }
String      VT_Notify_Info                      { mqtt=">[broker:/openhab/notification/info:state:*:default]" }
String      VT_Notify_Alert                     { mqtt=">[broker:/openhab/notification/alert:state:*:default]" }
String      VT_Notify_Warn                      { mqtt=">[broker:/openhab/notification/warn:state:*:default]" }
String      VT_Notify_Alarm                     { mqtt=">[broker:/openhab/notification/alarm:state:*:default]" }

rule file

rule "Wohnzimmer Licht"
when
    Item Wohnzimmer changed
then
    VT_Notify_Alarm.postUpdate("The burglar alarm has been tripped!!")
end

mqttwarn.ini

[config:slack]
token = 'xoxb-xxxxxxxxxxxx-xxxxxxxxxxxx'
targets = {
                # #channel/@user        username,       icon
   'general'    : [ '#allgemein',               "openhab",      ':syringe:' ],
  }

[/openhab/notification/]
targets = slack:mqtt-client
format  = -->{name}<--

Got it working with this config on mqttwarn.ini
Dont forget to add “slack” on launch inside mqttwarn.ini !

[config:slack]
token = 'xoxb-xxxxxxxxxxxx-xxxxxxxxxxxx'
targets = {
              #  #channel/@user   username, icon
   'mqtt-client'  : [ '#allgemein',       "openhab",   ':hankey:' ]
  }

[/openhab/notification/]
targets = file:mylog, log:info

[#]
targets = slack:mqtt-client