Module spotify_state -> mqtt
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

spotify.py 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import config
  2. import logging
  3. import mqtt
  4. import report
  5. import socket
  6. import subprocess
  7. import time
  8. import spotipy
  9. from spotipy.oauth2 import SpotifyClientCredentials
  10. import config
  11. import json
  12. try:
  13. from config import APP_NAME as ROOT_LOGGER_NAME
  14. except ImportError:
  15. ROOT_LOGGER_NAME = 'root'
  16. logger = logging.getLogger(ROOT_LOGGER_NAME).getChild('main')
  17. mc = mqtt.mqtt_client(config.APP_NAME, config.MQTT_SERVER, 1883, config.MQTT_USER, config.MQTT_PASS)
  18. class librespot(object):
  19. ON_CMD = ['play', ]
  20. OFF_CMD = ['pause', 'stop', ]
  21. def __init__(self, state_callback, title_callback):
  22. logger.info("Starting Librespot...")
  23. self.__state_callback__ = state_callback
  24. self.__title_callback__ = title_callback
  25. self.__start_process__()
  26. self.__state__ = None
  27. self.__preload_state__ = False
  28. self.__title__ = None
  29. self.__title_preload__ = None
  30. self.__title_published__ = None
  31. self.set_state(False)
  32. self.set_title("")
  33. def __start_process__(self):
  34. self.__process__ = subprocess.Popen(["librespot", "-v", "--name", config.DEVICE_NAME],
  35. shell=False,
  36. # We pipe the output to an internal pipe
  37. stdout=subprocess.PIPE,
  38. stderr=subprocess.STDOUT)
  39. def run(self):
  40. while True:
  41. output = self.__process__.stdout.readline()
  42. # Polling returns None when the program is still running, return_code otherwise
  43. return_code = self.__process__.poll()
  44. if return_code is not None:
  45. #self.__process__.close()
  46. # Program ended, get exit/return code
  47. #raise RuntimeError
  48. logger.exception(("Command '{}' finished with exit code {}".format(command, return_code)))
  49. # If the output is not empty, feed it to the function, strip the newline first
  50. self.__start_process__()
  51. output = None
  52. elif output:
  53. out_txt = output.decode('utf-8').strip('\n').strip()
  54. out_txt = out_txt[out_txt.find(']') + 2:]
  55. #logger.debug("librespot output: %s", out_txt)
  56. if out_txt.lower().startswith("loading"):
  57. logger.debug("librespot: %s", out_txt)
  58. title = out_txt[out_txt.index("<") + 1:out_txt.index(">")]
  59. if self.__preload_state__:
  60. self.__title_preload__ = title
  61. logger.info("Upcomming Title %s identified", title)
  62. else:
  63. self.__title__ = title
  64. logger.info("Current Title %s identified", title)
  65. if "command=" in out_txt:
  66. command = out_txt[out_txt.find('command=') + 8:].strip().lower()
  67. logger.debug("librespot command: %s", command)
  68. if command.startswith("preload"):
  69. self.__preload_state__ = True
  70. if command.startswith("load"):
  71. self.set_state(command.split(',')[2].strip() == 'true')
  72. #
  73. self.__preload_state__ = False
  74. if self.__title_preload__ is not None:
  75. self.__title__ = self.__title_preload__
  76. self.__title_preload__ = None
  77. #
  78. elif command in self.ON_CMD:
  79. self.set_state(True)
  80. elif command in self.OFF_CMD:
  81. self.set_state(False)
  82. if self.__state__:
  83. self.set_title(self.__title__)
  84. else:
  85. self.set_title("")
  86. def set_state(self, target_state):
  87. if target_state != self.__state__:
  88. self.__state__ = target_state
  89. logger.info("spotify state changed to %s", self.__state__)
  90. self.__state_callback__(self.__state__)
  91. def set_title(self, title):
  92. if self.__title_published__ != title:
  93. self.__title_published__= title
  94. logger.info("spotify title changed to \"%s\"", title)
  95. self.__title_callback__(title)
  96. def send_state_msg_mqtt(state):
  97. topic = config.MQTT_TOPIC + "/state"
  98. logger.info("Sending Spotify status information to mqtt %s = %s", topic, str(state))
  99. mc.send(topic, "true" if state else "false")
  100. def send_title_msg_mqtt(title):
  101. topic = config.MQTT_TOPIC + "/title"
  102. logger.info("Sending Spotify status information to mqtt %s = %s", topic, title)
  103. mc.send(topic, title)
  104. if __name__ == '__main__':
  105. report.appLoggingConfigure(config.__BASEPATH__, config.LOGTARGET, ((config.APP_NAME, config.LOGLVL), ), fmt=config.formatter, host=config.LOGHOST, port=config.LOGPORT)
  106. ls = librespot(send_state_msg_mqtt, send_title_msg_mqtt)
  107. ls.run()