001package com.aispeech.dui.dds.agent.wakeup;
002
003import android.text.TextUtils;
004
005import com.aispeech.dui.BaseNode;
006import com.aispeech.dui.BusClient;
007import com.aispeech.dui.dds.DDS;
008import com.aispeech.dui.dds.agent.Agent;
009import com.aispeech.dui.dds.agent.wakeup.cb.BfListener;
010import com.aispeech.dui.dds.agent.wakeup.cb.VoipListener;
011import com.aispeech.dui.dds.agent.wakeup.word.HotWords;
012import com.aispeech.dui.dds.agent.wakeup.word.IncrementWakeupType;
013import com.aispeech.dui.dds.agent.wakeup.word.WakeupPriorityType;
014import com.aispeech.dui.dds.agent.wakeup.word.WakeupWord;
015import com.aispeech.dui.dds.agent.wakeup.word.WakeupWordIntent;
016import com.aispeech.dui.dds.agent.wakeup.word.WordProxy;
017import com.aispeech.dui.dds.exceptions.DDSNotInitCompleteException;
018import com.aispeech.dui.manager.AILog;
019import com.aispeech.libbase.bussiness.JSONObjectUtil;
020import com.aispeech.libcomm.business.LocalKeys;
021import com.aispeech.libcomm.business.LocalKeysConfigUtil;
022import com.aispeech.libcomm.business.LocalKeysUtil;
023import com.aispeech.libcomm.business.call.WakeupCallUtil;
024import com.aispeech.libcomm.business.topic.GlobalAsrWakeupTopicUtil;
025import com.aispeech.libcomm.business.topic.RecorderTopicUtil;
026import com.aispeech.libcomm.business.topic.Topic;
027import com.aispeech.libcomm.business.topic.WakeupTopicUtil;
028import com.aispeech.libcomm.business.util.CompatibleTool;
029import com.aispeech.libcomm.callback.CallbackManager;
030import com.aispeech.libcomm.callback.OnSplitChannelAudioCallback;
031
032import org.json.JSONArray;
033import org.json.JSONException;
034import org.json.JSONObject;
035
036import java.util.ArrayList;
037import java.util.Arrays;
038import java.util.Iterator;
039import java.util.List;
040
041/**
042 * Created by nemo on 18-1-9.
043 */
044public class WakeupEngine {
045
046    private static final String TAG = "WakeupEngine";
047    private volatile static WakeupEngine mInstance;
048    private WordProxy mWordProxy = new WordProxy();
049    private VoipListener mVoipListener;
050    private BfListener mBfListener;
051    private BusClient mBc;
052
053    private String mBusServerAddr = "";
054
055    private BaseNode mNode = new BaseNode() {
056        @Override
057        public String getName() {
058            return TAG;
059        }
060
061        @Override
062        public String getAddress() {
063            if (!TextUtils.isEmpty(mBusServerAddr)) {
064                return mBusServerAddr;
065            } else {
066                return DDS.BUS_SERVER_ADDR;
067            }
068        }
069
070        @Override
071        public BusClient.RPCResult onCall(String url, Object... args) throws Exception {
072            if (url.equals(Topic.Wakeup.CallCustomGreeting.TOPIC_NAME)) {
073                if (args.length > 0) {
074                    JSONObject wakeupResult = new JSONObject(CompatibleTool.getString(args[0]));
075                    return mWordProxy.getGreetingRecResult(wakeupResult);
076                }
077            }
078            return null;
079        }
080
081        @Override
082        public void onJoin() {
083            super.onJoin();
084            mBc = bc;
085            subscribe();
086        }
087
088        @Override
089        public void onMessage(String topic, Object... parts) throws Exception {
090            switch (topic) {
091                case Topic.Pcm.LocalVoipPcm.TOPIC_NAME:
092                    if (mVoipListener != null) {
093                        byte[] pcm = (byte[]) parts[0];
094                        mVoipListener.onVoip(pcm);
095                    }
096                    break;
097                case Topic.Pcm.LocalAecPcm.TOPIC_NAME:
098                    if (mBfListener != null) {
099                        byte[] pcm = (byte[]) parts[0];
100                        mBfListener.onBeamforming(pcm);
101                    }
102                    break;
103            }
104            super.onMessage(topic, parts);
105        }
106    };
107
108    private WakeupEngine() {
109        mNode.start();
110    }
111
112    public static WakeupEngine getInstance() {
113        WakeupEngine localResource = mInstance;
114        if (localResource == null) {
115            synchronized (WakeupEngine.class) {
116                localResource = mInstance;
117                if (localResource == null) {
118                    mInstance = localResource = new WakeupEngine();
119                }
120            }
121        }
122        return localResource;
123    }
124
125    protected WakeupEngine(String lBridgeAddr) {
126        mBusServerAddr = lBridgeAddr;
127        mNode.start();
128    }
129
130    /**
131     * 设置自定义欢迎语的回调
132     *
133     * @param wakeupCallback 自定义唤醒的回调
134     */
135    public void setWakeupCallback(WakeupCallback wakeupCallback) {
136        AILog.userI(TAG, "setWakeupCallback input =", (wakeupCallback != null));
137        if (wakeupCallback != null) {
138            mBc.subscribeCall(Topic.Wakeup.CallCustomGreeting.TOPIC_NAME);
139        } else {
140            mBc.unsubscribeCall(Topic.Wakeup.CallCustomGreeting.TOPIC_NAME);
141        }
142        mWordProxy.setWakeupCallback(wakeupCallback);
143    }
144
145    /**
146     * 设置回调,可以回调信号处理后的各路音频
147     *
148     * @param callback 回调
149     */
150    public void setOnSplitChannelAudioCallback(OnSplitChannelAudioCallback callback) {
151        CallbackManager.getInstance().setOnSplitChannelAudioCallback(callback);
152    }
153
154    /**
155     * 设置voip监听器, 时时回调voip音频
156     *
157     * @param listener
158     */
159    public void setVoipListener(VoipListener listener) throws DDSNotInitCompleteException {
160        AILog.userI(TAG, "setVoipListener input =", (listener != null));
161        mVoipListener = listener;
162        if (mVoipListener == null) {
163            unSubscribe(Topic.Pcm.LocalVoipPcm.TOPIC_NAME);
164        } else {
165            subscribe();
166        }
167    }
168
169    /**
170     * 设置Beamforming监听器, 时时回调Beamforming音频
171     *
172     * @param listener
173     */
174    public void setBfListener(BfListener listener) throws DDSNotInitCompleteException {
175        AILog.userI(TAG, "setBfListener input =", (listener != null));
176        mBfListener = listener;
177        if (mBfListener == null) {
178            unSubscribe(Topic.Pcm.LocalAecPcm.TOPIC_NAME);
179        } else {
180            subscribe();
181        }
182    }
183
184    private void subscribe() {
185        if (mBc != null && mVoipListener != null) {
186            subscribe(Topic.Pcm.LocalVoipPcm.TOPIC_NAME);
187        }
188        if (mBc != null && mBfListener != null) {
189            subscribe(Topic.Pcm.LocalAecPcm.TOPIC_NAME);
190        }
191    }
192
193    private void subscribe(String inputTopic) {
194        mBc.unsubscribe(inputTopic);
195        mBc.subscribe(inputTopic);
196    }
197
198    private void unSubscribe(String topic) {
199        if (mBc != null) {
200            mBc.unsubscribe(topic);
201        }
202    }
203
204    /**
205     * 获取WakeupEngine
206     *
207     * @param lBridgeAddr 指定busserver地址
208     * @return WakeupEngine实例
209     */
210    public static WakeupEngine getInstance(String lBridgeAddr) {
211        WakeupEngine localResource = mInstance;
212        if (localResource == null) {
213            synchronized (WakeupEngine.class) {
214                localResource = mInstance;
215                if (localResource == null) {
216                    mInstance = localResource = new WakeupEngine(lBridgeAddr);
217                }
218            }
219        }
220        return localResource;
221    }
222
223    /**
224     * 获取 WakeupEngine 实例快照
225     *
226     * @return WakeupEngine
227     */
228    public static WakeupEngine getInstanceSnapshot() {
229        return mInstance;
230    }
231
232    /**
233     * 修改唤醒增强角度
234     * <p>
235     *
236     * @param doa 角度
237     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
238     */
239    public void setWakeupDoa(int doa) throws
240            DDSNotInitCompleteException {
241        checkInitComplete();
242        AILog.userI(TAG, "setWakeupDoa input =", doa);
243        BusClient bc = DDS.getInstance().getAgent().getBusClient();
244        WakeupTopicUtil.publishSetDoa(bc, "absolute", doa);
245    }
246
247
248    /**
249     * 修改驾驶模式
250     * <p>
251     * 如果需要支持音区控制,请每次更新唤醒模式后,再次同步音区配置信息
252     * {@code DDS.getInstance().getAgent().getWakeupEngine().setWakeupChannelMask(0b0100)}
253     *
254     * @param mode 驾驶模式, 0:定位模式, 1:主驾模式, 2: 副驾模式  3:全车模式
255     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
256     */
257    public void setWakeupMode(int mode) throws
258            DDSNotInitCompleteException {
259        checkInitComplete();
260        AILog.userI(TAG, "setWakeupMode input =", mode);
261
262        BusClient bc = DDS.getInstance().getAgent().getBusClient();
263        WakeupTopicUtil.publishSetMode(bc, mode);
264    }
265
266    /**
267     * 在定位模式或者全车模式下,手动设置为主驾唤醒或者副驾唤醒
268     *
269     * @param doaManually 1为主驾唤醒; 2为副驾唤醒;
270     */
271    public void setDriveDoaManually(int doaManually) throws DDSNotInitCompleteException {
272        checkInitComplete();
273        AILog.userI(TAG, "setDriveDoaManually =", doaManually);
274
275        BusClient bc = DDS.getInstance().getAgent().getBusClient();
276        WakeupTopicUtil.publishSetDriveDoaManually(bc, doaManually);
277    }
278
279    /**
280     * 更新 sspe(前端信号处理) 与  wakeup(唤醒) 资源
281     *
282     * @param sspeBinPath           sspe资源
283     * @param wakeupBinPath         唤醒资源
284     * @param backRowRestrainEnable 后排抑制开关,true:开启、false:关闭
285     */
286    public void setResBin(String sspeBinPath, String wakeupBinPath, boolean backRowRestrainEnable) throws DDSNotInitCompleteException {
287        checkInitComplete();
288        AILog.userI(TAG, "setResBin sspeBinPath =", sspeBinPath, "wakeupBinPath =", wakeupBinPath,"backRowRestrainEnable =", backRowRestrainEnable);
289
290        BusClient bc = DDS.getInstance().getAgent().getBusClient();
291        WakeupTopicUtil.publishSetResBin(bc, sspeBinPath, wakeupBinPath,backRowRestrainEnable);
292    }
293
294    /**
295     * 设置可唤醒路数掩码
296     * <p>
297     * 4麦有4位二进制表示对应的路数是否可以唤醒,最低位表示第1路。
298     * 比如设置 wakeupChannelMask 为 3(0011) 表示第1路和第2路唤醒
299     * <p>
300     * 只有使用 dmasp 算法的多麦唤醒配置才有效
301     * <p>
302     * 设置只有第3路可用的代码示例:
303     * <p>
304     * {@code DDS.getInstance().getAgent().getWakeupEngine().setWakeupChannelMask(0b0100)}
305     *
306     * @param wakeupChannelMask 可唤醒路数掩码
307     * @throws DDSNotInitCompleteException
308     */
309    public void setWakeupChannelMask(int wakeupChannelMask) throws
310            DDSNotInitCompleteException {
311        checkInitComplete();
312        AILog.userI(TAG, "setWakeupChannelMask input =", wakeupChannelMask);
313
314        BusClient bc = DDS.getInstance().getAgent().getBusClient();
315        WakeupTopicUtil.publishWakeupChannelMask(bc, wakeupChannelMask);
316    }
317
318
319    /**
320     * 添加主唤醒词的接口
321     * <p>
322     * 支持添加多个主唤醒词,调用此接口会覆盖控制台配置的主唤醒词,直到通过removeMainWakeupWord接口移除。
323     *
324     * @param words     主唤醒词,不为null
325     * @param pinyin    主唤醒词的拼音,不为null
326     * @param threshold 主唤醒词的阈值,不为null
327     * @param greetings 主唤醒词的欢迎语,不为null;如果某个唤醒词不想要欢迎语,在对应的维度设为null
328     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
329     */
330    @Deprecated
331    public void addMainWakeupWord(String[] words, String[] pinyin, String[] threshold, String[][] greetings) throws
332            DDSNotInitCompleteException {
333        mWordProxy.addMainWakeupWord(words, pinyin, threshold, greetings);
334    }
335
336    /**
337     * 添加一条主唤醒词
338     * <p>
339     * 调用此接口会覆盖控制台配置的主唤醒词,直到通过removeMainWakeupWord接口移除。
340     *
341     * @param wakeupWord 唤醒词业对象
342     *                   <p>
343     *                   必填参数:
344     *                   <p>
345     *                   word: 唤醒词的汉字
346     *                   <p>
347     *                   pinyin: 唤醒词的拼音
348     *                   <p>
349     *                   threshold: 唤醒词的阈值
350     *                   <p>
351     *                   选填参数:
352     *                   <p>
353     *                   greeting: 唤醒词的欢迎语, 若不设置,则与主唤醒词保持一致
354     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
355     */
356    public void addMainWakeupWord(WakeupWord wakeupWord) throws DDSNotInitCompleteException {
357        addMainWakeupWords(toWakeupWordList(wakeupWord));
358    }
359
360    /**
361     * 添加多条主唤醒词
362     * <p>
363     * 调用此接口会覆盖控制台配置的主唤醒词,直到通过removeMainWakeupWord接口移除。
364     *
365     * @param wakeupWordList 唤醒词业对象集合
366     *                       <p>
367     *                       必填参数:
368     *                       <p>
369     *                       word: 唤醒词的汉字
370     *                       <p>
371     *                       pinyin: 唤醒词的拼音
372     *                       <p>
373     *                       threshold: 唤醒词的阈值
374     *                       <p>
375     *                       选填参数:
376     *                       <p>
377     *                       greeting: 唤醒词的欢迎语, 若不设置,则与主唤醒词保持一致
378     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
379     */
380    public void addMainWakeupWords(List<WakeupWord> wakeupWordList) throws DDSNotInitCompleteException {
381        mWordProxy.addMainWakeupWords(wakeupWordList);
382    }
383
384    /**
385     * 移除指定的主唤醒词
386     * <p>
387     * 如果移除了所有通过addMainWakeupWord接口添加的主唤醒词,则主唤醒词重置为控制台所配置的
388     *
389     * @param words 主唤醒词的汉字(必须)
390     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
391     */
392    @Deprecated
393    public void removeMainWakeupWord(String[] words) throws DDSNotInitCompleteException {
394        mWordProxy.removeMainWakeupWord(words);
395    }
396
397    /**
398     * 关闭本地热词分级功能
399     */
400    public void enableIncrementWakeupPriority() throws DDSNotInitCompleteException {
401        enableIncrementWakeupWordPriority(Topic.Wakeup.IncrementWakeupEnablePriority.ENABLE_PRIORITY);
402    }
403
404    /**
405     * 更新黑名单词库,覆盖式更新,如需要清除则传null
406     */
407    public void updateIncrementWakeupBlackWords(List<String> blackWordList) throws DDSNotInitCompleteException {
408        if (blackWordList == null) {
409            blackWordList = new ArrayList<>();
410        }
411        String[] blackWords = blackWordList.toArray(new String[blackWordList.size()]);
412        BusClient bc = DDS.getInstance().getAgent().getBusClient();
413        WakeupTopicUtil.publishUpdateIncrementBlackWakeupWord(bc, blackWords);
414    }
415
416    /**
417     * 关闭本地热词分级功能
418     */
419    public void disableIncrementWakeupPriority() throws DDSNotInitCompleteException {
420        disableIncrementWakeupWordPriority(Topic.Wakeup.IncrementWakeupEnablePriority.DISENABLE_PRIORITY);
421    }
422
423    /**
424     * 开启本地热词分级功能
425     */
426    public void enableIncrementWakeupWordPriority(String priority) throws DDSNotInitCompleteException {
427        if (TextUtils.isEmpty(priority)) {
428            AILog.d(TAG, "enableIncrementWakeupWordPriority failed by empty priority");
429            return;
430        }
431        AILog.userI(TAG, "enableIncrementWakeupWordPriority input =", priority);
432        mWordProxy.enableIncrementWakeupPriority(priority);
433    }
434
435    /**
436     * 关闭本地热词分级功能
437     */
438    public void disableIncrementWakeupWordPriority(String priority) throws DDSNotInitCompleteException {
439        if (TextUtils.isEmpty(priority)) {
440            AILog.d(TAG, "disenableIncrementWakeupWordPriority failed by empty priority");
441            return;
442        }
443        AILog.userI(TAG, "disableIncrementWakeupWordPriority input =", priority);
444        mWordProxy.disenableIncrementWakeupPriority(priority);
445    }
446
447    /**
448     * 清空本地热词命令唤醒词的接口
449     */
450    public void clearIncrementCommandWakeupWord() throws DDSNotInitCompleteException {
451        AILog.userI(TAG, "clearIncrementCommandWakeupWord");
452        mWordProxy.clearIncrementCommandWakeupWord();
453    }
454
455    /**
456     * 清空本地热词打断唤醒词的接口
457     */
458    public void clearIncrementShortCutWakeupWord() throws DDSNotInitCompleteException {
459        AILog.userI(TAG, "clearIncrementShortCutWakeupWord");
460        mWordProxy.clearIncrementShortCutWakeupWord();
461    }
462
463    /**
464     * 移除所有本地热词
465     *
466     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
467     */
468    public void clearIncrementWakeupWord() throws DDSNotInitCompleteException {
469        AILog.userI(TAG, "clearIncrementWakeupWord");
470        mWordProxy.clearIncrementWakeupWord();
471    }
472
473    /**
474     * 移除一条指定的主唤醒词
475     * <p>
476     * 如果移除了所有通过addMainWakeupWord接口添加的主唤醒词,则主唤醒词重置为控制台所配置的
477     *
478     * @param wakeupWord 唤醒词的对象
479     *                   <p>
480     *                   必填参数:
481     *                   <p>
482     *                   word: 唤醒词的汉字
483     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
484     */
485    public void removeMainWakeupWord(WakeupWord wakeupWord) throws DDSNotInitCompleteException {
486        removeMainWakeupWords(toWakeupWordList(wakeupWord));
487    }
488
489    /**
490     * 移除多条指定的主唤醒词
491     * <p>
492     * 如果移除了所有通过addMainWakeupWord接口添加的主唤醒词,则主唤醒词重置为控制台所配置的
493     *
494     * @param wakeupWordList 唤醒词的对象集合
495     *                       <p>
496     *                       必填参数:
497     *                       <p>
498     *                       word: 唤醒词的汉字
499     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
500     */
501    public void removeMainWakeupWords(List<WakeupWord> wakeupWordList) throws DDSNotInitCompleteException {
502        mWordProxy.removeMainWakeupWords(wakeupWordList);
503    }
504
505    /**
506     * 更新多条主唤醒词的接口,覆盖原有的主唤醒词
507     * <p>
508     * 支持设置多个主唤醒词,所以参数为数组,重复调用会以最新的主唤醒词数组为准。
509     *
510     * @param wakeupWordList 唤醒词对象集合
511     *                       <p>
512     *                       必填参数:
513     *                       <p>
514     *                       word: 唤醒词的汉字
515     *                       <p>
516     *                       pinyin: 唤醒词的拼音
517     *                       <p>
518     *                       threshold: 唤醒词的阈值
519     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
520     */
521    public void updateMainWakeupWords(List<WakeupWord> wakeupWordList) throws DDSNotInitCompleteException {
522        mWordProxy.updateMainWakeupWords(wakeupWordList);
523    }
524
525    /**
526     * 清空主唤醒词的接口
527     *
528     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
529     */
530    public void clearMainWakeupWord() throws DDSNotInitCompleteException {
531        AILog.userI(TAG, "clearMainWakeupWord");
532        mWordProxy.clearMainWakeupWords();
533    }
534
535    /**
536     * 更新副唤醒词的接口
537     * <p>
538     * 支持设置一个副唤醒词,重复调用会以最新的副唤醒词为准
539     *
540     * @param word      副唤醒词, 若设置null,则清空当前的副唤醒词
541     * @param pinyin    副唤醒词的拼音
542     * @param threshold 副唤醒词的阈值, 若设置null,则自动估算
543     * @param greetings 副唤醒词的欢迎语, 若设置null,则与主唤醒词保持一致
544     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
545     */
546    @Deprecated
547    public void updateMinorWakeupWord(String word, String pinyin, String threshold, String[] greetings) throws
548            DDSNotInitCompleteException {
549        mWordProxy.updateMinorWakeupWord(word, pinyin, threshold, greetings);
550    }
551
552    /**
553     * 更新副唤醒词的接口
554     * <p>
555     * 支持设置一个副唤醒词,重复调用会以最新的副唤醒词为准
556     *
557     * @param wakeupWord 唤醒词对象
558     *                   <p>
559     *                   选填参数:
560     *                   <p>
561     *                   word: 唤醒词的汉字, 若不设置,则清空当前的副唤醒词
562     *                   <p>
563     *                   pinyin: 唤醒词的拼音, 若不设置,则清空当前的副唤醒词
564     *                   <p>
565     *                   threshold: 唤醒词的阈值, 若不设置,则自动估算
566     *                   <p>
567     *                   greeting: 唤醒词的欢迎语, 若不设置,则与主唤醒词保持一致
568     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
569     */
570    public void updateMinorWakeupWord(WakeupWord wakeupWord) throws DDSNotInitCompleteException {
571        mWordProxy.updateMinorWakeupWord(wakeupWord);
572    }
573
574    /**
575     * 获取当前的副唤醒词
576     *
577     * @return String 副唤醒词, 若无则返回null
578     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
579     */
580    public String getMinorWakeupWord() throws DDSNotInitCompleteException {
581        String result = mWordProxy.getMinorWakeupWord();
582        AILog.userI(TAG, "getMinorWakeupWord result =", result);
583        return result;
584    }
585
586
587    /**
588     * 更新命令唤醒词的接口,这类唤醒词会在唤醒之后执行一条指令,不能打断正在播报的语音
589     * <p>
590     * 支持设置多个命令唤醒词,所以参数为数组,重复调用会以最新的命令唤醒词数组为准。
591     *
592     * @param actions   命令唤醒词对应的command命令(必须)
593     * @param words     命令唤醒词的汉字(必须)
594     * @param pinyin    命令唤醒词的拼音(必须)
595     * @param threshold 命令唤醒词的阈值(必须
596     * @param greetings 命令唤醒词对应的唤醒语,一个唤醒词可以设置多条欢迎语,所以参数为二维数组,如果想要某个唤醒词不要欢迎语,那么该第二维数组的string可以设置为空字符串""
597     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
598     */
599    @Deprecated
600    public void updateCommandWakeupWord(String[] actions, String[] words, String[] pinyin, String[] threshold, String[][] greetings) throws DDSNotInitCompleteException {
601        mWordProxy.updateCommandWakeupWord(actions, words, pinyin, threshold, greetings);
602    }
603
604    /**
605     * 更新一条命令唤醒词的接口,这类唤醒词会在唤醒之后执行一条指令,不能打断正在播报的语音
606     * <p>
607     * 支持设置多个命令唤醒词,所以参数为数组,重复调用会以最新的命令唤醒词数组为准。
608     *
609     * @param wakeupWord 唤醒词对象
610     *                   <p>
611     *                   必填参数:
612     *                   <p>
613     *                   action: 唤醒词对应的command命令
614     *                   <p>
615     *                   word: 唤醒词的汉字
616     *                   <p>
617     *                   pinyin: 唤醒词的拼音
618     *                   <p>
619     *                   threshold: 唤醒词的阈值
620     *                   <p>
621     *                   选填参数:
622     *                   <p>
623     *                   greeting: 唤醒词对应的欢迎语,一个唤醒词可以设置多条欢迎语
624     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
625     */
626    public void updateCommandWakeupWord(WakeupWord wakeupWord) throws DDSNotInitCompleteException {
627        updateCommandWakeupWords(toWakeupWordList(wakeupWord));
628    }
629
630    /**
631     * 更新多条命令唤醒词的接口,这类唤醒词会在唤醒之后执行一条指令,不能打断正在播报的语音
632     * <p>
633     * 支持设置多个命令唤醒词,所以参数为数组,重复调用会以最新的命令唤醒词数组为准。
634     *
635     * @param wakeupWordList 唤醒词对象集合
636     *                       <p>
637     *                       必填参数:
638     *                       <p>
639     *                       action: 唤醒词对应的command命令
640     *                       <p>
641     *                       word: 唤醒词的汉字
642     *                       <p>
643     *                       pinyin: 唤醒词的拼音
644     *                       <p>
645     *                       threshold: 唤醒词的阈值
646     *                       <p>
647     *                       选填参数:
648     *                       <p>
649     *                       greeting: 唤醒词对应的欢迎语,一个唤醒词可以设置多条欢迎语
650     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
651     */
652    public void updateCommandWakeupWords(List<WakeupWord> wakeupWordList) throws DDSNotInitCompleteException {
653        mWordProxy.updateCommandWakeupWords(wakeupWordList);
654    }
655
656    /**
657     * 添加命令唤醒词,且不会覆盖之前的命令唤醒词
658     * <p>
659     *
660     * @param actions   命令唤醒词对应的command命令(必须)
661     * @param words     命令唤醒词的汉字(必须)
662     * @param pinyin    命令唤醒词的拼音(必须)
663     * @param threshold 命令唤醒词的阈值(必须
664     * @param greetings 命令唤醒词对应的唤醒语,一个唤醒词可以设置多条欢迎语,所以参数为二维数组,如果想要某个唤醒词不要欢迎语,那么该第二维数组的string可以设置为空字符串""
665     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
666     */
667    @Deprecated
668    public void addCommandWakeupWord(String[] actions, String[] words, String[] pinyin, String[] threshold, String[][] greetings) throws DDSNotInitCompleteException {
669        mWordProxy.addCommandWakeupWord(actions, words, pinyin, threshold, greetings);
670    }
671
672    /**
673     * 添加一条命令唤醒词,且不会覆盖之前的命令唤醒词
674     *
675     * @param wakeupWord 唤醒词对象
676     *                   <p>
677     *                   必填参数:
678     *                   <p>
679     *                   action: 唤醒词对应的command命令
680     *                   <p>
681     *                   word: 唤醒词的汉字
682     *                   <p>
683     *                   pinyin: 唤醒词的拼音
684     *                   <p>
685     *                   threshold: 唤醒词的阈值
686     *                   <p>
687     *                   选填参数:
688     *                   <p>
689     *                   greeting: 唤醒词对应的欢迎语,一个唤醒词可以设置多条欢迎语
690     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
691     */
692    public void addCommandWakeupWord(WakeupWord wakeupWord) throws DDSNotInitCompleteException {
693        addCommandWakeupWords(toWakeupWordList(wakeupWord));
694    }
695
696    /**
697     * 添加多条命令唤醒词,且不会覆盖之前的命令唤醒词
698     *
699     * @param wakeupWordList 唤醒词对象集合
700     *                       <p>
701     *                       必填参数:
702     *                       <p>
703     *                       action: 唤醒词对应的command命令
704     *                       <p>
705     *                       word: 唤醒词的汉字
706     *                       <p>
707     *                       pinyin: 唤醒词的拼音
708     *                       <p>
709     *                       threshold: 唤醒词的阈值
710     *                       <p>
711     *                       选填参数:
712     *                       <p>
713     *                       greeting: 唤醒词对应的欢迎语,一个唤醒词可以设置多条欢迎语
714     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
715     */
716    public void addCommandWakeupWords(List<WakeupWord> wakeupWordList) throws DDSNotInitCompleteException {
717        mWordProxy.addCommandWakeupWords(wakeupWordList);
718    }
719
720    /**
721     * 移除指定的命令唤醒词
722     * <p>
723     *
724     * @param words 命令唤醒词的汉字(必须)
725     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
726     */
727    @Deprecated
728    public void removeCommandWakeupWord(String[] words) throws DDSNotInitCompleteException {
729        mWordProxy.removeCommandWakeupWord(words);
730    }
731
732    /**
733     * 移除一条指定的命令唤醒词
734     *
735     * @param wakeupWord 唤醒词对象
736     *                   <p>
737     *                   必填参数:
738     *                   <p>
739     *                   word: 唤醒词的汉字
740     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
741     */
742    public void removeCommandWakeupWord(WakeupWord wakeupWord) throws DDSNotInitCompleteException {
743        removeCommandWakeupWords(toWakeupWordList(wakeupWord));
744    }
745
746    /**
747     * 移除一条指定的命令唤醒词
748     *
749     * @param wakeupWordList 唤醒词对象集合
750     *                       <p>
751     *                       必填参数:
752     *                       <p>
753     *                       word: 唤醒词的汉字
754     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
755     */
756    public void removeCommandWakeupWords(List<WakeupWord> wakeupWordList) throws DDSNotInitCompleteException {
757        mWordProxy.removeCommandWakeupWords(wakeupWordList);
758    }
759
760    /**
761     * 清空命令唤醒词的接口
762     *
763     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
764     */
765    public void clearCommandWakeupWord() throws DDSNotInitCompleteException {
766        AILog.userI(TAG, "clearCommandWakeupWord");
767        mWordProxy.clearCommandWakeupWord();
768    }
769
770    /**
771     * 清空打断唤醒词的接口
772     *
773     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
774     */
775    public void clearShortCutWakeupWord() throws DDSNotInitCompleteException {
776        AILog.userI(TAG, "clearShortCutWakeupWord");
777        mWordProxy.clearShortCutWakeupWord();
778    }
779
780    /**
781     * 更新打断唤醒词的接口,这类唤醒词能打断正在播报的语音并且将唤醒词送入识别
782     * <p>
783     * 支持设置多个打断唤醒词,所以参数为数组,重复调用会以最新的打断唤醒词数组为准。
784     *
785     * @param words     打断唤醒词的汉字(必须)
786     * @param pinyin    打断唤醒词的拼音(必须)
787     * @param threshold 打断唤醒词的阈值(必须
788     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
789     */
790    @Deprecated
791    public void updateShortcutWakeupWord(String[] words, String[] pinyin, String[] threshold) throws DDSNotInitCompleteException {
792        mWordProxy.updateShortcutWakeupWord(words, pinyin, threshold);
793    }
794
795    /**
796     * 更新一条打断唤醒词的接口,这类唤醒词能打断正在播报的语音并且将唤醒词送入识别
797     * <p>
798     * 支持设置多个打断唤醒词,所以参数为数组,重复调用会以最新的打断唤醒词数组为准。
799     *
800     * @param wakeupWord 唤醒词对象
801     *                   <p>
802     *                   必填参数:
803     *                   <p>
804     *                   word: 唤醒词的汉字
805     *                   <p>
806     *                   pinyin: 唤醒词的拼音
807     *                   <p>
808     *                   threshold: 唤醒词的阈值
809     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
810     */
811    public void updateShortcutWakeupWord(WakeupWord wakeupWord) throws DDSNotInitCompleteException {
812        updateShortcutWakeupWords(toWakeupWordList(wakeupWord));
813    }
814
815    /**
816     * 更新多条打断唤醒词的接口,这类唤醒词能打断正在播报的语音并且将唤醒词送入识别
817     * <p>
818     * 支持设置多个打断唤醒词,所以参数为数组,重复调用会以最新的打断唤醒词数组为准。
819     *
820     * @param wakeupWordList 唤醒词对象集合
821     *                       <p>
822     *                       必填参数:
823     *                       <p>
824     *                       word: 唤醒词的汉字
825     *                       <p>
826     *                       pinyin: 唤醒词的拼音
827     *                       <p>
828     *                       threshold: 唤醒词的阈值
829     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
830     */
831    public void updateShortcutWakeupWords(List<WakeupWord> wakeupWordList) throws DDSNotInitCompleteException {
832        mWordProxy.updateShortcutWakeupWords(wakeupWordList);
833    }
834
835    /**
836     * 添加新的打断唤醒词,且不会覆盖之前的唤醒词
837     * <p>
838     *
839     * @param words     打断唤醒词的汉字(必须)
840     * @param pinyin    打断唤醒词的拼音(必须)
841     * @param threshold 打断唤醒词的阈值(必须
842     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
843     */
844    @Deprecated
845    public void addShortcutWakeupWord(String[] words, String[] pinyin, String[] threshold) throws DDSNotInitCompleteException {
846        mWordProxy.addShortcutWakeupWord(words, pinyin, threshold);
847    }
848
849    /**
850     * 添加一条新的打断唤醒词,且不会覆盖之前的唤醒词
851     *
852     * @param wakeupWord 唤醒词对象
853     *                   <p>
854     *                   必填参数:
855     *                   <p>
856     *                   word: 唤醒词的汉字
857     *                   <p>
858     *                   pinyin: 唤醒词的拼音
859     *                   <p>
860     *                   threshold: 唤醒词的阈值
861     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
862     */
863    public void addShortcutWakeupWord(WakeupWord wakeupWord) throws DDSNotInitCompleteException {
864        addShortcutWakeupWords(toWakeupWordList(wakeupWord));
865    }
866
867    /**
868     * 添加多条新的打断唤醒词,且不会覆盖之前的唤醒词
869     *
870     * @param wakeupWordList 唤醒词对象集合
871     *                       <p>
872     *                       必填参数:
873     *                       <p>
874     *                       word: 唤醒词的汉字
875     *                       <p>
876     *                       pinyin: 唤醒词的拼音
877     *                       <p>
878     *                       threshold: 唤醒词的阈值
879     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
880     */
881    public void addShortcutWakeupWords(List<WakeupWord> wakeupWordList) throws DDSNotInitCompleteException {
882        mWordProxy.addShortcutWakeupWords(wakeupWordList);
883    }
884
885    /**
886     * 更新热词
887     *
888     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
889     */
890    public void updateHotWords(HotWords hotWords) throws DDSNotInitCompleteException {
891        checkInitComplete();
892        if (hotWords == null) {
893            hotWords = new HotWords();
894        }
895        BusClient bc = DDS.getInstance().getAgent().getBusClient();
896        JSONObject hotWordsObj = hotWords.getHotWordsObj();
897        WakeupTopicUtil.publishStickyUpdateHotWords(bc, hotWordsObj);
898    }
899
900    /**
901     * 移除指定的打断唤醒词
902     * <p>
903     *
904     * @param words 打断唤醒词的汉字(必须)
905     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
906     */
907    @Deprecated
908    public void removeShortcutWakeupWord(String[] words) throws DDSNotInitCompleteException {
909        mWordProxy.removeShortcutWakeupWord(words);
910    }
911
912    /**
913     * 移除一条指定的打断唤醒词
914     *
915     * @param wakeupWord 唤醒词对象
916     *                   <p>
917     *                   必填参数:
918     *                   <p>
919     *                   word: 唤醒词的汉字
920     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
921     */
922    public void removeShortcutWakeupWord(WakeupWord wakeupWord) throws DDSNotInitCompleteException {
923        removeShortcutWakeupWords(toWakeupWordList(wakeupWord));
924    }
925
926    /**
927     * 移除多条指定的打断唤醒词
928     *
929     * @param wakeupWordList 唤醒词对象集合
930     *                       <p>
931     *                       必填参数:
932     *                       <p>
933     *                       word: 唤醒词的汉字
934     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
935     */
936    public void removeShortcutWakeupWords(List<WakeupWord> wakeupWordList) throws DDSNotInitCompleteException {
937        mWordProxy.removeShortcutWakeupWords(wakeupWordList);
938    }
939
940    /**
941     * 更新唤醒词,合并请求
942     *
943     * @param intents 合并请求意图
944     */
945    public void updateWakeupWords(List<WakeupWordIntent> intents) throws DDSNotInitCompleteException {
946        mWordProxy.updateWakeupWords(intents);
947    }
948
949    /**
950     * 添加多条QuickStart词
951     * QuickStart词为类似“导航去”、“我想听”等,此类唤醒词只在oneshot模式下生效,
952     * 作用为在未唤醒状态下语音输入“导航去天安门”,可直接进入对话流程。
953     * <p>
954     *
955     * @param wakeupWordList QuickStart词对象集合
956     *                       <p>
957     *                       必填参数:
958     *                       <p>
959     *                       word: QuickStart词的汉字
960     *                       <p>
961     *                       pinyin: QuickStart词的拼音
962     *                       <p>
963     *                       threshold: QuickStart词的阈值
964     *                       <p>
965     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
966     */
967    public void addQuickStartWords(List<WakeupWord> wakeupWordList) throws DDSNotInitCompleteException {
968        mWordProxy.addQuickStartWords(wakeupWordList);
969    }
970
971    /**
972     * 移除一条指定的QuickStart词
973     * <p>
974     *
975     * @param wakeupWord QuickStart词的对象
976     *                   <p>
977     *                   必填参数:
978     *                   <p>
979     *                   word: QuickStart词的汉字
980     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
981     */
982    public void removeQuickStartWord(WakeupWord wakeupWord) throws DDSNotInitCompleteException {
983        removeQuickStartWords(toWakeupWordList(wakeupWord));
984    }
985
986    /**
987     * 移除多条指定的QuickStart词
988     * <p>
989     *
990     * @param wakeupWordList QuickStart词的对象集合
991     *                       <p>
992     *                       必填参数:
993     *                       <p>
994     *                       word: QuickStart词的汉字
995     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
996     */
997    public void removeQuickStartWords(List<WakeupWord> wakeupWordList) throws DDSNotInitCompleteException {
998        mWordProxy.removeQuickStartWords(wakeupWordList);
999    }
1000
1001    /**
1002     * 更新多条QuickStart词的接口,覆盖原有的QuickStart词
1003     * <p>
1004     * 支持设置多个QuickStart词,所以参数为数组,重复调用会以最新的QuickStart词数组为准。
1005     *
1006     * @param wakeupWordList QuickStart词对象集合
1007     *                       <p>
1008     *                       必填参数:
1009     *                       <p>
1010     *                       word: QuickStart词的汉字
1011     *                       <p>
1012     *                       pinyin: QuickStart词的拼音
1013     *                       <p>
1014     *                       threshold: QuickStart词的阈值
1015     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1016     */
1017    public void updateQuickStartWords(List<WakeupWord> wakeupWordList) throws DDSNotInitCompleteException {
1018        mWordProxy.updateQuickStartWords(wakeupWordList);
1019    }
1020
1021    /**
1022     * 清空QuickStart词的接口
1023     *
1024     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1025     */
1026    public void clearQuickStartWords() throws DDSNotInitCompleteException {
1027        AILog.userI(TAG, "clearQuickStartWords");
1028        mWordProxy.clearQuickStartWords();
1029    }
1030
1031    /**
1032     * 设置主唤醒词可唤醒,默认开启
1033     * (在已经调用enableWakeup的情况下临时使用, disableWakeup情况下无效)
1034     * <p>
1035     */
1036    public void enableMainWakeupWord() throws DDSNotInitCompleteException {
1037        checkInitComplete();
1038        AILog.userI(TAG, "enableMainWakeupWord");
1039        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1040        WakeupTopicUtil.publishStickySetWakeupWordStatus(bc, "mainword", "open");
1041    }
1042
1043    /**
1044     * 设置就近唤醒参数与调度参数
1045     * 仅在就近唤醒状态下生效(线双麦/线四麦)
1046     * <p>
1047     */
1048    @Deprecated
1049    public void setNearWakeupParams(JSONObject paramsObj) throws DDSNotInitCompleteException {
1050//        checkInitComplete();
1051//        AILog.userI(TAG, "setNearWakeupParams input =", paramsObj.toString());
1052//        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1053//        WakeupTopicUtil.publishNearWakeupSetParams(bc, paramsObj.toString());
1054    }
1055
1056    /**
1057     * 设置就近唤醒网络变化
1058     * 仅在就近唤醒状态下生效(线双麦/线四麦)
1059     * <p>
1060     */
1061    public void notifyNearWakeupNetworkChange(String ipAddress,JSONObject otherParams) throws DDSNotInitCompleteException {
1062        checkInitComplete();
1063        JSONObject paramsObj = new JSONObject();
1064        try {
1065            paramsObj.put("event", "networkchange");
1066            paramsObj.put("ip",ipAddress);
1067            paramsObj.put("remoteJudge",1);
1068            if(otherParams != null) {
1069                Iterator<String> keys = otherParams.keys();
1070                while (keys.hasNext()) {
1071                    String key = keys.next();
1072                    paramsObj.put(key,otherParams.opt(key));
1073                }
1074            }
1075        } catch (JSONException exception) {
1076            exception.printStackTrace();
1077        }
1078        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1079        WakeupTopicUtil.publishNearWakeupSetParams(bc, paramsObj.toString());
1080    }
1081
1082    /**
1083     * { "event": "wakeupSwitch",  "value": 0 }
1084     * 就近唤醒stop时会用到此参数,value为0时表示用户停止唤醒, value为1时表示用户开启唤醒
1085     * 作用是告诉就近唤醒是否要真正停止还是只停止唤醒不停止组网
1086     */
1087//    private void setNearWakeupParams(int isWakeup) {
1088//        try {
1089//            AILog.userI(TAG, "setNearWakeupParams input =", isWakeup);
1090//            JSONObject nearObj = new JSONObject();
1091//            nearObj.put("event", "wakeupSwitch");
1092//            nearObj.put("value", isWakeup);
1093//            setNearWakeupParams(nearObj);
1094//        } catch (Exception e) {
1095//            com.aispeech.dui.manager.AIJavaException.printException(e);
1096//        }
1097//    }
1098
1099    /**
1100     * 设置主唤醒词不可唤醒
1101     *
1102     * <p>
1103     */
1104    public void disableMainWakeupWord() throws DDSNotInitCompleteException {
1105        checkInitComplete();
1106        AILog.userI(TAG, "disableMainWakeupWord");
1107        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1108        WakeupTopicUtil.publishStickySetWakeupWordStatus(bc, "mainword", "close");
1109    }
1110
1111    /**
1112     * 设置副唤醒词可唤醒,默认开启
1113     * (在已经调用enableWakeup的情况下临时使用, disableWakeup情况下无效)
1114     * <p>
1115     */
1116    public void enableMinorWakeupWord() throws DDSNotInitCompleteException {
1117        checkInitComplete();
1118        AILog.userI(TAG, "enableMinorWakeupWord");
1119        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1120        WakeupTopicUtil.publishStickySetWakeupWordStatus(bc, "minorword", "open");
1121    }
1122
1123    /**
1124     * 设置副唤醒词不可唤醒
1125     *
1126     * <p>
1127     */
1128    public void disableMinorWakeupWord() throws DDSNotInitCompleteException {
1129        checkInitComplete();
1130        AILog.userI(TAG, "disableMinorWakeupWord");
1131        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1132        WakeupTopicUtil.publishStickySetWakeupWordStatus(bc, "minorword", "close");
1133    }
1134
1135    /**
1136     * 设置快捷命令唤醒词可唤醒,默认开启
1137     * (在已经调用enableWakeup的情况下临时使用, disableWakeup情况下无效)
1138     * <p>
1139     */
1140    public void enableCommandWakeupWord() throws DDSNotInitCompleteException {
1141        checkInitComplete();
1142        AILog.userI(TAG, "enableCommandWakeupWord");
1143        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1144        WakeupTopicUtil.publishStickySetWakeupWordStatus(bc, "commandword", "open");
1145    }
1146
1147    /**
1148     * 设置快捷命令唤醒词不可唤醒
1149     *
1150     * <p>
1151     */
1152    public void disableCommandWakeupWord() throws DDSNotInitCompleteException {
1153        checkInitComplete();
1154        AILog.userI(TAG, "disableCommandWakeupWord");
1155        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1156        WakeupTopicUtil.publishStickySetWakeupWordStatus(bc, "commandword", "close");
1157    }
1158
1159    /**
1160     * 设置QuickStart唤醒词可唤醒,默认开启
1161     * (在已经调用enableWakeup的情况下临时使用, disableWakeup情况下无效)
1162     * <p>
1163     */
1164    public void enableQuickStartWakeupWord() throws DDSNotInitCompleteException {
1165        checkInitComplete();
1166        AILog.userI(TAG, "enableQuickStartWakeupWord");
1167        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1168        WakeupTopicUtil.publishStickySetWakeupWordStatus(bc, "quickstartword", "open");
1169    }
1170
1171    /**
1172     * 设置QuickStart唤醒词不可唤醒
1173     *
1174     * <p>
1175     */
1176    public void disableQuickStartWakeupWord() throws DDSNotInitCompleteException {
1177        checkInitComplete();
1178        AILog.userI(TAG, "disableQuickStartWakeupWord");
1179        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1180        WakeupTopicUtil.publishStickySetWakeupWordStatus(bc, "quickstartword", "close");
1181    }
1182
1183    /**
1184     * 设置打断唤醒词可唤醒,默认开启
1185     * (在已经调用enableWakeup的情况下临时使用, disableWakeup情况下无效)
1186     * <p>
1187     */
1188    public void enableShortCutWakeupWord() throws DDSNotInitCompleteException {
1189        checkInitComplete();
1190        AILog.userI(TAG, "enableShortCutWakeupWord");
1191        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1192        WakeupTopicUtil.publishStickySetWakeupWordStatus(bc, "shortcutword", "open");
1193    }
1194
1195    /**
1196     * 设置打断唤醒词不可唤醒
1197     *
1198     * <p>
1199     */
1200    public void disableShortCutWakeupWord() throws DDSNotInitCompleteException {
1201        checkInitComplete();
1202        AILog.userI(TAG, "disableShortCutWakeupWord");
1203        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1204        WakeupTopicUtil.publishStickySetWakeupWordStatus(bc, "shortcutword", "close");
1205    }
1206
1207    /**
1208     * 开启唤醒
1209     *
1210     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1211     */
1212    public void enableWakeup() throws DDSNotInitCompleteException {
1213        checkInitComplete();
1214        AILog.userI(TAG, "enableWakeup");
1215//        setNearWakeupParams(1);
1216        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1217        WakeupTopicUtil.publishStickyAgentSettings(bc, "wakeup", true);
1218    }
1219
1220    /**
1221     * 是否允许识别过程中响应唤醒
1222     * <p>
1223     *
1224     * @param enable true: 允许识别过程中响应唤醒, false: 不允许识别过程中响应唤醒
1225     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1226     */
1227    public void enableWakeupWhenAsr(boolean enable) throws DDSNotInitCompleteException {
1228        AILog.userI(TAG, "enableWakeupWhenAsr input =", enable);
1229        if (enable) {
1230            enableWakeupWhenAsr();
1231        } else {
1232            disableWakeupWhenAsr();
1233        }
1234    }
1235
1236    /**
1237     * 设置录音机是否可用
1238     * <ul>
1239     *     <li>true 录音机可用,但真正打开录音还需依赖功能打开。比如 {@link #enableWakeup}</li>
1240     *     <li>false 录音机不可用,如果正在录音会关闭录音机</li>
1241     * </ul>
1242     * <p>
1243     *     从 setAudioRecordEnable(false) 到 setAudioRecordEnable(true) 后,
1244     *     还需要 {@linkplain #enableWakeup} 或者 {@linkplain Agent#startDialog()} 等方法触发录音操作
1245     * </p>
1246     *
1247     * @param enable true 录音机可用,false 不可用
1248     * @throws DDSNotInitCompleteException
1249     */
1250    public void setAudioRecordEnable(boolean enable) throws DDSNotInitCompleteException {
1251        checkInitComplete();
1252        final BusClient bc = DDS.getInstance().getAgent().getBusClient();
1253        RecorderTopicUtil.publishRecorderEnableByUser(bc, enable);
1254    }
1255
1256    /**
1257     * 是否开启全局免唤醒功能
1258     * <p>
1259     *
1260     * @param enable true: 允许全局免唤醒, false: 不允许全局免唤醒
1261     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1262     */
1263    public void enableGlobalWakeup(boolean enable) throws DDSNotInitCompleteException {
1264        checkInitComplete();
1265        AILog.userI(TAG, "enableGlobalWakeup input =", enable);
1266        BusClient busClient = DDS.getInstance().getAgent().getBusClient();
1267        GlobalAsrWakeupTopicUtil.publishGlobalCtrl(busClient, enable);
1268    }
1269
1270    /**
1271     * 允许识别过程中响应唤醒
1272     * <p>
1273     *
1274     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1275     */
1276    public void enableWakeupWhenAsr() throws DDSNotInitCompleteException {
1277        checkInitComplete();
1278
1279        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1280        WakeupTopicUtil.publishAsrWakeupCtrl(bc, false);
1281    }
1282
1283    /**
1284     * 不允许识别过程中响应唤醒
1285     * <p>
1286     *
1287     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1288     */
1289    public void disableWakeupWhenAsr() throws DDSNotInitCompleteException {
1290        checkInitComplete();
1291
1292        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1293        WakeupTopicUtil.publishAsrWakeupCtrl(bc, true);
1294    }
1295
1296    /**
1297     * 关闭唤醒
1298     *
1299     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1300     */
1301    public void disableWakeup() throws DDSNotInitCompleteException {
1302        checkInitComplete();
1303        AILog.userI(TAG, "disableWakeup");
1304//        setNearWakeupParams(0);
1305        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1306        WakeupTopicUtil.publishStickyAgentSettings(bc, "wakeup", false);
1307    }
1308
1309    /**
1310     * 动态设置对话模式
1311     *
1312     * @param type 对话模式 partner
1313     */
1314    public void updateWkupRouter(String type) throws DDSNotInitCompleteException {
1315        checkInitComplete();
1316        AILog.userI(TAG, "updateWkupRouter input =", type);
1317        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1318        WakeupTopicUtil.publishUpdateWakeupRouter(bc, type);
1319    }
1320
1321    /**
1322     * 设置是唤醒模块的模式(信号处理不变,环麦中暂不支持)
1323     *
1324     * @param mode 是否关闭唤醒 true-开启唤醒 ;false-关闭唤醒
1325     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1326     */
1327    public void setWakeupSwitch(boolean mode) throws DDSNotInitCompleteException {
1328        checkInitComplete();
1329        AILog.userI(TAG, "setWakeupSwitch input =", mode);
1330        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1331        WakeupTopicUtil.publishSetWakeupSwitch(bc, mode ? 1 : 0);
1332    }
1333
1334    /**
1335     * 从1.2.16.1开始,内核不再支持此功能
1336     * 设置低功耗模式, 开启低功耗模式后, 唤醒功能不可用, cpu会降低
1337     *
1338     * @param mode 是否开启低功耗模式 true-开启 ;false-关闭
1339     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1340     */
1341    @Deprecated
1342    public void setLpSwitch(boolean mode) throws DDSNotInitCompleteException {
1343    }
1344
1345    /**
1346     * 动态切换就近唤醒功能(暂时支持线性双麦/线性四麦)
1347     *
1348     * @param enable 是否开启就近唤醒 true-开启 ;false-关闭
1349     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1350     */
1351    @Deprecated
1352    public void enableNearWakeup(boolean enable) throws DDSNotInitCompleteException {
1353//        checkInitComplete();
1354//        AILog.userI(TAG, "enableNearWakeup input =", enable);
1355//        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1356//        WakeupTopicUtil.publishNearWakeupSetEnable(bc, enable);
1357    }
1358
1359    /**
1360     * 拦截唤醒结果 wakeup.result,
1361     *
1362     * @param isCatch 是否拦截唤醒结果 true-拦截 ;false-取消拦截
1363     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1364     */
1365    public void catchWakeupResult(boolean isCatch) throws DDSNotInitCompleteException {
1366        checkInitComplete();
1367        AILog.userI(TAG, "catchWakeupResult input =", isCatch);
1368        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1369        WakeupTopicUtil.publishWhetherCatchWakeupResult(bc, isCatch);
1370    }
1371
1372    /**
1373     * 开启oneshot
1374     *
1375     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1376     */
1377    public void enableOneShot() throws DDSNotInitCompleteException {
1378        checkInitComplete();
1379        AILog.userI(TAG, "enableOneShot");
1380        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1381        WakeupTopicUtil.publishStickyOneshotCtrl(bc, "enable");
1382    }
1383
1384    /**
1385     * 关闭oneshot
1386     *
1387     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1388     */
1389    public void disableOneShot() throws DDSNotInitCompleteException {
1390        checkInitComplete();
1391        AILog.userI(TAG, "disableOneShot");
1392        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1393        WakeupTopicUtil.publishStickyOneshotCtrl(bc, "disable");
1394    }
1395
1396    /**
1397     * 获取当前oneshot开关状态,如果有本地接口调用开关,以本地接口调用优先。
1398     *
1399     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1400     */
1401    public boolean getOneshotState() throws DDSNotInitCompleteException {
1402        checkInitComplete();
1403        boolean oneshotState = LocalKeysConfigUtil.getOneshotEnable();
1404        AILog.userI(TAG, "getOneshotState result =", oneshotState);
1405        return oneshotState;
1406    }
1407
1408    /**
1409     * 获取当前的唤醒词
1410     *
1411     * @return String[] 唤醒词数组
1412     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1413     */
1414    public String[] getWakeupWords() throws DDSNotInitCompleteException {
1415        String[] result = mWordProxy.getWakeupWords();
1416        AILog.userI(TAG, "getWakeupWords result =", (result != null ? Arrays.toString(result) : "null"));
1417        return result;
1418    }
1419
1420    /**
1421     * 获取当前唤醒库版本号
1422     *
1423     * @return 唤醒库版本号
1424     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1425     */
1426    public String getWakeupVersion() throws DDSNotInitCompleteException {
1427        checkInitComplete();
1428        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1429        return WakeupCallUtil.callWakeupVersion(bc);
1430    }
1431
1432    /**
1433     * 获取主唤醒词列表,默认返回WakeupEngine所设置的主唤醒词,如果没有设置过则返回产品配置的主唤醒词。
1434     *
1435     * @return 唤醒词列表
1436     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1437     */
1438    public List<WakeupWord> getMainWakeupWords() throws DDSNotInitCompleteException {
1439        checkInitComplete();
1440        List<WakeupWord> wakeupWords = new ArrayList<>();
1441        JSONArray jsonArray = null;
1442        if (mBc != null) {
1443            String ret = mBc.call(Topic.Wakeup.CALL_WAKEUP_WAKEUP_WORD).getStringResult();
1444            try {
1445                jsonArray = new JSONArray(ret);
1446            } catch (Exception e) {
1447                e.printStackTrace();
1448            }
1449        }
1450        if (jsonArray != null)
1451            for (int i = 0; i < jsonArray.length(); i++) {
1452                JSONObject item = jsonArray.optJSONObject(i);
1453                if (item == null)
1454                    continue;
1455                // 通过type过滤主唤醒词
1456                String type = item.optString("type");
1457                if (!TextUtils.equals(type, "major")) {
1458                    continue;
1459                }
1460                WakeupWord w = new WakeupWord();
1461                w.setThreshold(String.format("%.4f", item.optDouble("threshold")),
1462                        String.format("%.4f", item.optDouble("thresh2")));
1463                w.setPinyin(item.optString("pinyin"));
1464                w.setWord(item.optString("name"));
1465                w.setDcheck(item.optString("dcheck"));
1466                w.setMajor(item.optString("major"));
1467                JSONArray greeting = item.optJSONArray("greeting");
1468                if (greeting != null) {
1469                    for (int j = 0; j < greeting.length(); j++) {
1470                        w.addGreeting(greeting.optString(j));
1471                    }
1472                }
1473                wakeupWords.add(w);
1474            }
1475        return wakeupWords;
1476    }
1477
1478    /**
1479     * 返回产品配置的主唤醒词
1480     *
1481     * @return 唤醒词列表
1482     */
1483    private List<WakeupWord> getMainWakeupWordsWithGlobalConfig() {
1484        String globalConfigs = "";
1485        List<WakeupWord> wakeupWords = null;
1486        globalConfigs = LocalKeysUtil.getInstance().getString(LocalKeys.Daemon.LOCAL_KEYS_GLOBAL_CONFIG);
1487        wakeupWords = new ArrayList<>();
1488        try {
1489            JSONObject object = new JSONObject(globalConfigs);
1490            if (object.has("pickup")) {
1491                JSONObject pickup = object.optJSONObject("pickup");
1492                JSONObject wakeup = null;
1493                if (pickup.has("far") && pickup.optJSONObject("far").optBoolean("enable")) {
1494                    wakeup = pickup.optJSONObject("far").optJSONObject("wakeup");
1495                } else {
1496                    wakeup = pickup.optJSONObject("near").optJSONObject("wakeup");
1497                }
1498                if (wakeup != null) {
1499                    JSONArray array = wakeup.optJSONArray("majorword");
1500                    if (array != null) {
1501                        for (int i = 0; i < array.length(); i++) {
1502                            WakeupWord wakeupWord = new WakeupWord();
1503                            wakeupWord.setWord(array.optJSONObject(i).optString("name"));
1504                            wakeupWord.setThreshold(array.optJSONObject(i).optString("threshold"));
1505                            wakeupWord.setPinyin(array.optJSONObject(i).optString("pinyin"));
1506                            JSONArray greeting = array.optJSONObject(i).optJSONArray("greeting");
1507                            ArrayList<String> list = new ArrayList<>();
1508                            if (greeting != null) {
1509                                for (int j = 0; j < greeting.length(); j++) {
1510                                    list.add(greeting.optString(j));
1511                                }
1512                                wakeupWord.setGreetings(list);
1513                            }
1514                            wakeupWords.add(wakeupWord);
1515                        }
1516                    }
1517                    return wakeupWords;
1518                }
1519            }
1520        } catch (JSONException e) {
1521            com.aispeech.dui.manager.AIJavaException.printException(e);
1522        }
1523        return wakeupWords;
1524    }
1525
1526
1527    /**
1528     * 动态设置是否在唤醒中启用声纹
1529     * <p>
1530     *
1531     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1532     */
1533    public void useVprintInWakeUp(boolean enable) throws DDSNotInitCompleteException {
1534        checkInitComplete();
1535        AILog.userI(TAG, "useVprintInWakeUp result =", enable);
1536
1537        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1538        WakeupTopicUtil.publishUseVprintInWakeUp(bc, enable);
1539    }
1540
1541    /**
1542     * 动态设置是否在唤醒中启用Asrpp
1543     * <p>
1544     *
1545     * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
1546     */
1547    public void useAsrPPInWakeUp(boolean enable) throws DDSNotInitCompleteException {
1548        checkInitComplete();
1549        AILog.userI(TAG, "useAsrPPInWakeUp result =", enable);
1550
1551        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1552        WakeupTopicUtil.publishUseAsrPPInWakeUp(bc, enable);
1553    }
1554
1555    /**
1556     * 动态设置唤醒词优先级
1557     */
1558    @Deprecated
1559    public void setWakeupPriority(WakeupPriorityType type, boolean priority) throws DDSNotInitCompleteException {
1560        checkInitComplete();
1561        AILog.userI(TAG, "setWakeupPriority type =", type.name(), ", priority =", priority);
1562//        LocalKeysConfigUtil.WakeupWordPriority.setWakeupPriority(type.name(), priority);
1563    }
1564
1565    /**
1566     * 非对话情况下不使用可见即可说词
1567     * @param disable
1568     * @throws DDSNotInitCompleteException
1569     * @replace disableIncrementWakeup()
1570     */
1571    @Deprecated
1572    public void disableHotwordOutOfDialog(boolean disable) throws DDSNotInitCompleteException {
1573        checkInitComplete();
1574        AILog.userI(TAG, "disableHotwordOutOfDialog disable =", disable);
1575//        LocalKeysConfigUtil.WakeupWordPriority.disableHotwordOutOfDialog(disable);
1576    }
1577
1578    private void checkInitComplete() throws DDSNotInitCompleteException {
1579        if (DDS.getInstance().getInitStatus() != DDS.INIT_COMPLETE_FULL) {
1580            throw new DDSNotInitCompleteException();
1581        }
1582    }
1583
1584    public void destroy() {
1585        if (mInstance != null) {
1586            if (mInstance.mNode != null) {
1587                mInstance.mNode.stop();
1588            }
1589            mInstance = null;
1590        }
1591    }
1592
1593    private List<WakeupWord> toWakeupWordList(WakeupWord wakeupWord) {
1594        List<WakeupWord> wakeupWordList = new ArrayList<>();
1595        if (wakeupWord != null) {
1596            wakeupWordList.add(wakeupWord);
1597        }
1598        return wakeupWordList;
1599    }
1600
1601    /**
1602     * 设置可见即可说不可用
1603     *
1604     * <p>
1605     */
1606    public void disableIncrementWakeup() throws DDSNotInitCompleteException {
1607        disableIncrementWakeup(JSONObjectUtil.create()
1608                .put(Topic.Wakeup.IncrementWakeupCtrl.TYPE, "all")
1609                .build());
1610    }
1611
1612    /**
1613     * 设置可见即可说不可用
1614     * inputObj : {"type":"all"}
1615     * type:
1616     *      all:所有
1617     *      hotWord:可见即可说词
1618     *      globalWord:全局免唤醒词
1619     */
1620    public void disableIncrementWakeup(JSONObject inputObj) throws DDSNotInitCompleteException {
1621        checkInitComplete();
1622        if (inputObj == null) {
1623            inputObj = new JSONObject();
1624        }
1625        JSONObjectUtil.put(inputObj, Topic.Wakeup.IncrementWakeupCtrl.USER_SET, true);
1626        JSONObjectUtil.put(inputObj, Topic.Wakeup.IncrementWakeupCtrl.CTRL, "stop");
1627        AILog.userI(TAG, "disableIncrementWakeup inputData =", inputObj);
1628        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1629        WakeupTopicUtil.publishIncrementWakeupCtrl(bc, inputObj);
1630    }
1631
1632    /**
1633     * 设置可见即可说可用
1634     *
1635     * <p>
1636     */
1637    public void enableIncrementWakeup() throws DDSNotInitCompleteException {
1638        enableIncrementWakeup(JSONObjectUtil.create()
1639                .put(Topic.Wakeup.IncrementWakeupCtrl.TYPE, "all")
1640                .build());
1641    }
1642
1643    /**
1644     * 设置可见即可说可用
1645     * inputObj : {"type":"all"}
1646     * type:
1647     *      all 所有
1648     *      hotWord 可见即可说词
1649     *      globalWord  全局免唤醒词
1650     */
1651    public void enableIncrementWakeup(JSONObject inputObj) throws DDSNotInitCompleteException {
1652        checkInitComplete();
1653        if (inputObj == null) {
1654            inputObj = new JSONObject();
1655        }
1656        JSONObjectUtil.put(inputObj, Topic.Wakeup.IncrementWakeupCtrl.USER_SET, true);
1657        AILog.userI(TAG, "enableIncrementWakeup inputData =", inputObj);
1658        JSONObjectUtil.put(inputObj, Topic.Wakeup.IncrementWakeupCtrl.CTRL, "start");
1659        BusClient bc = DDS.getInstance().getAgent().getBusClient();
1660        WakeupTopicUtil.publishIncrementWakeupCtrl(bc, inputObj);
1661    }
1662
1663    /**
1664     * 如果可见即可说和全局免唤醒词有相同的词,设置哪一个优先响应, 默认可见即可说优先
1665     * @param type
1666     * WakeupPriorityType.HOTWORD_FIRST : 可见即可说优先
1667     * WakeupPriorityType.GLOBALWORD_FIRST : 全局免唤醒优先
1668     * @throws DDSNotInitCompleteException
1669     */
1670    public void setIncrementPriority(WakeupPriorityType type) throws DDSNotInitCompleteException {
1671        checkInitComplete();
1672        AILog.userI(TAG, "setIncrementPriority type =", type.name());
1673        LocalKeysConfigUtil.IncrementPriority.setPriority(type.name());
1674    }
1675}