v0.8.950
This commit is contained in:
@@ -4,28 +4,35 @@ import logging
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
from homeassistant.components import media_source
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
VERSION = '0.8.933'
|
VERSION = '0.8.950'
|
||||||
|
|
||||||
DOMAIN = "yoradio"
|
DOMAIN = "yoradio"
|
||||||
|
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
|
|
||||||
|
from homeassistant.components.media_player.browse_media import (
|
||||||
|
async_process_play_media_url,
|
||||||
|
)
|
||||||
from homeassistant.components.media_player import (
|
from homeassistant.components.media_player import (
|
||||||
MediaPlayerEntity,
|
MediaPlayerEntity,
|
||||||
|
MediaPlayerEnqueue,
|
||||||
|
BrowseMedia,
|
||||||
PLATFORM_SCHEMA
|
PLATFORM_SCHEMA
|
||||||
)
|
)
|
||||||
|
|
||||||
from homeassistant.components.media_player.const import (
|
from homeassistant.components.media_player.const import (
|
||||||
MEDIA_TYPE_MUSIC,
|
MEDIA_TYPE_MUSIC,
|
||||||
|
MEDIA_TYPE_URL,
|
||||||
SUPPORT_TURN_ON, SUPPORT_TURN_OFF,
|
SUPPORT_TURN_ON, SUPPORT_TURN_OFF,
|
||||||
SUPPORT_VOLUME_STEP, SUPPORT_VOLUME_SET,
|
SUPPORT_VOLUME_STEP, SUPPORT_VOLUME_SET,
|
||||||
SUPPORT_PAUSE, SUPPORT_PLAY, SUPPORT_STOP,
|
SUPPORT_PAUSE, SUPPORT_PLAY, SUPPORT_STOP,
|
||||||
SUPPORT_PREVIOUS_TRACK, SUPPORT_NEXT_TRACK,
|
SUPPORT_PREVIOUS_TRACK, SUPPORT_NEXT_TRACK,
|
||||||
SUPPORT_SELECT_SOURCE
|
SUPPORT_SELECT_SOURCE, SUPPORT_BROWSE_MEDIA, SUPPORT_PLAY_MEDIA
|
||||||
)
|
)
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
@@ -38,7 +45,7 @@ from homeassistant.const import (
|
|||||||
SUPPORT_YORADIO = SUPPORT_PAUSE | SUPPORT_PLAY | SUPPORT_STOP |\
|
SUPPORT_YORADIO = SUPPORT_PAUSE | SUPPORT_PLAY | SUPPORT_STOP |\
|
||||||
SUPPORT_VOLUME_SET | SUPPORT_VOLUME_STEP | \
|
SUPPORT_VOLUME_SET | SUPPORT_VOLUME_STEP | \
|
||||||
SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | \
|
SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | \
|
||||||
SUPPORT_SELECT_SOURCE
|
SUPPORT_SELECT_SOURCE | SUPPORT_BROWSE_MEDIA | SUPPORT_PLAY_MEDIA
|
||||||
|
|
||||||
DEFAULT_NAME = 'yoRadio'
|
DEFAULT_NAME = 'yoRadio'
|
||||||
CONF_MAX_VOLUME = 'max_volume'
|
CONF_MAX_VOLUME = 'max_volume'
|
||||||
@@ -88,6 +95,12 @@ class yoradioApi():
|
|||||||
except:
|
except:
|
||||||
await self.mqtt.async_publish(self.hass, self.root_topic + '/command', command)
|
await self.mqtt.async_publish(self.hass, self.root_topic + '/command', command)
|
||||||
|
|
||||||
|
async def set_browse_media(self, media_content_id):
|
||||||
|
try:
|
||||||
|
self.mqtt.async_publish(self.root_topic + '/command', media_content_id)
|
||||||
|
except:
|
||||||
|
await self.mqtt.async_publish(self.hass, self.root_topic + '/command', media_content_id)
|
||||||
|
|
||||||
async def load_playlist(self, msg):
|
async def load_playlist(self, msg):
|
||||||
try:
|
try:
|
||||||
async with aiohttp.ClientSession() as session:
|
async with aiohttp.ClientSession() as session:
|
||||||
@@ -186,6 +199,32 @@ class yoradioDevice(MediaPlayerEntity):
|
|||||||
def source_list(self):
|
def source_list(self):
|
||||||
return self.api.playlist
|
return self.api.playlist
|
||||||
|
|
||||||
|
async def async_browse_media(
|
||||||
|
self, media_content_type: str | None = None, media_content_id: str | None = None
|
||||||
|
) -> BrowseMedia:
|
||||||
|
#await self.api.set_browse_media(media_content_id)
|
||||||
|
"""Implement the websocket media browsing helper."""
|
||||||
|
return await media_source.async_browse_media(
|
||||||
|
self.hass,
|
||||||
|
media_content_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_play_media(
|
||||||
|
self,
|
||||||
|
media_type: str,
|
||||||
|
media_id: str,
|
||||||
|
enqueue: MediaPlayerEnqueue | None = None,
|
||||||
|
announce: bool | None = None, **kwargs
|
||||||
|
) -> None:
|
||||||
|
"""Play a piece of media."""
|
||||||
|
if media_source.is_media_source_id(media_id):
|
||||||
|
media_type = MEDIA_TYPE_URL
|
||||||
|
play_item = await media_source.async_resolve_media(self.hass, media_id, self.entity_id)
|
||||||
|
media_id = async_process_play_media_url(self.hass, play_item.url)
|
||||||
|
if media_type in (MEDIA_TYPE_URL):
|
||||||
|
media_id = async_process_play_media_url(self.hass, media_id)
|
||||||
|
await self.api.set_browse_media(media_id)
|
||||||
|
|
||||||
async def async_select_source(self, source):
|
async def async_select_source(self, source):
|
||||||
await self.api.set_source(source)
|
await self.api.set_source(source)
|
||||||
self._current_source = source
|
self._current_source = source
|
||||||
|
|||||||
@@ -223,6 +223,9 @@ Work is in progress...
|
|||||||
|
|
||||||
---
|
---
|
||||||
## Version history
|
## Version history
|
||||||
|
#### v0.8.950
|
||||||
|
- added support for remote media playback from Home Assistant (Local Media, Radio Browser, TTS)
|
||||||
|
|
||||||
#### v0.8.933 (homeassistant component)
|
#### v0.8.933 (homeassistant component)
|
||||||
- HA component >> fixed bugs of getting and generating a playlist
|
- HA component >> fixed bugs of getting and generating a playlist
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "mqtt.h"
|
#include "mqtt.h"
|
||||||
|
|
||||||
#ifdef MQTT_HOST
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
#include "WiFi.h"
|
#include "WiFi.h"
|
||||||
|
|
||||||
#include "telnet.h"
|
#include "telnet.h"
|
||||||
@@ -122,6 +122,12 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
|
|||||||
player.request.doSave = true;
|
player.request.doSave = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (strstr(buf, "http")==buf){
|
||||||
|
Serial.println(payload);
|
||||||
|
if(len+1>sizeof(player.burl)) return;
|
||||||
|
strlcpy(player.burl, payload, len+1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ifdef MQTT_HOST
|
#endif // #ifdef MQTT_ROOT_TOPIC
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ void handleHTTPArgs(AsyncWebServerRequest * request);
|
|||||||
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len);
|
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len);
|
||||||
|
|
||||||
bool shouldReboot = false;
|
bool shouldReboot = false;
|
||||||
#ifdef MQTT_HOST
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
Ticker mqttplaylistticker;
|
Ticker mqttplaylistticker;
|
||||||
bool mqttplaylistblock = false;
|
bool mqttplaylistblock = false;
|
||||||
void mqttplaylistSend() {
|
void mqttplaylistSend() {
|
||||||
@@ -231,7 +231,7 @@ void NetServer::processQueue(){
|
|||||||
}
|
}
|
||||||
if (strlen(wsbuf) > 0) {
|
if (strlen(wsbuf) > 0) {
|
||||||
if (clientId == 0) { websocket.textAll(wsbuf); }else{ websocket.text(clientId, wsbuf); }
|
if (clientId == 0) { websocket.textAll(wsbuf); }else{ websocket.text(clientId, wsbuf); }
|
||||||
#ifdef MQTT_HOST
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
if (clientId == 0 && (request.type == STATION || request.type == ITEM || request.type == TITLE || request.type == MODE)) mqttPublishStatus();
|
if (clientId == 0 && (request.type == STATION || request.type == ITEM || request.type == TITLE || request.type == MODE)) mqttPublishStatus();
|
||||||
if (clientId == 0 && request.type == VOLUME) mqttPublishVolume();
|
if (clientId == 0 && request.type == VOLUME) mqttPublishVolume();
|
||||||
#endif
|
#endif
|
||||||
@@ -548,7 +548,7 @@ void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t client
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (strcmp(cmd, "submitplaylistdone") == 0) {
|
if (strcmp(cmd, "submitplaylistdone") == 0) {
|
||||||
#ifdef MQTT_HOST
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
//mqttPublishPlaylist();
|
//mqttPublishPlaylist();
|
||||||
mqttplaylistticker.attach(5, mqttplaylistSend);
|
mqttplaylistticker.attach(5, mqttplaylistSend);
|
||||||
#endif
|
#endif
|
||||||
@@ -679,7 +679,7 @@ void handleHTTPArgs(AsyncWebServerRequest * request) {
|
|||||||
if (request->method() == HTTP_GET) {
|
if (request->method() == HTTP_GET) {
|
||||||
DBGVB("[%s] client ip=%s request of %s", __func__, request->client()->remoteIP().toString().c_str(), request->url().c_str());
|
DBGVB("[%s] client ip=%s request of %s", __func__, request->client()->remoteIP().toString().c_str(), request->url().c_str());
|
||||||
if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 || strcmp(request->url().c_str(), SSIDS_PATH) == 0 || strcmp(request->url().c_str(), INDEX_PATH) == 0 || strcmp(request->url().c_str(), TMP_PATH) == 0 || strcmp(request->url().c_str(), PLAYLIST_SD_PATH) == 0 || strcmp(request->url().c_str(), INDEX_SD_PATH) == 0) {
|
if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 || strcmp(request->url().c_str(), SSIDS_PATH) == 0 || strcmp(request->url().c_str(), INDEX_PATH) == 0 || strcmp(request->url().c_str(), TMP_PATH) == 0 || strcmp(request->url().c_str(), PLAYLIST_SD_PATH) == 0 || strcmp(request->url().c_str(), INDEX_SD_PATH) == 0) {
|
||||||
#ifdef MQTT_HOST
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0) while (mqttplaylistblock) vTaskDelay(5);
|
if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0) while (mqttplaylistblock) vTaskDelay(5);
|
||||||
#endif
|
#endif
|
||||||
if(strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 && config.store.play_mode==PM_SDCARD){
|
if(strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 && config.store.play_mode==PM_SDCARD){
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef options_h
|
#ifndef options_h
|
||||||
#define options_h
|
#define options_h
|
||||||
|
|
||||||
#define YOVERSION "0.8.933"
|
#define YOVERSION "0.8.950"
|
||||||
|
|
||||||
/*******************************************************
|
/*******************************************************
|
||||||
DO NOT EDIT THIS FILE.
|
DO NOT EDIT THIS FILE.
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ Player player;
|
|||||||
|
|
||||||
void Player::init() {
|
void Player::init() {
|
||||||
Serial.print("##[BOOT]#\tplayer.init\t");
|
Serial.print("##[BOOT]#\tplayer.init\t");
|
||||||
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
|
memset(burl, 0, 400);
|
||||||
|
#endif
|
||||||
if(MUTE_PIN!=255) pinMode(MUTE_PIN, OUTPUT);
|
if(MUTE_PIN!=255) pinMode(MUTE_PIN, OUTPUT);
|
||||||
#if I2S_DOUT!=255
|
#if I2S_DOUT!=255
|
||||||
#if !I2S_INTERNAL
|
#if !I2S_INTERNAL
|
||||||
@@ -124,6 +127,11 @@ void Player::loop() {
|
|||||||
volTimer=false;
|
volTimer=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
|
if(strlen(burl)>0){
|
||||||
|
browseUrl();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::zeroRequest() {
|
void Player::zeroRequest() {
|
||||||
@@ -165,6 +173,30 @@ void Player::play(uint16_t stationId, uint32_t filePos) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
|
void Player::browseUrl(){
|
||||||
|
resumeAfterUrl = mode==PLAYING;
|
||||||
|
display.putRequest(PSTOP);
|
||||||
|
setDefaults();
|
||||||
|
setOutputPins(false);
|
||||||
|
config.setTitle(const_PlConnect);
|
||||||
|
netserver.requestOnChange(TITLE, 0);
|
||||||
|
if (connecttohost(burl)){
|
||||||
|
mode = PLAYING;
|
||||||
|
config.setTitle("");
|
||||||
|
netserver.requestOnChange(TITLE, 0);
|
||||||
|
netserver.requestOnChange(MODE, 0);
|
||||||
|
setOutputPins(true);
|
||||||
|
requestToStart = true;
|
||||||
|
display.putRequest(PSTART);
|
||||||
|
if (player_on_start_play) player_on_start_play();
|
||||||
|
}else{
|
||||||
|
telnet.printf("##ERROR#:\tError connecting to %s\n", burl);
|
||||||
|
}
|
||||||
|
memset(burl, 0, 400);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void Player::prev() {
|
void Player::prev() {
|
||||||
if(config.store.play_mode==PM_WEB || !config.sdSnuffle){
|
if(config.store.play_mode==PM_WEB || !config.sdSnuffle){
|
||||||
if (config.store.lastStation == 1) config.store.lastStation = config.store.countStation; else config.store.lastStation--;
|
if (config.store.lastStation == 1) config.store.lastStation = config.store.countStation; else config.store.lastStation--;
|
||||||
|
|||||||
@@ -27,13 +27,20 @@ class Player: public Audio {
|
|||||||
void zeroRequest();
|
void zeroRequest();
|
||||||
SemaphoreHandle_t playmutex=NULL;
|
SemaphoreHandle_t playmutex=NULL;
|
||||||
bool lockOutput = true;
|
bool lockOutput = true;
|
||||||
|
bool resumeAfterUrl = false;
|
||||||
uint32_t sd_min, sd_max;
|
uint32_t sd_min, sd_max;
|
||||||
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
|
char burl[400]; /* buffer for browseUrl */
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
Player();
|
Player();
|
||||||
void init();
|
void init();
|
||||||
void loop();
|
void loop();
|
||||||
void initHeaders(const char *file);
|
void initHeaders(const char *file);
|
||||||
void play(uint16_t stationId, uint32_t filePos=0);
|
void play(uint16_t stationId, uint32_t filePos=0);
|
||||||
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
|
void browseUrl();
|
||||||
|
#endif
|
||||||
void stop(const char *nttl = NULL);
|
void stop(const char *nttl = NULL);
|
||||||
void prev();
|
void prev();
|
||||||
void next();
|
void next();
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ void setup() {
|
|||||||
initControls();
|
initControls();
|
||||||
display.putRequest(DSP_START);
|
display.putRequest(DSP_START);
|
||||||
while(!display.ready()) delay(10);
|
while(!display.ready()) delay(10);
|
||||||
#ifdef MQTT_HOST
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
mqttInit();
|
mqttInit();
|
||||||
#endif
|
#endif
|
||||||
if (config.store.play_mode==PM_SDCARD) player.initHeaders(config.station.url);
|
if (config.store.play_mode==PM_SDCARD) player.initHeaders(config.station.url);
|
||||||
@@ -87,7 +87,7 @@ void checkConnection(){
|
|||||||
display.putRequest(NEWMODE, PLAYER);
|
display.putRequest(NEWMODE, PLAYER);
|
||||||
if (playing) player.request.station = config.store.lastStation;
|
if (playing) player.request.station = config.store.lastStation;
|
||||||
checkMillis = millis();
|
checkMillis = millis();
|
||||||
#ifdef MQTT_HOST
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
connectToMqtt();
|
connectToMqtt();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -142,6 +142,9 @@ void audio_showstation(const char *info) {
|
|||||||
bool p = printable(info);
|
bool p = printable(info);
|
||||||
config.setTitle(p?info:config.station.name);
|
config.setTitle(p?info:config.station.name);
|
||||||
netserver.requestOnChange(TITLE, 0);
|
netserver.requestOnChange(TITLE, 0);
|
||||||
|
config.setStation(p?info:config.station.name);
|
||||||
|
display.putRequest(NEWSTATION);
|
||||||
|
netserver.requestOnChange(STATION, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,6 +201,7 @@ void audio_id3data(const char *info){ //id3 metadata
|
|||||||
if(player.lockOutput) return;
|
if(player.lockOutput) return;
|
||||||
telnet.printf("##AUDIO.ID3#: %s\n", info);
|
telnet.printf("##AUDIO.ID3#: %s\n", info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_eof_mp3(const char *info){ //end of file
|
void audio_eof_mp3(const char *info){ //end of file
|
||||||
config.sdResumePos = 0;
|
config.sdResumePos = 0;
|
||||||
if(config.sdSnuffle){
|
if(config.sdSnuffle){
|
||||||
@@ -206,6 +210,17 @@ void audio_eof_mp3(const char *info){ //end of file
|
|||||||
player.next();
|
player.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void audio_eof_stream(const char *info){
|
||||||
|
player.stop();
|
||||||
|
if(!player.resumeAfterUrl) return;
|
||||||
|
if (config.store.play_mode==PM_WEB){
|
||||||
|
player.play(config.store.lastStation);
|
||||||
|
}else{
|
||||||
|
player.play(config.store.lastStation, config.sdResumePos==0?0:config.sdResumePos-player.sd_min);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void audio_progress(uint32_t startpos, uint32_t endpos){
|
void audio_progress(uint32_t startpos, uint32_t endpos){
|
||||||
player.sd_min = startpos;
|
player.sd_min = startpos;
|
||||||
player.sd_max = endpos;
|
player.sd_max = endpos;
|
||||||
|
|||||||
Reference in New Issue
Block a user