From 7501b479c54d63ee1419c4d7bfc4550bb2d9a529 Mon Sep 17 00:00:00 2001 From: Lanket Date: Mon, 28 May 2018 23:18:01 +0300 Subject: [PATCH] =?UTF-8?q?=D0=95=D1=89=D0=B5=20=D0=BD=D0=B5=D0=B7=D0=B0?= =?UTF-8?q?=D0=BA=D0=BE=D0=BD=D1=87=D0=B5=D0=BD=D0=BD=D0=BE=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/mdmPiTerminal/mdmPiTerminal.class.php | 62 +++- modules/mdmPiTerminal/mpt_edit.inc.php | 6 +- modules/mdmPiTerminal/mpt_kw_edit.inc.php | 91 +++++ modules/mdmPiTerminal/mpt_kw_search.inc.php | 31 ++ modules/mdmPiTerminal/mpt_send.inc.php | 2 +- templates/mdmPiTerminal/action_admin.html | 73 +++- .../mdmPiTerminal/mpt_description_admin.html | 3 + templates/mdmPiTerminal/mpt_edit.html | 91 +++++ templates/mdmPiTerminal/mpt_kw_edit.html | 314 ++++++++++++++++++ .../mdmPiTerminal/mpt_kw_search_admin.html | 78 +++++ templates/mdmPiTerminal/mpt_search_admin.html | 19 -- 11 files changed, 728 insertions(+), 42 deletions(-) create mode 100644 modules/mdmPiTerminal/mpt_kw_edit.inc.php create mode 100644 modules/mdmPiTerminal/mpt_kw_search.inc.php create mode 100644 templates/mdmPiTerminal/mpt_description_admin.html create mode 100644 templates/mdmPiTerminal/mpt_kw_edit.html create mode 100644 templates/mdmPiTerminal/mpt_kw_search_admin.html diff --git a/modules/mdmPiTerminal/mdmPiTerminal.class.php b/modules/mdmPiTerminal/mdmPiTerminal.class.php index 9cfbf74..119d090 100644 --- a/modules/mdmPiTerminal/mdmPiTerminal.class.php +++ b/modules/mdmPiTerminal/mdmPiTerminal.class.php @@ -17,7 +17,7 @@ class mdmPiTerminal extends module { * @access private */ function mdmPiTerminal() { - $this->debug = 0; + $this->debug = 1; $this->name="mdmPiTerminal"; $this->title="MDM VoiceAssistant"; $this->module_category="<#LANG_SECTION_DEVICES#>"; @@ -44,6 +44,9 @@ function saveParams($data=1) { if (IsSet($this->tab)) { $p["tab"]=$this->tab; } + if (IsSet($this->data_source)) { + $p["data_source"]=$this->data_source; + } return parent::saveParams($p); } /** @@ -58,6 +61,7 @@ function getParams() { global $mode; global $view_mode; global $edit_mode; + global $data_source; global $tab; if (isset($id)) { $this->id=$id; @@ -71,6 +75,9 @@ function getParams() { if (isset($edit_mode)) { $this->edit_mode=$edit_mode; } + if (isset($data_source)) { + $this->data_source=$data_source; + } if (isset($tab)) { $this->tab=$tab; } @@ -100,6 +107,7 @@ function run() { $out['EDIT_MODE']=$this->edit_mode; $out['MODE']=$this->mode; $out['ACTION']=$this->action; + $out['DATA_SOURCE']=$this->data_source; $out['TAB']=$this->tab; $this->data=$out; $p=new parser(DIR_TEMPLATES.$this->name."/".$this->name.".html", $this->data, $this); @@ -139,8 +147,21 @@ function admin(&$out) { } if ($this->view_mode=='delete_mpt') { $this->delete_mpt($this->id); - $this->redirect("?"); + $this->redirect("?data_source=search_mpt"); + } + } + if ($this->data_source=='mpt_kw') { + if ($this->view_mode=='' || $this->view_mode=='search_mpt_kw') { + $this->search_mpt_kw($out); + } + if ($this->view_mode=='edit_mpt_kw') { + $this->edit_mpt_kw($out, $this->id); + } + if ($this->view_mode=='delete_mpt_kw') { + $this->delete_mpt_kw($this->id); + $this->redirect("?data_source=search_mpt_kw"); } + } } /** @@ -162,6 +183,14 @@ function search_mpt(&$out) { require(DIR_MODULES.$this->name.'/mpt_search.inc.php'); } /** +* mpt_kw search +* +* @access public +*/ + function search_mpt_kw(&$out) { + require(DIR_MODULES.$this->name.'/mpt_kw_search.inc.php'); + } +/** * mpt edit/add * * @access public @@ -170,6 +199,14 @@ function edit_mpt(&$out, $id) { require(DIR_MODULES.$this->name.'/mpt_edit.inc.php'); } /** +* mpt_kw edit/add +* +* @access public +*/ + function edit_mpt_kw(&$out, $id) { + require(DIR_MODULES.$this->name.'/mpt_edit_kw.inc.php'); + } +/** * mpt send data to terminal * * @access public @@ -187,6 +224,17 @@ function delete_mpt($id) { // some action for related tables SQLExec("DELETE FROM mpt WHERE ID='".$rec['ID']."'"); } +/** +* mpt_kw delete record +* +* @access public +*/ + function delete_mpt_kw($id) { + $rec=SQLSelectOne("SELECT * FROM mpt_kw WHERE ID='$id'"); + // some action for related tables + SQLExec("DELETE FROM mpt_kw WHERE ID='".$rec['ID']."'"); + } + function propertySetHandle($object, $property, $value) { $table='mpt'; $properties=SQLSelect("SELECT ID FROM $table WHERE LINKED_OBJECT LIKE '".DBSafe($object)."' AND LINKED_PROPERTY LIKE '".DBSafe($property)."'"); @@ -213,14 +261,14 @@ function targetToIp($target='') { if(!$target) return null; if (preg_match('/^[\d\.]+$/',$target)) { - if($this->debug == 1) debmes('mpt ttIp 1: ' . $target); + if($this->debug == 1) debmes('mpt ttIp ip: ' . $target); return $target; } else { $qry = "terminals.NAME LIKE '".DBSafe($target)."' OR terminals.TITLE LIKE '".DBSafe($target)."'"; $res = SQLSelectOne("SELECT terminals.HOST FROM `mpt` inner join terminals on mpt.ID_TERMINAL = terminals.ID where $qry"); - if($this->debug == 1) debmes('mpt ttIp 2: ' . $res['HOST']); + if($this->debug == 1) debmes('mpt ttIp name: ' . $res['HOST']); if(!res) return null; return $res['HOST']; } @@ -251,6 +299,7 @@ function uninstall() { unsubscribeFromEvent($this->name, 'SAYTO'); unsubscribeFromEvent($this->name, 'ASK'); SQLExec('DROP TABLE IF EXISTS mpt'); + SQLExec('DROP TABLE IF EXISTS mpt_kw'); parent::uninstall(); } /** @@ -276,6 +325,11 @@ function dbInstall($data) { mpt: ALARMKWACTIVATED BOOLEAN NOT NULL DEFAULT TRUE mpt: ALARMTTS BOOLEAN NOT NULL DEFAULT TRUE mpt: ALARMSTT BOOLEAN NOT NULL DEFAULT TRUE + + mpt_kw: ID int(10) unsigned NOT NULL auto_increment + mpt_kw: NAME varchar(50) NOT NULL + mpt_kw: SYSNAME varchar(20) NOT NULL + mpt_kw: ID_USERS int(10) NOT NULL EOD; parent::dbInstall($data); } diff --git a/modules/mdmPiTerminal/mpt_edit.inc.php b/modules/mdmPiTerminal/mpt_edit.inc.php index 1a56f3a..1bc0948 100644 --- a/modules/mdmPiTerminal/mpt_edit.inc.php +++ b/modules/mdmPiTerminal/mpt_edit.inc.php @@ -82,11 +82,11 @@ SQLUpdate($table_name, $rec); // update sql $tmp = SQLSelectOne('SELECT HOST FROM terminals where ID = ' . $rec['ID_TERMINAL']); $ip = $tmp['HOST']; - if($this->debug == 1) debmes('mpt: ' . $tmp['HOST']); + if($this->debug == 1) debmes('mpt edit: update assistanr settings: ' . $tmp['HOST']); $rec['IP_SERVER']=$_SERVER['SERVER_ADDR']; unset($rec['ID'],$rec['ID_TERMINAL']); $senddata = json_encode($rec); - if($this->debug == 1) debmes('mpt edit send: ' . $senddata); + if($this->debug == 1) debmes('mpt edit: send assistanr settings: ' . $senddata); $this->send_mpt('settings',$senddata,$ip); } else { $new_rec=1; @@ -96,7 +96,7 @@ $rec['IP_SERVER']=$_SERVER['SERVER_ADDR']; unset($rec['ID'],$rec['ID_TERMINAL']); $senddata = json_encode($rec); - if($this->debug == 1) debmes('mpt edit send: ' . $senddata); + if($this->debug == 1) debmes('mpt add new assistant: ' . $senddata); $this->send_mpt('settings',$senddata,$ip); } $out['OK']=1; diff --git a/modules/mdmPiTerminal/mpt_kw_edit.inc.php b/modules/mdmPiTerminal/mpt_kw_edit.inc.php new file mode 100644 index 0000000..07535ec --- /dev/null +++ b/modules/mdmPiTerminal/mpt_kw_edit.inc.php @@ -0,0 +1,91 @@ +owner->name=='panel') { + $out['CONTROLPANEL']=1; + } + $table_name='mpt_kw'; + $rec=SQLSelectOne("SELECT * FROM $table_name WHERE ID='$id'"); + if ($this->mode=='update') { + $ok=1; + + //options for 'ID_TERMINAL' (select) +/* global $id_terminal; + $rec['ID_TERMINAL'] = $id_terminal; + $qry = ''; + if($rec['ID']) $qry = " and ID <> " . $rec['ID']; + $findduble=SQLSelectOne("SELECT * FROM $table_name WHERE ID_TERMINAL='$id_terminal' $qry"); + // chech not empy terminal and mast no dubles + if($rec['ID_TERMINAL'] == '' or $findduble['ID']) + { + $out['ERR_ID_TERMINAL']=1; + $ok=0; + } +*/ + //updating '<%LANG_TITLE%>' (varchar, required) + + /* + global $title; + $rec['TITLE']=$title; + if ($rec['TITLE']=='') { + $out['ERR_TITLE']=1; + $ok=0; + } + //updating 'name' (varchar) + global $name; + $rec['NAME']=$name; + //updating 'linkedRoom' (varchar) + global $linkedroom; + $rec['LINKEDROOM']=$linkedroom; + //updating 'ip' (varchar) + global $ip; + $rec['IP']=$ip; + */ + + //UPDATING RECORD + if ($ok) { + if ($rec['ID']) { + SQLUpdate($table_name, $rec); // update sql + $tmp = SQLSelectOne('SELECT HOST FROM terminals where ID = ' . $rec['ID_TERMINAL']); + $ip = $tmp['HOST']; + if($this->debug == 1) debmes('mpt edit: update assistanr settings: ' . $tmp['HOST']); + $rec['IP_SERVER']=$_SERVER['SERVER_ADDR']; + unset($rec['ID'],$rec['ID_TERMINAL']); + $senddata = json_encode($rec); + if($this->debug == 1) debmes('mpt edit: send assistanr settings: ' . $senddata); + $this->send_mpt('settings',$senddata,$ip); + } else { + $new_rec=1; + $rec['ID']=SQLInsert($table_name, $rec); // adding new record + $tmp = SQLSelectOne('SELECT HOST FROM terminals where ID = ' . $rec['ID_TERMINAL']); + $ip = $tmp['HOST']; + $rec['IP_SERVER']=$_SERVER['SERVER_ADDR']; + unset($rec['ID'],$rec['ID_TERMINAL']); + $senddata = json_encode($rec); + if($this->debug == 1) debmes('mpt add new assistant: ' . $senddata); + $this->send_mpt('settings',$senddata,$ip); + } + $out['OK']=1; + } else { + $out['ERR']=1; + } + } + $tmp=SQLSelect("SELECT ID, TITLE as NAME FROM terminals ORDER BY NAME"); + $terminals_total=count($tmp); + for($terminals_i=0;$terminals_i<$terminals_total;$terminals_i++) { + $terminal_id_opt[$tmp[$terminals_i]['ID']]=$tmp[$terminals_i]['NAME']; + } + for($i=0;$i<$terminals_total;$i++) { + if ($rec['ID_TERMINAL']==$tmp[$i]['ID']) $tmp[$i]['SELECTED']=1; + } + $out['ID_TERMINAL_OPTIONS']=$tmp; + + if (is_array($rec)) { + foreach($rec as $k=>$v) { + if (!is_array($v)) { + $rec[$k]=htmlspecialchars($v); + } + } + } + outHash($rec, $out); diff --git a/modules/mdmPiTerminal/mpt_kw_search.inc.php b/modules/mdmPiTerminal/mpt_kw_search.inc.php new file mode 100644 index 0000000..6d110bc --- /dev/null +++ b/modules/mdmPiTerminal/mpt_kw_search.inc.php @@ -0,0 +1,31 @@ +owner->name=='panel') { + $out['CONTROLPANEL']=1; + } + $qry="1"; + // search filters + // QUERY READY + global $save_qry; + if ($save_qry) { + $qry=$session->data['mpt_kw_qry']; + } else { + $session->data['mpt_kw_qry']=$qry; + } + if (!$qry) $qry="1"; + $sortby_mpt_kw="ID DESC"; + $out['SORTBY']=$sortby_mpt_kw; + // SEARCH RESULTS + //$res=SQLSelect("SELECT * FROM mpt WHERE $qry ORDER BY ".$sortby_mpt); + $res=SQLSelect("SELECT * FROM `mpt_kw` WHERE $qry ORDER BY ".$sortby_mpt_kw); + if ($res[0]['ID']) { + //paging($res, 100, $out); // search result paging + $total=count($res); + for($i=0;$i<$total;$i++) { + // some action for every record if required + } + $out['RESULT']=$res; + } diff --git a/modules/mdmPiTerminal/mpt_send.inc.php b/modules/mdmPiTerminal/mpt_send.inc.php index e8b8407..30a0e1b 100644 --- a/modules/mdmPiTerminal/mpt_send.inc.php +++ b/modules/mdmPiTerminal/mpt_send.inc.php @@ -10,7 +10,7 @@ $service_port='7999'; $in= $command.':'.$data; - if($this->debug == 1) debmes('mpt send - ' . $in . '; to = ' . $target); + if($this->debug == 1) debmes('mpt send: ' . $in . '; to = ' . $target); $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if ($socket) { $result = socket_connect($socket, $target, $service_port); diff --git a/templates/mdmPiTerminal/action_admin.html b/templates/mdmPiTerminal/action_admin.html index ac1ff5e..b2f434d 100644 --- a/templates/mdmPiTerminal/action_admin.html +++ b/templates/mdmPiTerminal/action_admin.html @@ -1,17 +1,60 @@ - - [#if VIEW_MODE="search_mpt" || VIEW_MODE=""#] - [#inc mpt_search_admin.html#] - [#endif VIEW_MODE#] - - - [#if VIEW_MODE="edit_mpt"#] - [#inc mpt_edit.html#] - [#endif VIEW_MODE#] - - - [#if VIEW_MODE="view_mpt"#] - [#inc mpt_view.html#] - [#endif VIEW_MODE#] - + + [#if SET_DATASOURCE!="1"#] +   + + + +
+ +[#endif SET_DATASOURCE#] + + + [#if DATA_SOURCE=="mpt" || DATA_SOURCE==""#] + + [#if VIEW_MODE="search_mpt" || VIEW_MODE=""#] + [#inc mpt_search_admin.html#] + [#endif VIEW_MODE#] + + + [#if VIEW_MODE="edit_mpt"#] + [#inc mpt_edit.html#] + [#endif VIEW_MODE#] + + + [#if VIEW_MODE="view_mpt"#] + [#inc mpt_view.html#] + [#endif VIEW_MODE#] + +[#endif DATA_SOURCE#] + + + + [#if DATA_SOURCE=="mpt_kw"#] + + [#if VIEW_MODE="search_mpt_kw"] + [#inc mpt_kw_search_admin.html#] + [#endif VIEW_MODE#] + + + [#if VIEW_MODE="edit_mpt_kw"#] + [#inc mpt_kw_edit.html#] + [#endif VIEW_MODE#] + + + [#if VIEW_MODE="view_mpt_kw"#] + [#inc mpt_kw_view.html#] + [#endif VIEW_MODE#] + + [#endif DATA_SOURCE#] + + + [#if DATA_SOURCE=="description"#] + [#inc mpt_description_admin.html#] + [#endif DATA_SOURCE#] + \ No newline at end of file diff --git a/templates/mdmPiTerminal/mpt_description_admin.html b/templates/mdmPiTerminal/mpt_description_admin.html new file mode 100644 index 0000000..34d3450 --- /dev/null +++ b/templates/mdmPiTerminal/mpt_description_admin.html @@ -0,0 +1,3 @@ +

Для добавления в систему нового Голосового ассистента сначала надо добавить его в качестве обычного терминала. Это можно сделать в "Панель управления" -> "Настройки" -> "Терминалы"

+

Там надо указать ip адрес вашего Голосового ассистента, если хотите по ней слушать онлайн радио то поставьте галочку "может проигрывать медиа-контент" и выберите "Тип плеера" "MPD", "Порт доступа к плееру" "6600"

+

Самого Голосового ассистента можно сделать из недорогого одноплатника, например, Orange Pi Zero. Установив на него простой скрипт. Сам скрипт и его установка описаны на странице проекта в GitHub https://github.com/devoff/mdmPiTerminal

diff --git a/templates/mdmPiTerminal/mpt_edit.html b/templates/mdmPiTerminal/mpt_edit.html index 3e51328..160d4bb 100644 --- a/templates/mdmPiTerminal/mpt_edit.html +++ b/templates/mdmPiTerminal/mpt_edit.html @@ -209,7 +209,98 @@ + + +
+ +

+ <#LANG_ADD#> +

+ +
+ + [#if RESULT#] + + [#if PAGES#] + + + [#begin PREVPAGE#][#end PREVPAGE#] + + [#begin NEXTPAGE#][#end NEXTPAGE#] +
Pages: <<< + [#begin PAGES#] + [#if !SELECTED#][#else#][#endif#][#NUM#] + [#end PAGES#] + >>>
+ [#endif PAGES#] + + +
+ + + [#begin RESULT#] + + + + + + + [#end RESULT#] + +
+ + [#TITLE#] + + + + [#NAME#] + + + + [#HOST#] + + +
+ [#if "<#ACTION#>"=="admin"#] + + + [#endif ACTION#] +
+
+ + +
+ + + [#if PAGES#] + + + [#begin PREVPAGE#][#end PREVPAGE#] + + [#begin NEXTPAGE#][#end NEXTPAGE#] +
Pages: <<< + [#begin PAGES#] + [#if !SELECTED#][#else#][#endif#][#NUM#] + [#end PAGES#] + >>>
+ [#endif PAGES#] + + [#else RESULT#] +

+ <#LANG_NO_RECORDS_FOUND#> +

+ [#endif RESULT#] + +
+ + + + +

Здесь можно записать 3 образца своего ключевого слова. Для избегания ложных срабатываний лучше записать словосочетание из двух слов и более. Для лучшего качества срабатывания лучше записывать с тем микрофоном, который будет использоваться для распознавания. Говорить надо в микрофон на терминале.


Запись первого образца ключевого слова

diff --git a/templates/mdmPiTerminal/mpt_kw_edit.html b/templates/mdmPiTerminal/mpt_kw_edit.html new file mode 100644 index 0000000..a41d3ac --- /dev/null +++ b/templates/mdmPiTerminal/mpt_kw_edit.html @@ -0,0 +1,314 @@ + + + + +
+ [#if OK#] +
<#LANG_DATA_SAVED#>
+ [#endif OK#] + [#if ERR#] +
<#LANG_FILLOUT_REQURED#>
+ [#endif ERR#] +
+ [#if ID=""#] + <#LANG_NEW_RECORD#> + [#endif ID#] + + + [#if !IS_SET_ID_TERMINAL#] +
+ +
+ + +
+
+ [#endif IS_SET_ID_TERMINAL#] + + + + +
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
+
+ [#if ID!=""#] + + [#else ID#] + + [#endif ID#] + <#LANG_CANCEL#> + + + + +
+
+
+
+ + + + +

+ <#LANG_ADD#> +

+ +
+ + [#if RESULT#] + + [#if PAGES#] + + + [#begin PREVPAGE#][#end PREVPAGE#] + + [#begin NEXTPAGE#][#end NEXTPAGE#] +
Pages: <<< + [#begin PAGES#] + [#if !SELECTED#][#else#][#endif#][#NUM#] + [#end PAGES#] + >>>
+ [#endif PAGES#] + + +
+ + + [#begin RESULT#] + + + + + + + [#end RESULT#] + +
+ + [#TITLE#] + + + + [#NAME#] + + + + [#HOST#] + + +
+ [#if "<#ACTION#>"=="admin"#] + + + [#endif ACTION#] +
+
+ + +
+ + + [#if PAGES#] + + + [#begin PREVPAGE#][#end PREVPAGE#] + + [#begin NEXTPAGE#][#end NEXTPAGE#] +
Pages: <<< + [#begin PAGES#] + [#if !SELECTED#][#else#][#endif#][#NUM#] + [#end PAGES#] + >>>
+ [#endif PAGES#] + + [#else RESULT#] +

+ <#LANG_NO_RECORDS_FOUND#> +

+ [#endif RESULT#] + +
+ + + + + +

Здесь можно записать 3 образца своего ключевого слова. Для избегания ложных срабатываний лучше записать словосочетание из двух слов и более. Для лучшего качества срабатывания лучше записывать с тем микрофоном, который будет использоваться для распознавания. Говорить надо в микрофон на терминале.

+
+

Запись первого образца ключевого слова

+ + + +
+

Запись второго образца ключевого слова

+ + + +
+

Запись третьего образца ключевого слова

+ + + +
+

Последний этап тренировки ключевого слова надо сгенерить служебный файл из записанных образцов по которому и будет работать распознавание ключевого слова.

+ diff --git a/templates/mdmPiTerminal/mpt_kw_search_admin.html b/templates/mdmPiTerminal/mpt_kw_search_admin.html new file mode 100644 index 0000000..3cf023f --- /dev/null +++ b/templates/mdmPiTerminal/mpt_kw_search_admin.html @@ -0,0 +1,78 @@ + +

+ <#LANG_ADD#> +

+ +
+ + [#if RESULT#] + + [#if PAGES#] + + + [#begin PREVPAGE#][#end PREVPAGE#] + + [#begin NEXTPAGE#][#end NEXTPAGE#] +
Pages: <<< + [#begin PAGES#] + [#if !SELECTED#][#else#][#endif#][#NUM#] + [#end PAGES#] + >>>
+ [#endif PAGES#] + + +
+ + + [#begin RESULT#] + + + + + + + [#end RESULT#] + +
+ + [#NAME#] + + + + [#SYSNAME#] + + +
+ [#if "<#ACTION#>"=="admin"#] + + + [#endif ACTION#] +
+
+ + +
+ + + [#if PAGES#] + + + [#begin PREVPAGE#][#end PREVPAGE#] + + [#begin NEXTPAGE#][#end NEXTPAGE#] +
Pages: <<< + [#begin PAGES#] + [#if !SELECTED#][#else#][#endif#][#NUM#] + [#end PAGES#] + >>>
+ [#endif PAGES#] + + [#else RESULT#] +

+ <#LANG_NO_RECORDS_FOUND#> +

+ [#endif RESULT#] + +
diff --git a/templates/mdmPiTerminal/mpt_search_admin.html b/templates/mdmPiTerminal/mpt_search_admin.html index 07eb47a..1f8521f 100644 --- a/templates/mdmPiTerminal/mpt_search_admin.html +++ b/templates/mdmPiTerminal/mpt_search_admin.html @@ -1,12 +1,3 @@ - - -
-
-
-

<#LANG_ADD#> @@ -90,13 +81,3 @@ [#endif RESULT#] -

-
-

Для добавления в систему нового Голосового ассистента сначала надо добавить его в качестве обычного терминала. Это можно сделать в "Панель управления" -> "Настройки" -> "Терминалы"

-

Там надо указать ip адрес вашего Голосового ассистента, если хотите по ней слушать онлайн радио то поставьте галочку "может проигрывать медиа-контент" и выберите "Тип плеера" "MPD", "Порт доступа к плееру" "6600"

-

Самого Голосового ассистента можно сделать из недорогого одноплатника, например, Orange Pi Zero. Установив на него простой скрипт. Сам скрипт и его установка описаны на странице проекта в GitHub https://github.com/devoff/mdmPiTerminal

-
-
-