Skip to content

Commit d31901e

Browse files
committed
add iot framework
1 parent 43b1046 commit d31901e

27 files changed

+686
-76
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# CMakeLists in this exact order for cmake to work correctly
55
cmake_minimum_required(VERSION 3.16)
66

7-
set(PROJECT_VER "0.9.6")
7+
set(PROJECT_VER "0.9.7")
88

99
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
1010
project(xiaozhi)

main/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ set(SOURCES "audio_codecs/audio_codec.cc"
99
"protocols/protocol.cc"
1010
"protocols/mqtt_protocol.cc"
1111
"protocols/websocket_protocol.cc"
12+
"iot/thing.cc"
13+
"iot/thing_manager.cc"
1214
"system_info.cc"
1315
"application.cc"
1416
"ota.cc"
@@ -19,6 +21,10 @@ set(SOURCES "audio_codecs/audio_codec.cc"
1921

2022
set(INCLUDE_DIRS "." "display" "audio_codecs" "protocols" "audio_processing")
2123

24+
# 添加 IOT 相关文件
25+
file(GLOB IOT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/iot/things/*.cc)
26+
list(APPEND SOURCES ${IOT_SOURCES})
27+
2228
# 字体
2329
file(GLOB FONT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/fonts/*.c)
2430
list(APPEND SOURCES ${FONT_SOURCES})
@@ -44,6 +50,8 @@ elseif(CONFIG_BOARD_TYPE_KEVIN_C3)
4450
set(BOARD_TYPE "kevin-c3")
4551
elseif(CONFIG_BOARD_TYPE_LICHUANG_DEV)
4652
set(BOARD_TYPE "lichuang-dev")
53+
elseif(CONFIG_BOARD_TYPE_TERRENCE_C3_DEV)
54+
set(BOARD_TYPE "terrence-c3-dev")
4755
endif()
4856
file(GLOB BOARD_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_TYPE}/*.cc)
4957
list(APPEND SOURCES ${BOARD_SOURCES})
@@ -55,6 +63,7 @@ endif()
5563
idf_component_register(SRCS ${SOURCES}
5664
EMBED_FILES "assets/err_reg.p3" "assets/err_pin.p3" "assets/err_wificonfig.p3"
5765
INCLUDE_DIRS ${INCLUDE_DIRS}
66+
WHOLE_ARCHIVE
5867
)
5968

6069
# 使用 target_compile_definitions 来定义 BOARD_TYPE

main/application.cc

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
#include "application.h"
2+
#include "board.h"
3+
#include "display.h"
24
#include "system_info.h"
35
#include "ml307_ssl_transport.h"
46
#include "audio_codec.h"
57
#include "mqtt_protocol.h"
68
#include "websocket_protocol.h"
79
#include "font_awesome_symbols.h"
10+
#include "iot/thing_manager.h"
811

912
#include <cstring>
1013
#include <esp_log.h>
@@ -183,8 +186,6 @@ void Application::StopListening() {
183186

184187
void Application::Start() {
185188
auto& board = Board::GetInstance();
186-
board.Initialize();
187-
188189
auto builtin_led = board.GetBuiltinLed();
189190
builtin_led->SetBlue();
190191
builtin_led->StartContinuousBlink(100);
@@ -308,18 +309,22 @@ void Application::Start() {
308309
}
309310
});
310311
protocol_->OnAudioChannelOpened([this, codec, &board]() {
312+
board.SetPowerSaveMode(false);
311313
if (protocol_->server_sample_rate() != codec->output_sample_rate()) {
312314
ESP_LOGW(TAG, "服务器的音频采样率 %d 与设备输出的采样率 %d 不一致,重采样后可能会失真",
313315
protocol_->server_sample_rate(), codec->output_sample_rate());
314316
}
315317
SetDecodeSampleRate(protocol_->server_sample_rate());
316-
board.SetPowerSaveMode(false);
318+
// 物联网设备描述符
319+
last_iot_states_.clear();
320+
auto& thing_manager = iot::ThingManager::GetInstance();
321+
protocol_->SendIotDescriptors(thing_manager.GetDescriptorsJson());
317322
});
318323
protocol_->OnAudioChannelClosed([this, &board]() {
324+
board.SetPowerSaveMode(true);
319325
Schedule([this]() {
320326
SetChatState(kChatStateIdle);
321327
});
322-
board.SetPowerSaveMode(true);
323328
});
324329
protocol_->OnIncomingJson([this, display](const cJSON* root) {
325330
// Parse JSON data
@@ -363,6 +368,15 @@ void Application::Start() {
363368
if (emotion != NULL) {
364369
display->SetEmotion(emotion->valuestring);
365370
}
371+
} else if (strcmp(type->valuestring, "iot") == 0) {
372+
auto commands = cJSON_GetObjectItem(root, "commands");
373+
if (commands != NULL) {
374+
auto& thing_manager = iot::ThingManager::GetInstance();
375+
for (int i = 0; i < cJSON_GetArraySize(commands); ++i) {
376+
auto command = cJSON_GetArrayItem(commands, i);
377+
thing_manager.Invoke(command);
378+
}
379+
}
366380
}
367381
});
368382

@@ -557,6 +571,7 @@ void Application::SetChatState(ChatState state) {
557571
#if CONFIG_IDF_TARGET_ESP32S3
558572
audio_processor_.Start();
559573
#endif
574+
UpdateIotStates();
560575
break;
561576
case kChatStateSpeaking:
562577
builtin_led->SetGreen();
@@ -591,3 +606,12 @@ void Application::SetDecodeSampleRate(int sample_rate) {
591606
output_resampler_.Configure(opus_decode_sample_rate_, codec->output_sample_rate());
592607
}
593608
}
609+
610+
void Application::UpdateIotStates() {
611+
auto& thing_manager = iot::ThingManager::GetInstance();
612+
auto states = thing_manager.GetStatesJson();
613+
if (states != last_iot_states_) {
614+
last_iot_states_ = states;
615+
protocol_->SendIotStates(states);
616+
}
617+
}

main/application.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,16 @@
44
#include <freertos/FreeRTOS.h>
55
#include <freertos/event_groups.h>
66
#include <freertos/task.h>
7-
#include <opus.h>
7+
8+
#include <string>
89
#include <mutex>
910
#include <list>
10-
#include <condition_variable>
1111

12-
#include "opus_encoder.h"
13-
#include "opus_decoder.h"
14-
#include "opus_resampler.h"
12+
#include <opus_encoder.h>
13+
#include <opus_decoder.h>
14+
#include <opus_resampler.h>
1515

1616
#include "protocol.h"
17-
#include "display.h"
18-
#include "board.h"
1917
#include "ota.h"
2018
#include "background_task.h"
2119

@@ -58,6 +56,7 @@ class Application {
5856
void ToggleChatState();
5957
void StartListening();
6058
void StopListening();
59+
void UpdateIotStates();
6160

6261
private:
6362
Application();
@@ -75,6 +74,7 @@ class Application {
7574
volatile ChatState chat_state_ = kChatStateUnknown;
7675
bool keep_listening_ = false;
7776
bool aborted_ = false;
77+
std::string last_iot_states_;
7878

7979
// Audio encode / decode
8080
BackgroundTask background_task_;

main/boards/bread-compact-ml307/compact_ml307_board.cc

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "button.h"
77
#include "led.h"
88
#include "config.h"
9+
#include "iot/thing_manager.h"
910

1011
#include <esp_log.h>
1112
#include <driver/i2c_master.h>
@@ -59,8 +60,7 @@ class CompactMl307Board : public Ml307Board {
5960
});
6061

6162
volume_up_button_.OnLongPress([this]() {
62-
auto codec = GetAudioCodec();
63-
codec->SetOutputVolume(100);
63+
GetAudioCodec()->SetOutputVolume(100);
6464
GetDisplay()->ShowNotification("最大音量");
6565
});
6666

@@ -75,30 +75,31 @@ class CompactMl307Board : public Ml307Board {
7575
});
7676

7777
volume_down_button_.OnLongPress([this]() {
78-
auto codec = GetAudioCodec();
79-
codec->SetOutputVolume(0);
78+
GetAudioCodec()->SetOutputVolume(0);
8079
GetDisplay()->ShowNotification("已静音");
8180
});
8281
}
8382

83+
// 物联网初始化,添加对 AI 可见设备
84+
void InitializeIot() {
85+
auto& thing_manager = iot::ThingManager::GetInstance();
86+
thing_manager.AddThing(iot::CreateThing("Speaker"));
87+
thing_manager.AddThing(iot::CreateThing("Lamp"));
88+
}
89+
8490
public:
8591
CompactMl307Board() : Ml307Board(ML307_TX_PIN, ML307_RX_PIN, 4096),
8692
boot_button_(BOOT_BUTTON_GPIO),
8793
touch_button_(TOUCH_BUTTON_GPIO),
8894
volume_up_button_(VOLUME_UP_BUTTON_GPIO),
8995
volume_down_button_(VOLUME_DOWN_BUTTON_GPIO),
9096
system_reset_(RESET_NVS_BUTTON_GPIO, RESET_FACTORY_BUTTON_GPIO) {
91-
}
92-
93-
virtual void Initialize() override {
94-
ESP_LOGI(TAG, "Initializing CompactMl307Board");
9597
// Check if the reset button is pressed
9698
system_reset_.CheckButtons();
9799

98100
InitializeDisplayI2c();
99101
InitializeButtons();
100-
101-
Ml307Board::Initialize();
102+
InitializeIot();
102103
}
103104

104105
virtual Led* GetBuiltinLed() override {

main/boards/bread-compact-wifi/compact_wifi_board.cc

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "button.h"
77
#include "led.h"
88
#include "config.h"
9+
#include "iot/thing_manager.h"
910

1011
#include <wifi_station.h>
1112
#include <esp_log.h>
@@ -64,8 +65,7 @@ class CompactWifiBoard : public WifiBoard {
6465
});
6566

6667
volume_up_button_.OnLongPress([this]() {
67-
auto codec = GetAudioCodec();
68-
codec->SetOutputVolume(100);
68+
GetAudioCodec()->SetOutputVolume(100);
6969
GetDisplay()->ShowNotification("最大音量");
7070
});
7171

@@ -80,30 +80,31 @@ class CompactWifiBoard : public WifiBoard {
8080
});
8181

8282
volume_down_button_.OnLongPress([this]() {
83-
auto codec = GetAudioCodec();
84-
codec->SetOutputVolume(0);
83+
GetAudioCodec()->SetOutputVolume(0);
8584
GetDisplay()->ShowNotification("已静音");
8685
});
8786
}
8887

88+
// 物联网初始化,添加对 AI 可见设备
89+
void InitializeIot() {
90+
auto& thing_manager = iot::ThingManager::GetInstance();
91+
thing_manager.AddThing(iot::CreateThing("Speaker"));
92+
thing_manager.AddThing(iot::CreateThing("Lamp"));
93+
}
94+
8995
public:
9096
CompactWifiBoard() :
9197
boot_button_(BOOT_BUTTON_GPIO),
92-
touch_button_(TOUCH_BUTTON_GPIO, 1),
98+
touch_button_(TOUCH_BUTTON_GPIO),
9399
volume_up_button_(VOLUME_UP_BUTTON_GPIO),
94100
volume_down_button_(VOLUME_DOWN_BUTTON_GPIO),
95101
system_reset_(RESET_NVS_BUTTON_GPIO, RESET_FACTORY_BUTTON_GPIO) {
96-
}
97-
98-
virtual void Initialize() override {
99-
ESP_LOGI(TAG, "Initializing CompactWifiBoard");
100102
// Check if the reset button is pressed
101103
system_reset_.CheckButtons();
102104

103105
InitializeDisplayI2c();
104106
InitializeButtons();
105-
106-
WifiBoard::Initialize();
107+
InitializeIot();
107108
}
108109

109110
virtual Led* GetBuiltinLed() override {

main/boards/common/board.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
#include <esp_ota_ops.h>
77
#include <esp_chip_info.h>
88

9-
// static const char *TAG = "Board";
9+
#define TAG "Board"
10+
11+
Board::Board() {
12+
}
1013

1114
bool Board::GetBatteryLevel(int &level, bool& charging) {
1215
return false;

main/boards/common/board.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class Board {
1919
virtual std::string GetBoardJson() = 0;
2020

2121
protected:
22-
Board() = default;
22+
Board();
2323

2424
public:
2525
static Board& GetInstance() {
@@ -30,7 +30,6 @@ class Board {
3030
return *instance;
3131
}
3232

33-
virtual void Initialize() = 0;
3433
virtual void StartNetwork() = 0;
3534
virtual ~Board() = default;
3635
virtual Led* GetBuiltinLed() = 0;

main/boards/common/ml307_board.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "ml307_board.h"
2+
23
#include "application.h"
4+
#include "display.h"
35
#include "font_awesome_symbols.h"
46

57
#include <esp_log.h>
@@ -72,10 +74,9 @@ void Ml307Board::WaitForNetworkReady() {
7274
ESP_LOGI(TAG, "ML307 Module: %s", module_name.c_str());
7375
ESP_LOGI(TAG, "ML307 IMEI: %s", imei.c_str());
7476
ESP_LOGI(TAG, "ML307 ICCID: %s", iccid.c_str());
75-
}
7677

77-
void Ml307Board::Initialize() {
78-
ESP_LOGI(TAG, "Initializing Ml307Board");
78+
// Close all previous connections
79+
modem_.ResetConnections();
7980
}
8081

8182
Http* Ml307Board::CreateHttp() {

main/boards/common/ml307_board.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ class Ml307Board : public Board {
1313

1414
public:
1515
Ml307Board(gpio_num_t tx_pin, gpio_num_t rx_pin, size_t rx_buffer_size = 4096);
16-
virtual void Initialize() override;
1716
virtual void StartNetwork() override;
1817
virtual Http* CreateHttp() override;
1918
virtual WebSocket* CreateWebSocket() override;

0 commit comments

Comments
 (0)