Module spotify_state -> mqtt
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

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