diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..90bcf39
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+
+agent/tools/IotmService.py
diff --git a/README.md b/README.md
index d582b68..d8dd6ed 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@
-**12月迟来的报到,Fay数字人 AI Agent版(含智慧农业箱的操作demo代码,如果你需要完整代码可以公众号留言申请获取)第4版正式上传!**
+**12月迟来的报到,Fay数字人 AI Agent版(含智慧农业箱的操作demo代码,如果你需要完整代码可以公众号留言申请获取)第5版正式上传!**
如果你需要是一个线上线下的销售员,请移步[`带货完整版`](https://github.com/TheRamU/Fay/tree/fay-sales-edition)
@@ -55,9 +55,29 @@ python main.py
### **启动数字人(非必须)**
-+ 启动数字人[xszyou/fay-ue5: 可对接fay数字人的ue5工程 (github.com)](https://github.com/xszyou/fay-ue5)
++ 仓库地址:https://github.com/xszyou/fay-ue5
+
+### **启动android 连接器(非必须)**
+
++ 仓库地址:https://github.com/xszyou/fay-android
+
+### **更新日志**
+2023.12.25:
+
+*实现agent ReAct与LLM chain自动切换逻辑✓
+
+聊天窗区分任务消息✓
+
+修复删除日程bug✓
+
+优化远程音频逻辑✓
+
+等待处理引入加载中效果✓
+
+优化prompt以解决日程任务递归调用问题✓
+
+修复一次性日程清除的bug✓
-
### **联系**
diff --git a/README_EN.md b/README_EN.md
index 5e33e37..85457ae 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -11,7 +11,7 @@
-**Belated December announcement, the 4th edition of Fay Digital Human AI Agent Version (complete code for smart agriculture box can be requested via our public channel) is officially uploaded!**
+**Belated December announcement, the 5th edition of Fay Digital Human AI Agent Version (complete code for smart agriculture box can be requested via our public channel) is officially uploaded!**
If you need an online and offline salesperson, please go to [`Complete Retail Version`](https://github.com/TheRamU/Fay/tree/fay-sales-edition)
@@ -52,9 +52,29 @@ python main.py
### **Launching the Digital Human (Optional)**
-+ Launch the digital human[xszyou/fay-ue5: 可对接fay数字人的ue5工程 (github.com)](https://github.com/xszyou/fay-ue5)
+Repository URL:https://github.com/xszyou/fay-ue5
+
+
+### **Launch of Android Connector (Optional)**
+Repository URL: https://github.com/xszyou/fay-android
+
+
+### **Changelog**
+2023.12.25:
+
+Implemented the automatic switching logic between agent ReAct and LLM chain ✓
+Distinguished task messages in the chat window ✓
+
+Fixed the bug in deleting schedules ✓
+
+Optimized remote audio logic ✓
+
+Introduced loading effects for pending processes ✓
+
+Optimized prompts to resolve recursive calling issues in schedule tasks ✓
+
+Fixed the bug in clearing one-time schedules ✓
-
### **Contact**
diff --git a/agent/agent_service.py b/agent/agent_service.py
index 3cdf053..d006538 100644
--- a/agent/agent_service.py
+++ b/agent/agent_service.py
@@ -8,6 +8,7 @@ scheduled_tasks = {}
agent_running = False
agent = FayAgentCore()
+
# 数据库初始化
def init_db():
conn = sqlite3.connect('timer.db')
@@ -51,8 +52,7 @@ def parse_repeat_rule(rule, task_time):
# 执行任务
def execute_task(task_time, id, content):
- content = "执行任务->现在" + content
- agent.run(content)
+ agent.run("执行任务->立刻" + content)
del scheduled_tasks[id]
# 如果不重复,执行后删除记录
conn = sqlite3.connect('timer.db')
@@ -90,7 +90,6 @@ def agent_start():
agent_running = True
init_db()
- # insert_test_data()
check_and_execute_thread = threading.Thread(target=check_and_execute)
check_and_execute_thread.start()
diff --git a/agent/fay_agent.py b/agent/fay_agent.py
index 1585088..71b3f2d 100644
--- a/agent/fay_agent.py
+++ b/agent/fay_agent.py
@@ -6,6 +6,7 @@ from langchain.docstore import InMemoryDocstore
from langchain.vectorstores import FAISS
from langchain.agents import AgentExecutor, Tool, ZeroShotAgent, initialize_agent, agent_types
from langchain.chains import LLMChain
+from langchain.prompts import PromptTemplate
from agent.tools.MyTimer import MyTimer
from agent.tools.QueryTime import QueryTime
@@ -19,6 +20,8 @@ from agent.tools.QueryTimerDB import QueryTimerDB
from agent.tools.DeleteTimer import DeleteTimer
from agent.tools.GetSwitchLog import GetSwitchLog
from agent.tools.getOnRunLinkage import getOnRunLinkage
+from agent.tools.SetChatStatus import SetChatStatus
+
import utils.config_util as utils
from core.content_db import Content_Db
@@ -26,6 +29,7 @@ from core import wsa_server
import os
+
class FayAgentCore():
def __init__(self):
@@ -64,6 +68,7 @@ class FayAgentCore():
delete_timer_tool = DeleteTimer()
get_switch_log = GetSwitchLog()
get_on_run_linkage = getOnRunLinkage()
+ set_chat_status_tool = SetChatStatus()
tools = [
Tool(
@@ -126,22 +131,57 @@ class FayAgentCore():
func=get_on_run_linkage.run,
description=get_on_run_linkage.description
),
+ Tool(
+ name=set_chat_status_tool.name,
+ func=set_chat_status_tool.run,
+ description=set_chat_status_tool.description
+ ),
]
-
+ #agent用于执行任务
self.agent = initialize_agent(agent_types=agent_types.AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION,
tools=tools, llm=llm, verbose=True,
max_history=5,
memory=memory, handle_parsing_errors=True)
+
+ #创建llm chain用于聊天
+ tools_prompt = "["
+ tool_names = [tool.name for tool in tools if tool.name != set_chat_status_tool.name and tool.name != say_tool.name]
+ tools_prompt += "、".join(tool_names) + "]"
+ template = """你是一个智慧农业实验箱里的ai,你的责任是陪伴主人生活、工作,以及协助主人打理好农业种植箱里的农作物.现在主人正在和你聊天,若你在聊天过程中感觉到主人想使用以下工具,请按“agent:'主人刚刚的说话'”这样的格式回复,否则请直接回复我文字内容。工具如下:
+ """ + tools_prompt +"""
+ {chat_history}
+ Human: {human_input}
+ AI:"""
+ prompt = PromptTemplate(
+ input_variables=["chat_history", "human_input"], template=template
+ )
+ self.llm_chain = LLMChain(
+ llm=llm,
+ prompt=prompt,
+ verbose=True,
+ memory=memory
+ )
+
+ self.is_chat = False#聊天状态
+
def run(self, input_text):
#消息保存
contentdb = Content_Db()
contentdb.add_content('member', 'agent', input_text.replace('主人语音说了:', '').replace('主人文字说了:', ''))
wsa_server.get_web_instance().add_cmd({"panelReply": {"type":"member","content":input_text.replace('主人语音说了:', '').replace('主人文字说了:', '')}})
- result = None
+ result = ""
try:
- result = self.agent.run(input_text)
+ #判断执行聊天模式还是agent模式,双模式在运行过程中会主动切换
+ if self.is_chat:
+ result = self.llm_chain.predict(human_input=input_text.replace('主人语音说了:', '').replace('主人文字说了:', ''))
+ if "agent:" in result.lower() or not self.is_chat:
+ print(result)
+ print(self.is_chat)
+ self.is_chat = False
+ input_text = result if result.lower().replace("agent:", "") else input_text
+ result = self.agent.run(input_text)
except Exception as e:
print(e)
result = "执行完毕" if result is None or result == "N/A" else result
diff --git a/agent/tools/GetSwitchLog.py b/agent/tools/GetSwitchLog.py
index 54ee251..8a3b318 100644
--- a/agent/tools/GetSwitchLog.py
+++ b/agent/tools/GetSwitchLog.py
@@ -2,11 +2,11 @@ import os
from typing import Any
from langchain.tools import BaseTool
-import agent.tools.IotmService as IotmService
+import tools.IotmService as IotmService
class GetSwitchLog(BaseTool):
name = "GetSwitchLog"
- description = "此工具用于查询农业箱的设备开关操作历史记录,设备序号:小风扇(1)、电热风扇(2)、制冷风扇(3)、肥料开关(4)、补光设备(5)、植物生长灯(6)、二氧化碳(7)"
+ description = "此工具用于查询农业箱的设备开关当天的操作历史记录"
def __init__(self):
super().__init__()
@@ -16,10 +16,31 @@ class GetSwitchLog(BaseTool):
pass
- def _run(self, para: str) -> str:
- infos = IotmService.get_switch_log()
-
- return infos
+ def _run(self, para: str):
+ logs = IotmService.get_switch_log()
+ device_logs = {}
+
+ switch_mapping = {
+ 1: '小风扇',
+ 2: '电热风扇',
+ 3: '制冷风扇',
+ 4: '水开关',
+ 5: '肥料开关',
+ 6: '植物生长灯',
+ 7: '二氧化碳'
+ }
+
+ for val in logs:
+ switch_name = switch_mapping[val['number']]
+ status = 'on' if val['status'] == 1 else 'off'
+ info = val['timetText']
+
+ if switch_name not in device_logs:
+ device_logs[switch_name] = {'on': [], 'off': []}
+
+ device_logs[switch_name][status].append(info)
+
+ return device_logs
if __name__ == "__main__":
tool = GetSwitchLog()
diff --git a/agent/tools/Knowledge.py b/agent/tools/Knowledge.py
index 4308cf5..a59066c 100644
--- a/agent/tools/Knowledge.py
+++ b/agent/tools/Knowledge.py
@@ -7,7 +7,7 @@ from langchain.tools import BaseTool
class Knowledge(BaseTool):
name = "Knowledge"
- description = """此工具用于查询箱内植物的专业知识,可以作为补充参考,使用时请传入相关问题作为参数,例如:“草梅最适合的生长温度”"""
+ description = """此工具用于查询箱内植物的专业知识,使用时请传入相关问题作为参数,例如:“草梅最适合的生长温度”"""
def __init__(self):
super().__init__()
diff --git a/agent/tools/Say.py b/agent/tools/Say.py
index 43f1aa9..ae59bdf 100644
--- a/agent/tools/Say.py
+++ b/agent/tools/Say.py
@@ -5,11 +5,12 @@ import requests
from langchain.tools import BaseTool
import fay_booter
from core.interact import Interact
+from agent import agent_service
class Say(BaseTool):
- name = "Say"
- description = """此工具用于沟通及提醒,使用时请传入说话内容作为参数,例如:“该下班了,请注意休息”"""
+ name = "语音输出工具"
+ description = """此工具用于语音输出,使用时请传入说话内容作为参数,例如:“该下班了,请注意休息”"""
def __init__(self):
super().__init__()
@@ -20,8 +21,9 @@ class Say(BaseTool):
def _run(self, para: str) -> str:
- interact = Interact("agent", 1, {'user': '', 'msg': para})
+ interact = Interact("audio", 1, {'user': '', 'msg': para})
fay_booter.feiFei.on_interact(interact)
+ agent_service.agent.is_chat = True
return "语音输出了:" + para
diff --git a/agent/tools/SetChatStatus.py b/agent/tools/SetChatStatus.py
new file mode 100644
index 0000000..7f23b59
--- /dev/null
+++ b/agent/tools/SetChatStatus.py
@@ -0,0 +1,29 @@
+import os
+from typing import Any
+
+from langchain.tools import BaseTool
+from agent import agent_service
+
+
+class SetChatStatus(BaseTool):
+ name = "SetChatStatus"
+ description = """此工具用于设置聊天状态,当识别到主人想进行交流聊天时使用此工具"""
+
+ def __init__(self):
+ super().__init__()
+
+ async def _arun(self, *args: Any, **kwargs: Any) -> Any:
+ # 用例中没有用到 arun 不予具体实现
+ pass
+
+
+ def _run(self, para: str) -> str:
+ agent_service.agent.is_chat = True
+ return "设置聊天状态成功"
+
+
+
+if __name__ == "__main__":
+ tool = SetChatStatus()
+ info = tool.run("该下班了,请注意休息")
+ print(info)
diff --git a/agent/tools/getOnRunLinkage.py b/agent/tools/getOnRunLinkage.py
index 5a2d9ab..1a8a124 100644
--- a/agent/tools/getOnRunLinkage.py
+++ b/agent/tools/getOnRunLinkage.py
@@ -1,12 +1,13 @@
import os
from typing import Any
+from itertools import groupby
from langchain.tools import BaseTool
-import agent.tools.IotmService as IotmService
+import tools.IotmService as IotmService
class getOnRunLinkage(BaseTool):
name = "getOnRunLinkage"
- description = "此工具用于查询农业箱当前在运行的联动,设备序号:小风扇(1)、电热风扇(2)、制冷风扇(3)、肥料开关(4)、补光设备(5)、植物生长灯(6)、二氧化碳(7)"
+ description = "此工具用于查询农业箱当前在运行的联动"
def __init__(self):
super().__init__()
@@ -17,9 +18,45 @@ class getOnRunLinkage(BaseTool):
def _run(self, para: str) -> str:
- infos = IotmService.get_on_run_linkage()
- return infos
+ logs = IotmService.get_on_run_linkage()
+ desc_list = {
+ 'co2_S36': '二氧化碳',
+ 'light_bh1': '箱内的光照强度',
+ 'air_S37': '污染气体',
+ 'nh3_S37': '氨气',
+ 'temperature_MP14': '箱外温度',
+ 'temperature_MP21': '箱内温度',
+ 'humidity_MP14': '箱外湿度',
+ 'humidity_S34': '箱内土壤的湿度',
+ }
+ infos = {}
+
+ logs.sort(key=lambda x: (x['label'], x['port']))
+
+ for (sensor_type, port), group in groupby(logs, key=lambda x: (x['label'], x['port'])):
+
+ group_infos = []
+ for val in group:
+
+ onoff = '开启设备开关' if val['onoff'] == 1 else '关闭设备开关'
+
+ info = {
+ 'max': val['maxVal'],
+ 'min': val['minVal'],
+ 'onoff': onoff,
+ }
+ if float(val['keeptime']) > 0:
+ info["持续时间(若需执行开启设备,持续时间过后执行关闭),单位为分钟"] = val['keeptime']
+ if float(val['delaytime']) > 0:
+ info["执行后下次检查相距时间,单位为分钟"] = val['delaytime']
+
+ group_infos.append(info)
+
+ key_str = f"{sensor_type}_{port}"
+ infos[desc_list.get(key_str, 'Unknown')] = group_infos
+
+ return infos
if __name__ == "__main__":
tool = getOnRunLinkage()
info = tool.run("")
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.gitignore b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.gitignore
deleted file mode 100644
index aa724b7..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.gitignore
+++ /dev/null
@@ -1,15 +0,0 @@
-*.iml
-.gradle
-/local.properties
-/.idea/caches
-/.idea/libraries
-/.idea/modules.xml
-/.idea/workspace.xml
-/.idea/navEditor.xml
-/.idea/assetWizardSettings.xml
-.DS_Store
-/build
-/captures
-.externalNativeBuild
-.cxx
-local.properties
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.idea/.gitignore b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.idea/.gitignore
deleted file mode 100644
index 26d3352..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.idea/compiler.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.idea/compiler.xml
deleted file mode 100644
index fb7f4a8..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.idea/compiler.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.idea/gradle.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.idea/gradle.xml
deleted file mode 100644
index a2d7c21..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.idea/gradle.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.idea/misc.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.idea/misc.xml
deleted file mode 100644
index 1166903..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/.idea/misc.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/.gitignore b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/.gitignore
deleted file mode 100644
index 42afabf..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/build.gradle b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/build.gradle
deleted file mode 100644
index 593724e..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/build.gradle
+++ /dev/null
@@ -1,38 +0,0 @@
-plugins {
- id 'com.android.application'
-}
-
-android {
- compileSdk 32
-
- defaultConfig {
- applicationId "com.yaheen.fayconnectordemo"
- minSdk 29
- targetSdk 32
- versionCode 1
- versionName "1.0"
-
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- }
-
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
-}
-
-dependencies {
-
- implementation 'androidx.appcompat:appcompat:1.3.0'
- implementation 'com.google.android.material:material:1.4.0'
- implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
- testImplementation 'junit:junit:4.13.2'
- androidTestImplementation 'androidx.test.ext:junit:1.1.3'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
-}
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/proguard-rules.pro b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/proguard-rules.pro
deleted file mode 100644
index 481bb43..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/proguard-rules.pro
+++ /dev/null
@@ -1,21 +0,0 @@
-# Add project specific ProGuard rules here.
-# You can control the set of applied configuration files using the
-# proguardFiles setting in build.gradle.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
-
-# Uncomment this to preserve the line number information for
-# debugging stack traces.
-#-keepattributes SourceFile,LineNumberTable
-
-# If you keep the line number information, uncomment this to
-# hide the original source file name.
-#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/androidTest/java/com/yaheen/fayconnectordemo/ExampleInstrumentedTest.java b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/androidTest/java/com/yaheen/fayconnectordemo/ExampleInstrumentedTest.java
deleted file mode 100644
index 3035a79..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/androidTest/java/com/yaheen/fayconnectordemo/ExampleInstrumentedTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.yaheen.fayconnectordemo;
-
-import android.content.Context;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.junit.Assert.*;
-
-/**
- * Instrumented test, which will execute on an Android device.
- *
- * @see Testing documentation
- */
-@RunWith(AndroidJUnit4.class)
-public class ExampleInstrumentedTest {
- @Test
- public void useAppContext() {
- // Context of the app under test.
- Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
- assertEquals("com.yaheen.fayconnectordemo", appContext.getPackageName());
- }
-}
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/AndroidManifest.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/AndroidManifest.xml
deleted file mode 100644
index 4526265..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/java/com/yaheen/fayconnectordemo/FayConnectorService.java b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/java/com/yaheen/fayconnectordemo/FayConnectorService.java
deleted file mode 100644
index b62dd51..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/java/com/yaheen/fayconnectordemo/FayConnectorService.java
+++ /dev/null
@@ -1,343 +0,0 @@
-package com.yaheen.fayconnectordemo;
-
-import android.Manifest;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.graphics.BitmapFactory;
-import android.media.AudioFormat;
-import android.media.AudioManager;
-import android.media.AudioRecord;
-import android.media.MediaPlayer;
-import android.media.MediaRecorder;
-import android.os.Build;
-import android.os.IBinder;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-import androidx.core.app.ActivityCompat;
-import androidx.core.app.NotificationCompat;
-import androidx.core.app.NotificationManagerCompat;
-import androidx.core.content.ContextCompat;
-
-import com.google.android.material.snackbar.Snackbar;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Socket;
-import java.util.Arrays;
-import java.util.Date;
-
-public class FayConnectorService extends Service {
- private AudioRecord record;
- private int recordBufsize = 0;
- private Socket socket = null;
- private InputStream in = null;
- private OutputStream out = null;
- public static boolean running = false;
- private File cacheDir = null;
- private String channelId = null;
- private PendingIntent pendingIntent = null;
- private NotificationManagerCompat notificationManager = null;
- private long totalrece = 0;
- private long totalsend = 0;
- private AudioManager mAudioManager = null;
- private boolean isPlay = false;
-
-
- //创建通知
- private String createNotificationChannel(String channelID, String channelNAME, int level) {
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
- NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
- NotificationChannel channel = new NotificationChannel(channelID, channelNAME, level);
- manager.createNotificationChannel(channel);
- return channelID;
- } else {
- return null;
- }
- }
-
-
- @Nullable
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- super.onStartCommand(intent, START_FLAG_REDELIVERY, startId);
- return Service.START_STICKY;
-
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- Log.d("fay", "服务启动");
-
-
-
- //开启蓝牙传输
- mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- mAudioManager.startBluetoothSco();
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
- BroadcastReceiver receiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
- if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) {
- Log.d("fay", "蓝牙sco连接成功");
-
-
- }
- }
- };
- this.registerReceiver(receiver, intentFilter);
-
- running = true;
- this.cacheDir = getApplicationContext().getFilesDir();//getCacheDir();
- Thread sendThread = new Thread(new Runnable() {
- @Override
- public void run() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- if (ContextCompat.checkSelfPermission(FayConnectorService.this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
- if (record == null) {
- recordBufsize = AudioRecord
- .getMinBufferSize(16000,
- AudioFormat.CHANNEL_IN_MONO,
- AudioFormat.ENCODING_PCM_16BIT);
- record = new AudioRecord(MediaRecorder.AudioSource.MIC,
- 16000,
- AudioFormat.CHANNEL_IN_MONO,
- AudioFormat.ENCODING_PCM_16BIT,
- recordBufsize);
-
- }
- try {
- socket = new Socket("192.168.1.101", 10001);
- in = socket.getInputStream();
- out = socket.getOutputStream();
- Log.d("fay", "fay控制器连接成功");
- } catch (IOException e) {
- Log.d("fay", "socket连接失败");
- running = false;
- return;
- }
- byte[] data = new byte[1024];
- record.startRecording();
- Log.d("fay", "麦克风启动成功");
- try {
- Log.d("fay", "开始传输音频");
- while (running) {
- if (isPlay){
- continue;
- }
- int size = record.read(data, 0, 1024);
- if (size > 0) {
- out.write(data);
- totalsend += data.length / 1024;
- }else{//录音异常,等待60秒重新录取
- try {
- Thread.sleep(60000);
- record.stop();
- record.startRecording();
- }catch (Exception e){
- }
- }
- }
- } catch (Exception e) { //通过异常关退出循环
- Log.d("fay", "服务端关闭:" + e.toString());
- } finally {
- running = false;
- record.stop();
- record = null;
- ((AudioManager) getSystemService(Context.AUDIO_SERVICE)).stopBluetoothSco();
- try {
- socket.close();
- } catch (Exception e) {
- }
- socket = null;
- Log.d("fay", "send线程结束");
-
- }
-
- }
- }
-
- }
- });
-
-
- Thread receThread = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- while (running) {
- while (socket != null && !socket.isClosed()) {
- byte[] data = new byte[9];
- byte[] wavhead = new byte[]{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};//文件传输开始标记
- in.read(data);
- if (Arrays.equals(wavhead, data)) {
- Log.d("fay", "开始接收音频文件");
- String filedata = "";
- data = new byte[1024];
- int len = 0;
- while ((len = in.read(data)) != -1) {
- byte[] temp = new byte[len];
- System.arraycopy(data, 0, temp, 0, len);
- filedata += MainActivity.bytesToHexString(temp);
- int index = filedata.indexOf("080706050403020100");
- if (filedata.length() > 9 && index > 0) {//wav文件结束标记
- filedata = filedata.substring(0, index).replaceAll("F0F1F2F3F4F5F6F7F8", "");
- File wavFile = new File(cacheDir, String.format("sample-%s.wav", new Date().getTime() + ""));
- wavFile.createNewFile();
- FileOutputStream fos = new FileOutputStream(wavFile);
- fos.write(MainActivity.decodeHexBytes(filedata.toCharArray()));
- fos.close();
- totalrece += filedata.length() / 2 / 1024;
- Log.d("fay", "wav文件接收完成:" + wavFile.getAbsolutePath() + "," + filedata.length() / 2);
- try {
- MediaPlayer player = new MediaPlayer();
- player.setDataSource(wavFile.getAbsolutePath());
- player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
- @Override
- public void onPrepared(MediaPlayer mp) {
- Log.d("fay", "开始播放");
- if (mAudioManager.isBluetoothScoOn()){
- mAudioManager.stopBluetoothSco();
- mAudioManager.setBluetoothScoOn(false);
- mAudioManager.setMode(mAudioManager.MODE_NORMAL);
- }
- try {
- Thread.sleep(500);
- }catch (Exception e){
-
- }
- isPlay = true;
- mp.start();
- }
- });
- player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
-
- @Override
- public void onCompletion(MediaPlayer mp) {
- Log.d("fay", "播放完成");
- isPlay = false;
- mp.release();
- mAudioManager.startBluetoothSco();
- mAudioManager.setMode(mAudioManager.MODE_IN_CALL);
- mAudioManager.setBluetoothScoOn(true);
-
-
- }
-
- });
- player.setVolume(1,1);
- player.setLooping(false);
- player.prepareAsync();
-
- } catch (IOException e) {
- Log.e("fay", e.toString());
- }
- break;
- }
-
- }
- try {
- Thread.sleep(1000);
- } catch (Exception e) {
-
- }
-
- }
- }
- try {
- Thread.sleep(1000);
- } catch (Exception e) {
-
- }
-
- }
- } catch (Exception e) {//通过异常判断socket已经关闭,退出循环
-
- } finally {
- Log.d("fay", "rece线程结束");
-
- }
- }
- });
- sendThread.start();
- receThread.start();
-
- //通知栏
- new Thread(new Runnable() {
- @Override
- public void run() {
- try{
- while (running) {
- Thread.sleep(3000);
- if (totalsend + totalrece > 2048){
- inotify("fay connector demo", "已经连接fay控制器,累计接收/发送:" + String.format("%.2f", (double)totalrece / 1024) + "/" + String.format("%.2f", (double)totalsend / 1024) + "MB");
- } else {
- inotify("fay connector demo", "已经连接fay控制器,累计接收/发送:" + totalrece + "/" + totalsend + "KB");
- }
- }
- inotify("fay connector demo", "已经断开fay控制器");
- }catch (Exception e){
- Log.e("fay", e.toString());
- }finally {
- FayConnectorService.this.stopSelf();
- }
- }
- }).start();
-
-
- }
-
- private void inotify(String title, String content){
- Intent intent = new Intent(this, MainActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- if (pendingIntent == null){
- pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
- }
- if (channelId == null){
- channelId = createNotificationChannel("my_channel_ID", "my_channel_NAME", NotificationManager.IMPORTANCE_HIGH);
- }
- if (notificationManager == null){
- notificationManager = NotificationManagerCompat.from(this);
- }
- NotificationCompat.Builder notification2 = new NotificationCompat.Builder(FayConnectorService.this, channelId)
- .setContentTitle(title)
- .setContentText(content)
- .setContentIntent(pendingIntent)
- .setSmallIcon(R.drawable.icon)
- .setPriority(NotificationCompat.PRIORITY_HIGH)
- .setAutoCancel(true);
- //notificationManager.notify(100, notification2.build());
- startForeground(100, notification2.build());
- }
-
-
-
-
- @Override
- public void onDestroy() {
- Log.d("fay", "服务关闭");
- super.onDestroy();
- mAudioManager.stopBluetoothSco();
- running = false;
- stopForeground(true);
- }
-}
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/java/com/yaheen/fayconnectordemo/MainActivity.java b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/java/com/yaheen/fayconnectordemo/MainActivity.java
deleted file mode 100644
index 6164ca8..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/java/com/yaheen/fayconnectordemo/MainActivity.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package com.yaheen.fayconnectordemo;
-
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.core.app.ActivityCompat;
-import androidx.core.content.ContextCompat;
-
-import android.Manifest;
-import android.app.ActivityManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.media.AudioFormat;
-import android.media.AudioManager;
-import android.media.AudioRecord;
-import android.media.MediaPlayer;
-import android.media.MediaRecorder;
-import android.os.Build;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.View;
-import android.widget.TextView;
-
-import com.google.android.material.snackbar.Snackbar;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Socket;
-import java.net.SocketException;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-
-public class MainActivity extends AppCompatActivity {
- private TextView tv = null;
- private boolean running = false;
- private Intent serviceIntent = null;
-
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- tv = this.findViewById(R.id.tv);
- serviceIntent = new Intent(this, FayConnectorService.class);
-
- //按钮点击
- tv.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Log.d("fay","onclick");
- running = FayConnectorService.running;//isServiceRunning();//同步service的运行状态,不好使!
- if (!running){//运行
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//开启
- if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
- if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.RECORD_AUDIO)) {
- Log.d("fay", "用户彻底拒绝了权限");
- return;
- } else {
- // 用户未彻底拒绝授予权限
- ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.RECORD_AUDIO}, 1);
- }
- }
-
- if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
- Log.d("fay","权限ok");
-
- Snackbar.make(view, "正在连接fay控制器", Snackbar.LENGTH_SHORT)
- .setAction("Action", null).show();
- startForegroundService(serviceIntent);
- running = true;
- }
- }
- } else{//关闭
- stopService(serviceIntent);
- Snackbar.make(view, "已经断开fay控制器", Snackbar.LENGTH_SHORT)
- .setAction("Action", null).show();
- running = false;
- }
-
- }
- });
- }
-
-
- public static String bytesToHexString(byte[] data){
- String result="";
- for (int i = 0; i < data.length; i++) {
- result+=Integer.toHexString((data[i] & 0xFF) | 0x100).toUpperCase().substring(1, 3);
- }
- return result;
- }
-
-
- public static byte[] decodeHexBytes(char[] data) {
- int len = data.length;
- if ((len & 0x01) != 0) {
- throw new RuntimeException("未知的字符");
- }
- byte[] out = new byte[len >> 1];
- for (int i = 0, j = 0; j < len; i++) {
- int f = toDigit(data[j], j) << 4;
- j++;
- f = f | toDigit(data[j], j);
- j++;
- out[i] = (byte) (f & 0xFF);
- }
- return out;
- }
-
- protected static int toDigit(char ch, int index) {
- int digit = Character.digit(ch, 16);
- if (digit == -1) {
- throw new RuntimeException("非法16进制字符 " + ch
- + " 在索引 " + index);
- }
- return digit;
- }
-
- private boolean isServiceRunning() {
- ActivityManager activityManager = (ActivityManager) this.getApplicationContext()
- .getSystemService(Context.ACTIVITY_SERVICE);
- ComponentName serviceName = new ComponentName("com.yaheen.fayconnectordemo", ".FayConnectorService");
- PendingIntent intent = activityManager.getRunningServiceControlPanel(serviceName);
- if (intent == null){
- return false;
- }
- return true;
-
- }
-}
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
deleted file mode 100644
index 2b068d1..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/drawable-v24/icon.png b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/drawable-v24/icon.png
deleted file mode 100644
index c66c4d3..0000000
Binary files a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/drawable-v24/icon.png and /dev/null differ
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/drawable/ic_launcher_background.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/drawable/ic_launcher_background.xml
deleted file mode 100644
index 07d5da9..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/drawable/ic_launcher_background.xml
+++ /dev/null
@@ -1,170 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/layout/activity_main.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/layout/activity_main.xml
deleted file mode 100644
index caf5670..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
deleted file mode 100644
index eca70cf..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
deleted file mode 100644
index eca70cf..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-hdpi/ic_launcher.webp
deleted file mode 100644
index c209e78..0000000
Binary files a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-hdpi/ic_launcher.webp and /dev/null differ
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
deleted file mode 100644
index b2dfe3d..0000000
Binary files a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-mdpi/ic_launcher.webp
deleted file mode 100644
index 4f0f1d6..0000000
Binary files a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-mdpi/ic_launcher.webp and /dev/null differ
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
deleted file mode 100644
index 62b611d..0000000
Binary files a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
deleted file mode 100644
index 948a307..0000000
Binary files a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xhdpi/ic_launcher.webp and /dev/null differ
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
deleted file mode 100644
index 1b9a695..0000000
Binary files a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
deleted file mode 100644
index 28d4b77..0000000
Binary files a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp and /dev/null differ
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
deleted file mode 100644
index 9287f50..0000000
Binary files a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
deleted file mode 100644
index aa7d642..0000000
Binary files a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and /dev/null differ
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
deleted file mode 100644
index 9126ae3..0000000
Binary files a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/values-night/themes.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/values-night/themes.xml
deleted file mode 100644
index 3fe0a9a..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/values-night/themes.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/values/colors.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/values/colors.xml
deleted file mode 100644
index f8c6127..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/values/colors.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
- #FFBB86FC
- #FF6200EE
- #FF3700B3
- #FF03DAC5
- #FF018786
- #FF000000
- #FFFFFFFF
-
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/values/strings.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/values/strings.xml
deleted file mode 100644
index 6fdadf3..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
- fayConnectorDemo
-
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/values/themes.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/values/themes.xml
deleted file mode 100644
index 215bbd4..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/values/themes.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/xml/backup_rules.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/xml/backup_rules.xml
deleted file mode 100644
index fa0f996..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/xml/backup_rules.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/xml/data_extraction_rules.xml b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/xml/data_extraction_rules.xml
deleted file mode 100644
index 9ee9997..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/main/res/xml/data_extraction_rules.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/test/java/com/yaheen/fayconnectordemo/ExampleUnitTest.java b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/test/java/com/yaheen/fayconnectordemo/ExampleUnitTest.java
deleted file mode 100644
index 1eee6ff..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/app/src/test/java/com/yaheen/fayconnectordemo/ExampleUnitTest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.yaheen.fayconnectordemo;
-
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * @see Testing documentation
- */
-public class ExampleUnitTest {
- @Test
- public void addition_isCorrect() {
- assertEquals(4, 2 + 2);
- }
-}
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/build.gradle b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/build.gradle
deleted file mode 100644
index a550ce3..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/build.gradle
+++ /dev/null
@@ -1,9 +0,0 @@
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
-plugins {
- id 'com.android.application' version '7.2.1' apply false
- id 'com.android.library' version '7.2.1' apply false
-}
-
-task clean(type: Delete) {
- delete rootProject.buildDir
-}
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradle.properties b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradle.properties
deleted file mode 100644
index dab7c28..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradle.properties
+++ /dev/null
@@ -1,21 +0,0 @@
-# Project-wide Gradle settings.
-# IDE (e.g. Android Studio) users:
-# Gradle settings configured through the IDE *will override*
-# any settings specified in this file.
-# For more details on how to configure your build environment visit
-# http://www.gradle.org/docs/current/userguide/build_environment.html
-# Specifies the JVM arguments used for the daemon process.
-# The setting is particularly useful for tweaking memory settings.
-org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
-# When configured, Gradle will run in incubating parallel mode.
-# This option should only be used with decoupled projects. More details, visit
-# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
-# org.gradle.parallel=true
-# AndroidX package structure to make it clearer which packages are bundled with the
-# Android operating system, and which are packaged with your app"s APK
-# https://developer.android.com/topic/libraries/support-library/androidx-rn
-android.useAndroidX=true
-# Enables namespacing of each library's R class so that its R class includes only the
-# resources declared in the library itself and none from the library's dependencies,
-# thereby reducing the size of the R class for that library
-android.nonTransitiveRClass=true
\ No newline at end of file
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradle/wrapper/gradle-wrapper.jar b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index e708b1c..0000000
Binary files a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradle/wrapper/gradle-wrapper.properties b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 3d3b352..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-#Fri Jan 20 09:27:45 CST 2023
-distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
-distributionPath=wrapper/dists
-zipStorePath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradlew b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradlew
deleted file mode 100644
index 4f906e0..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradlew
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-##############################################################################
-##
-## Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
- echo "$*"
-}
-
-die () {
- echo
- echo "$*"
- echo
- exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
- else
- JAVACMD="$JAVA_HOME/bin/java"
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
- fi
- i=`expr $i + 1`
- done
- case $i in
- 0) set -- ;;
- 1) set -- "$args0" ;;
- 2) set -- "$args0" "$args1" ;;
- 3) set -- "$args0" "$args1" "$args2" ;;
- 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
-fi
-
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=`save "$@"`
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-exec "$JAVACMD" "$@"
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradlew.bat b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradlew.bat
deleted file mode 100644
index 107acd3..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/gradlew.bat
+++ /dev/null
@@ -1,89 +0,0 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/settings.gradle b/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/settings.gradle
deleted file mode 100644
index 49e31ef..0000000
--- a/android_connector_demo/fayConnectorDemo-蓝牙service后台运行版/settings.gradle
+++ /dev/null
@@ -1,16 +0,0 @@
-pluginManagement {
- repositories {
- gradlePluginPortal()
- google()
- mavenCentral()
- }
-}
-dependencyResolutionManagement {
- repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
- repositories {
- google()
- mavenCentral()
- }
-}
-rootProject.name = "fayConnectorDemo"
-include ':app'
diff --git a/core/fay_core.py b/core/fay_core.py
index 4be5952..eb75723 100644
--- a/core/fay_core.py
+++ b/core/fay_core.py
@@ -33,7 +33,6 @@ if platform.system() == "Windows":
from test_olipsync import LipSyncGenerator
-
#文本消息处理(20231211增加:agent操作)
def send_for_answer(msg):
#记录运行时间
@@ -53,6 +52,11 @@ def send_for_answer(msg):
#agent 处理
text = agent_service.agent.run(msg)
+ #聊天模式语音输入语音输出
+ if text and "语音" in msg and agent_service.agent.is_chat:
+ interact = Interact("audio", 1, {'user': '', 'msg': text})
+ fay_booter.feiFei.on_interact(interact)
+
#推送数字人
if not cfg.config["interact"]["playSound"]:
content = {'Topic': 'Unreal', 'Data': {'Key': 'log', 'Value': text}}
@@ -240,7 +244,7 @@ class FeiFei:
# if audio_length <= config_util.config["interact"]["maxInteractTime"] or say_type == "script":
if config_util.config["interact"]["playSound"]: # 展板播放
self.__play_sound(file_url)
- else:#发送音频给ue和socket
+ else:#发送音频给ue
#推送ue
content = {'Topic': 'Unreal', 'Data': {'Key': 'audio', 'Value': os.path.abspath(file_url), 'Text': self.a_msg, 'Time': audio_length, 'Type': say_type}}
#计算lips
@@ -254,22 +258,22 @@ class FeiFei:
util.log(1, "唇型数字生成失败,无法使用新版ue5工程")
wsa_server.get_instance().add_cmd(content)
- #推送远程音频
- if self.deviceConnect is not None:
- try:
- self.deviceConnect.send(b'\x00\x01\x02\x03\x04\x05\x06\x07\x08') # 发送音频开始标志,同时也检查设备是否在线
- wavfile = open(os.path.abspath(file_url),'rb')
+ #推送远程音频
+ if self.deviceConnect is not None:
+ try:
+ self.deviceConnect.send(b'\x00\x01\x02\x03\x04\x05\x06\x07\x08') # 发送音频开始标志,同时也检查设备是否在线
+ wavfile = open(os.path.abspath(file_url),'rb')
+ data = wavfile.read(1024)
+ total = 0
+ while data:
+ total += len(data)
+ self.deviceConnect.send(data)
data = wavfile.read(1024)
- total = 0
- while data:
- total += len(data)
- self.deviceConnect.send(data)
- data = wavfile.read(1024)
- time.sleep(0.001)
- self.deviceConnect.send(b'\x08\x07\x06\x05\x04\x03\x02\x01\x00')# 发送音频结束标志
- util.log(1, "远程音频发送完成:{}".format(total))
- except socket.error as serr:
- util.log(1,"远程音频输入输出设备已经断开:{}".format(serr))
+ time.sleep(0.001)
+ self.deviceConnect.send(b'\x08\x07\x06\x05\x04\x03\x02\x01\x00')# 发送音频结束标志
+ util.log(1, "远程音频发送完成:{}".format(total))
+ except socket.error as serr:
+ util.log(1,"远程音频输入输出设备已经断开:{}".format(serr))
time.sleep(audio_length + 0.5)
wsa_server.get_web_instance().add_cmd({"panelMsg": ""})
diff --git a/core/recorder.py b/core/recorder.py
index c28ef7e..b83b10e 100644
--- a/core/recorder.py
+++ b/core/recorder.py
@@ -155,8 +155,7 @@ class Recorder:
if not data:
continue
-
- if cfg.config['source']['record']['enabled']:
+ if cfg.config['source']['record']['enabled'] and not self.is_remote():
if len(cfg.config['source']['record'])<3:
channels = 1
else:
@@ -167,7 +166,6 @@ class Recorder:
mono = data[:, 0] # taking the first channel
data = mono.tobytes()
-
level = audioop.rms(data, 2)
if len(self.__history_data) >= 5:
self.__history_data.pop(0)
@@ -229,3 +227,8 @@ class Recorder:
@abstractmethod
def get_stream(self):
pass
+
+ #TODO Edit by xszyou on 20231225:子类实现返回是否远程音频
+ @abstractmethod
+ def is_remote(self):
+ pass
diff --git a/fay_booter.py b/fay_booter.py
index e236e0d..0fa351e 100644
--- a/fay_booter.py
+++ b/fay_booter.py
@@ -71,7 +71,9 @@ class RecorderListener(Recorder):
except Exception as e:
print(e)
util.log(1, "请检查设备是否有误,再重新启动!")
-
+
+ def is_remote(self):
+ return False
@@ -129,6 +131,9 @@ class DeviceInputListener(Recorder):
def start_ngrok(self, clientId):
self.ngrok = ngrok_util.NgrokCilent(clientId)
self.ngrok.start()
+
+ def is_remote(self):
+ return True
diff --git a/gui/static/css/index.css b/gui/static/css/index.css
index 1cc0f39..fd66112 100644
--- a/gui/static/css/index.css
+++ b/gui/static/css/index.css
@@ -417,4 +417,32 @@ textarea {
border-radius: 10px;
background: rgba(0, 0, 0, 0);
-webkit-box-shadow: inset006pxrgba(0, 0, 0, 0.5);
-}
\ No newline at end of file
+}
+/* CSS 加载动画样式 */
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+ }
+
+ .loading-spinner {
+ border: 5px solid #f3f3f3; /* 轻颜色 */
+ border-top: 5px solid #3498db; /* 蓝色 */
+ border-radius: 50%;
+ width: 50px;
+ height: 50px;
+ animation: spin 2s linear infinite;
+ }
+ .spinner {
+ border: 4px solid rgba(0, 0, 0, 0.1);
+ border-radius: 50%;
+ border-top: 4px solid #3498db;
+ width: 10px;
+ height: 10px;
+ animation: spin 1s linear infinite;
+ }
+
+ @keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+ }
\ No newline at end of file
diff --git a/gui/static/js/index.js b/gui/static/js/index.js
index 40b550c..24eebb1 100644
--- a/gui/static/js/index.js
+++ b/gui/static/js/index.js
@@ -74,7 +74,8 @@ new Vue({
msg_list:[],
is_connect: false,
wake_word_enabled:false,
- wake_word: ''
+ wake_word: '',
+ loading: false
}
},
@@ -535,6 +536,12 @@ new Vue({
'type' : data['type'] ,
'way' : 'send'
}
+ console.log(info)
+ if (data['type'] == 'fay'){
+ _this.loading = false;
+ }else{
+ _this.loading = true;
+ }
_this.msg_list.push(info);
this.timer = setTimeout(()=>{ //设置延迟执行
diff --git a/gui/templates/index.html b/gui/templates/index.html
index 8a69a34..341f4a3 100644
--- a/gui/templates/index.html
+++ b/gui/templates/index.html
@@ -157,28 +157,32 @@
-
-
+
+
+
[[item.timetext]]
-
-
-
 }})
-
-
[[item.content]]
-
-
-
-
[[item.content]]
-
 }})
-
-
-
-
-
-
-
-
+
+
 }})
+
+
[[item.content]]
+
+
+
+
+
+
+
 }})
+
+
+
+
+
+
+
+
+
+