A mqtt sniffer
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import argparse
  2. try:
  3. import bottombar as bb
  4. except ModuleNotFoundError:
  5. bb = None
  6. try:
  7. from console_bottombar import BottomBar
  8. except ModuleNotFoundError:
  9. BottomBar = None
  10. import getpass
  11. import json
  12. import mqtt
  13. import os
  14. import re
  15. import time
  16. VERSION = "0.2.0"
  17. logfile = None
  18. HELPTEXT = """
  19. F1: Get this help message
  20. F2: Set a filter (regular expression) for the topic of a message
  21. Examples:
  22. * "/gfw/.*/main_light/" to get everything with "/gfw/" before "/main_light/"
  23. * "^zigbee.*(?>!logging)$" to get everything starting with "zigbee" and not ending with "logging"
  24. * "^(?!shellies).*/dirk/.*temperature$" to get everything not starting with "shellies" followed by "/dirk/" and ends with "temperature"
  25. F9: Start / Stop logging to mqtt-sniffer.log
  26. F12: Quit the mqtt sniffer
  27. 'c': Clear screen
  28. 'q': Quit
  29. """
  30. def msg_print_log(message, topic_regex, log2file):
  31. global logfile
  32. try:
  33. match = len(re.findall(topic_regex, message.topic)) > 0
  34. except re.error:
  35. print('No valid regular expression (%s). No filter active.' % topic_regex)
  36. match = True
  37. data = None
  38. try:
  39. data = json.loads(message.payload)
  40. except:
  41. pass
  42. try:
  43. data = message.payload.decode("utf-8")
  44. except:
  45. data = message.payload
  46. if match:
  47. print("%25s::%75s::%s" % (time.asctime(), message.topic, data))
  48. if log2file:
  49. if logfile is None:
  50. logfile = open('mqtt_sniffer.log', 'w')
  51. logfile.write("%25s::%s::%s\n" % (time.asctime(), message.topic, data))
  52. logfile.flush()
  53. def rx_mqtt(mc, userdata, message):
  54. global my_bb
  55. global args
  56. if BottomBar is not None and bb is not None:
  57. msg_print_log(message, my_bb.get_entry('msg_re'), my_bb.get_entry('log2file'))
  58. bb.redraw()
  59. else:
  60. msg_print_log(message, args.topicfilter, args.logtofile)
  61. if __name__ == "__main__":
  62. parser = argparse.ArgumentParser(description='This is a mqtt sniffer.')
  63. parser.add_argument('-f', dest='hostname', default='localhost', help='Hostname of the mqtt server')
  64. parser.add_argument('-p', dest='port', default=1883, type=int, help='Port of the mqtt server')
  65. parser.add_argument('-n', dest='no_credentials', action='store_true', help='Avoid asking for credentials')
  66. parser.add_argument('-u', dest='username', default=None, help='Set username for mqtt server')
  67. parser.add_argument('-t', dest='topicfilter', default="", help='Set topic filter')
  68. parser.add_argument('-l', dest='logtofile', action='store_true', help='Enable logging to file')
  69. args = parser.parse_args()
  70. if not args.no_credentials:
  71. if args.username == None:
  72. args.username = input("Username: ")
  73. password = getpass.getpass(prompt='Password: ', stream=None)
  74. else:
  75. args.username = None
  76. password = None
  77. if BottomBar != None:
  78. my_bb = BottomBar(VERSION, label='MQTT-Sniffer')
  79. my_bb.add_entry('help', 1, my_bb.FUNC_INFO, label='[F1] Help', infotext=HELPTEXT)
  80. my_bb.add_entry('msg_re', 2, my_bb.FUNC_TEXT, label='[F2] Filter', default=args.topicfilter)
  81. my_bb.add_entry('quit', 12, my_bb.FUNC_QUIT, "Quit", label='[F12]', right=True)
  82. my_bb.add_entry('log2file', 9, my_bb.FUNC_BOOL, label='[F9] Log2File', default=args.logtofile, right=True)
  83. mc = mqtt.mqtt_client("mqtt_sniffer", args.hostname, port=args.port, username=args.username, password=password)
  84. mc.add_callback("#", rx_mqtt)
  85. if BottomBar != None:
  86. my_bb.run()
  87. else:
  88. while True:
  89. time.sleep(1)