富瑞坤去掉鉴权
authorliangzhenying <867174124@qq.com>
Tue, 24 Dec 2024 06:33:49 +0000 (14:33 +0800)
committerliangzhenying <867174124@qq.com>
Tue, 24 Dec 2024 06:33:49 +0000 (14:33 +0800)
16 files changed:
Document/Scenario2_Client.cpp [new file with mode: 0644]
MouseSdk/AiMouseSdk/AiMouseSdk.xcodeproj/project.pbxproj
MouseSdk/AiMouseSdk/AiMouseSdk.xcodeproj/xcuserdata/yaozuopan.xcuserdatad/xcschemes/xcschememanagement.plist [new file with mode: 0644]
MouseSdk/AiMouseSdk/AiMouseSdk/AiMouseSdk.h
MouseSdk/AiMouseSdk/AiMouseSdk/AiMouseSdk.m
MouseSdk/AiMouseSdk/ByteDance/ByteDanceSdk.m
MouseSdk/AiMouseSdk/Manager/DeviceManger.h
MouseSdk/AiMouseSdk/Manager/DeviceManger.m
MouseSdk/AiMouseSdk/Manager/LogManager.h [new file with mode: 0644]
MouseSdk/AiMouseSdk/Manager/LogManager.m [new file with mode: 0644]
MouseSdk/AiMouseSdk/TlwMouseSdk/TlwMouseSdk.h
MouseSdk/AiMouseSdk/TlwMouseSdk/TlwMouseSdk.m
MouseSdk/MouseSdk.xcodeproj/xcuserdata/yaozuopan.xcuserdatad/xcschemes/xcschememanagement.plist [new file with mode: 0644]
MouseSdk/MouseSdk.xcworkspace/xcuserdata/yaozuopan.xcuserdatad/UserInterfaceState.xcuserstate [new file with mode: 0644]
MouseSdk/MouseSdk/ViewController.m
MouseSdk/Pods/Pods.xcodeproj/xcuserdata/yaozuopan.xcuserdatad/xcschemes/xcschememanagement.plist [new file with mode: 0644]

diff --git a/Document/Scenario2_Client.cpp b/Document/Scenario2_Client.cpp
new file mode 100644 (file)
index 0000000..ac0d479
--- /dev/null
@@ -0,0 +1,926 @@
+//*********************************************************\r
+//\r
+// Copyright (c) Microsoft. All rights reserved.\r
+// This code is licensed under the MIT License (MIT).\r
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r
+//\r
+//*********************************************************\r
+\r
+#include "pch.h"\r
+#include "Scenario2_Client.h"\r
+#include "Scenario2_Client.g.cpp"\r
+#include "SampleConfiguration.h"\r
+#include "BluetoothLEAttributeDisplay.h"\r
+extern "C" {\r
+#include "stb_app.h"\r
+#include "stb_hal.h"\r
+}\r
+#include <sstream>\r
+#include <iomanip>\r
+\r
+using namespace winrt;\r
+using namespace Windows::Devices::Bluetooth;\r
+using namespace Windows::Devices::Bluetooth::GenericAttributeProfile;\r
+using namespace Windows::Devices::Enumeration;\r
+using namespace Windows::Foundation;\r
+using namespace Windows::Foundation::Collections;\r
+using namespace Windows::Globalization;\r
+using namespace Windows::Security::Cryptography;\r
+using namespace Windows::Storage::Streams;\r
+using namespace Windows::UI::Xaml;\r
+using namespace Windows::UI::Xaml::Controls;\r
+using namespace Windows::UI::Xaml::Navigation;\r
+using namespace Windows::Foundation::Collections;\r
+using namespace Windows::Storage::Streams;\r
+\r
+//\r
+GattCharacteristic CusWriteCharacteristic{ nullptr };\r
+SDKTemplate::MainPage g_rootPage = nullptr;\r
+std::wstring g_tokenStr;\r
+\r
+#include <windows.h>\r
+\r
+\r
+void STB_STDCALL cus_printf(const char* format, ...)\r
+{\r
+    char buffer[1024];\r
+    va_list args;\r
+    va_start(args, format);\r
+    int len = vsnprintf(buffer, sizeof(buffer), format, args);\r
+    va_end(args);\r
+\r
+    OutputDebugStringA(buffer);\r
+\r
+    return;\r
+}\r
+\r
+void STB_STDCALL cus_printf_str(char* str)\r
+{\r
+    OutputDebugStringA(str);\r
+    return;\r
+}\r
+\r
+//int32_t stb_hal_send_data(uint8_t* data, uint32_t len)\r
+int32_t STB_STDCALL cus_hal_send_data2device(uint8_t* data, uint32_t len)\r
+{\r
+    std::ostringstream oss;\r
+    // 把数据转换成十六进制字符串\r
+    IBuffer buffer;\r
+    for (uint32_t i = 0; i < len; ++i)\r
+    {\r
+        oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(data[i]) << " ";\r
+    }\r
+    // 转换为字符串并使用 OutputDebugString 输出\r
+    std::string hexData = oss.str();\r
+    OutputDebugString(L"[STBAPP] send data 2 device:\n");\r
+    OutputDebugStringA(hexData.c_str());\r
+    DataWriter writer;\r
+    for (uint32_t i = 0; i < len; ++i)\r
+    {\r
+        writer.WriteByte(data[i]);\r
+    }\r
+    writer.WriteByte('\n');\r
+    buffer = writer.DetachBuffer();\r
+    CusWriteCharacteristic.WriteValueAsync(buffer);\r
+    return 0;\r
+}\r
+\r
+void STB_STDCALL cust_event_callback_func(uint32_t type, uint8_t* data, uint32_t data_len)\r
+{\r
+\r
+    switch (type) {\r
+    case STB_DYNREG_SUCCESS:\r
+        OutputDebugString(L"\n\STB_DYNREG_SUCCESS\n\r");\r
+        g_rootPage.NotifyUser(L"dynreg success.", SDKTemplate::NotifyType::StatusMessage);\r
+        break;\r
+    case STB_DYNREG_FAIL:\r
+        OutputDebugString(L"\n\rSTB_DYNREG_FAIL\n\r");\r
+        g_rootPage.NotifyUser(L"dynreg failed.", SDKTemplate::NotifyType::ErrorMessage);\r
+        break;\r
+    case STB_MQTT_CONNECT_SUCCESS:\r
+        OutputDebugString(L"\n\STB_MQTT_CONNECT_SUCCESS\n\r");\r
+        g_rootPage.NotifyUser(L"mqtt connect success.", SDKTemplate::NotifyType::StatusMessage);\r
+        break;\r
+    case STB_MQTT_CONNECT_FAIL:\r
+        OutputDebugString(L"\n\STB_MQTT_CONNECT_FAIL\n\r");\r
+        g_rootPage.NotifyUser(L"mqtt connect fail.", SDKTemplate::NotifyType::ErrorMessage);\r
+        break;\r
+    case STB_MQTT_CONNECT_OFFLINE:\r
+        OutputDebugString(L"\n\STB_MQTT_CONNECT_OFFLINE\n\r");\r
+        g_rootPage.NotifyUser(L"mqtt connect offline.", SDKTemplate::NotifyType::ErrorMessage);\r
+        break;\r
+    case STB_MQTT_CONNECT_ONLINE:\r
+        OutputDebugString(L"\n\STB_MQTT_CONNECT_ONLINE\n\r");\r
+        g_rootPage.NotifyUser(L"mqtt connect online.", SDKTemplate::NotifyType::StatusMessage);\r
+        break;\r
+    case STB_DM_DATA_ARRIVED_TOKEN:\r
+        OutputDebugString(L"\n\STB_DM_DATA_ARRIVED_TOKEN\n\r");\r
+        break;\r
+    case STB_DM_DATA_ARRIVED_TOKEN_TIMEOUT:\r
+        OutputDebugString(L"\n\STB_DM_DATA_ARRIVED_TOKEN_TIMEOUT\n\r");\r
+        break;\r
+    case STB_DM_DATA_ARRIVED_HOST:\r
+        OutputDebugString(L"\n\STB_DM_DATA_ARRIVED_HOST\n\r");\r
+        break;\r
+    case STB_DM_DATA_ARRIVED_PARAMS_SIGN:\r
+        OutputDebugString(L"\n\STB_DM_DATA_ARRIVED_PARAMS_SIGN\n\r");\r
+        break;\r
+    default:\r
+        OutputDebugString(L"\n\UNKNOWN_MSG\n\r");\r
+        break;\r
+    }\r
+\r
+\r
+    if (data != nullptr && data_len > 0)\r
+    {\r
+        if (type == STB_DM_DATA_ARRIVED_TOKEN || type == STB_DM_DATA_ARRIVED_TOKEN_TIMEOUT || type == STB_DM_DATA_ARRIVED_PARAMS_SIGN)\r
+        {\r
+            if (type == STB_DM_DATA_ARRIVED_TOKEN)\r
+            {\r
+                g_tokenStr.clear();\r
+            }\r
+\r
+            for (uint32_t i = 0; i < data_len; ++i)\r
+            {\r
+                g_tokenStr.append(1, static_cast<char>(data[i]));\r
+            }\r
+            g_tokenStr.append(1, '\n');\r
+            if (type == STB_DM_DATA_ARRIVED_PARAMS_SIGN)\r
+            {\r
+                g_rootPage.NotifyUser(g_tokenStr.c_str(), SDKTemplate::NotifyType::StatusMessage);\r
+            }\r
+        \r
+        }\r
+        else\r
+        {\r
+            // 将 data 转换为字符串打印\r
+            std::wstring dataStr = L"[STBAPP]Data:  ";\r
+            for (uint32_t i = 0; i < data_len; ++i)\r
+            {\r
+                dataStr.append(1, static_cast<char>(data[i]));\r
+            }\r
+            OutputDebugString(dataStr.c_str());\r
+            OutputDebugString(L"\n\[STBAPP]EndCB\n\r");\r
+\r
+            g_rootPage.NotifyUser(dataStr.c_str(), SDKTemplate::NotifyType::StatusMessage);\r
+        }\r
+\r
+    }\r
+\r
+}\r
+namespace\r
+{\r
+    void SetVisibility(UIElement const& element, bool visible)\r
+    {\r
+        element.Visibility(visible ? Visibility::Visible : Visibility::Collapsed);\r
+    }\r
+\r
+    // Utility function to convert a string to an int32_t and detect bad input\r
+    bool TryParseInt(const wchar_t* str, int32_t& result)\r
+    {\r
+        wchar_t* end;\r
+        errno = 0;\r
+        result = std::wcstol(str, &end, 0);\r
+\r
+        if (str == end)\r
+        {\r
+            // Not parseable.\r
+            return false;\r
+        }\r
+\r
+        if (errno == ERANGE || result < INT_MIN || INT_MAX < result)\r
+        {\r
+            // Out of range.\r
+            return false;\r
+        }\r
+\r
+        if (*end != L'\0')\r
+        {\r
+            // Extra unparseable characters at the end.\r
+            return false;\r
+        }\r
+\r
+        return true;\r
+    }\r
+\r
+    template<typename T>\r
+    T Read(DataReader const& reader);\r
+\r
+    template<>\r
+    uint32_t Read<uint32_t>(DataReader const& reader)\r
+    {\r
+        return reader.ReadUInt32();\r
+    }\r
+\r
+    template<>\r
+    int32_t Read<int32_t>(DataReader const& reader)\r
+    {\r
+        return reader.ReadInt32();\r
+    }\r
+\r
+    template<>\r
+    uint8_t Read<uint8_t>(DataReader const& reader)\r
+    {\r
+        return reader.ReadByte();\r
+    }\r
+\r
+    template<typename T>\r
+    bool TryExtract(IBuffer const& buffer, T& result)\r
+    {\r
+        if (buffer.Length() >= sizeof(T))\r
+        {\r
+            DataReader reader = DataReader::FromBuffer(buffer);\r
+            result = Read<T>(reader);\r
+            return true;\r
+        }\r
+        return false;\r
+    }\r
+}\r
+\r
+namespace winrt\r
+{\r
+    hstring to_hstring(GattCommunicationStatus status)\r
+    {\r
+        switch (status)\r
+        {\r
+        case GattCommunicationStatus::Success: return L"Success";\r
+        case GattCommunicationStatus::Unreachable: return L"Unreachable";\r
+        case GattCommunicationStatus::ProtocolError: return L"ProtocolError";\r
+        case GattCommunicationStatus::AccessDenied: return L"AccessDenied";\r
+        }\r
+        return to_hstring(static_cast<int>(status));\r
+    }\r
+}\r
+\r
+namespace winrt::SDKTemplate::implementation\r
+{\r
+#pragma region UI Code\r
+    Scenario2_Client::Scenario2_Client()\r
+    {\r
+        InitializeComponent();\r
+        g_rootPage = rootPage;\r
+    }\r
+\r
+    void Scenario2_Client::OnNavigatedTo(NavigationEventArgs const&)\r
+    {\r
+        SelectedDeviceRun().Text(SampleState::SelectedBleDeviceName);\r
+        if (SampleState::SelectedBleDeviceId.empty())\r
+        {\r
+            ConnectButton().IsEnabled(false);\r
+        }\r
+    }\r
+\r
+    fire_and_forget Scenario2_Client::OnNavigatedFrom(NavigationEventArgs const&)\r
+    {\r
+        auto lifetime = get_strong();\r
+        if (!co_await ClearBluetoothLEDeviceAsync())\r
+        {\r
+            rootPage.NotifyUser(L"Error: Unable to reset app state", NotifyType::ErrorMessage);\r
+        }\r
+    }\r
+#pragma endregion\r
+\r
+#pragma region Enumerating Services\r
+    IAsyncOperation<bool> Scenario2_Client::ClearBluetoothLEDeviceAsync()\r
+    {\r
+        auto lifetime = get_strong();\r
+\r
+        if (notificationsToken)\r
+        {\r
+            // Need to clear the CCCD from the remote device so we stop receiving notifications\r
+            GattCommunicationStatus result = co_await registeredCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue::None);\r
+            if (result != GattCommunicationStatus::Success)\r
+            {\r
+                co_return false;\r
+            }\r
+            else\r
+            {\r
+                selectedCharacteristic.ValueChanged(std::exchange(notificationsToken, {}));\r
+            }\r
+        }\r
+\r
+        if (bluetoothLeDevice != nullptr)\r
+        {\r
+            bluetoothLeDevice.Close();\r
+            bluetoothLeDevice = nullptr;\r
+        }\r
+        co_return true;\r
+    }\r
+\r
+    fire_and_forget Scenario2_Client::ConnectButton_Click()\r
+    {\r
+        auto lifetime = get_strong();\r
+\r
+        ConnectButton().IsEnabled(false);\r
+\r
+        if (!co_await ClearBluetoothLEDeviceAsync())\r
+        {\r
+            rootPage.NotifyUser(L"Error: Unable to reset state, try again.", NotifyType::ErrorMessage);\r
+            ConnectButton().IsEnabled(true);\r
+            co_return;\r
+        }\r
+\r
+        try\r
+        {\r
+            // BT_Code: BluetoothLEDevice.FromIdAsync must be called from a UI thread because it may prompt for consent.\r
+            bluetoothLeDevice = co_await BluetoothLEDevice::FromIdAsync(SampleState::SelectedBleDeviceId);\r
+\r
+            if (bluetoothLeDevice == nullptr)\r
+            {\r
+                rootPage.NotifyUser(L"Failed to connect to device.", NotifyType::ErrorMessage);\r
+            }\r
+        }\r
+        catch (hresult_error& ex)\r
+        {\r
+            if (ex.to_abi() == HRESULT_FROM_WIN32(ERROR_DEVICE_NOT_AVAILABLE))\r
+            {\r
+                rootPage.NotifyUser(L"Bluetooth radio is not on.", NotifyType::ErrorMessage);\r
+            }\r
+            else\r
+            {\r
+                throw;\r
+            }\r
+        }\r
+\r
+        if (bluetoothLeDevice != nullptr)\r
+        {\r
+            // Note: BluetoothLEDevice.GattServices property will return an empty list for unpaired devices. For all uses we recommend using the GetGattServicesAsync method.\r
+            // BT_Code: GetGattServicesAsync returns a list of all the supported services of the device (even if it's not paired to the system).\r
+            // If the services supported by the device are expected to change during BT usage, subscribe to the GattServicesChanged event.\r
+            GattDeviceServicesResult result = co_await bluetoothLeDevice.GetGattServicesAsync(BluetoothCacheMode::Uncached);\r
+\r
+            if (result.Status() == GattCommunicationStatus::Success)\r
+            {\r
+                IVectorView<GattDeviceService> services = result.Services();\r
+                rootPage.NotifyUser(L"Found " + to_hstring(services.Size()) + L" services", NotifyType::StatusMessage);\r
+                for (auto&& service : services)\r
+                {\r
+                    ComboBoxItem item;\r
+                    item.Content(box_value(DisplayHelpers::GetServiceName(service)));\r
+                    item.Tag(service);\r
+                    ServiceList().Items().Append(item);\r
+                }\r
+                ConnectButton().Visibility(Visibility::Collapsed);\r
+                ServiceList().Visibility(Visibility::Visible);\r
+            }\r
+            else\r
+            {\r
+                rootPage.NotifyUser(L"Device unreachable", NotifyType::ErrorMessage);\r
+            }\r
+        }\r
+        ConnectButton().IsEnabled(true);\r
+    }\r
+    void Scenario2_Client::STB_StartAuth_Click()\r
+    {\r
+        OutputDebugString(L"[STBAPP] Auth button cliecked\n");\r
+        OutputDebugString(L"[STBAPP] identify start\n");\r
+        stb_app_start_identify();\r
+        return;\r
+    }\r
+    void Scenario2_Client::STB_Init_Click()\r
+    {\r
+        OutputDebugString(L"[STBAPP] init button cliecked\n");\r
+        stb_app_printf_str_register(cus_printf_str);\r
+        stb_app_init("tis_test");\r
+        stb_app_event_callback_register(cust_event_callback_func);\r
+        //stb_app_printf_register(cus_printf);\r
+        stb_app_send_data_to_device_register(cus_hal_send_data2device);\r
+        return;\r
+    }\r
+    void Scenario2_Client::STB_GetToken_Click()\r
+    {\r
+        OutputDebugString(L"[STBAPP] token button cliecked\n");\r
+        stb_app_get_token_async();\r
+        return;\r
+    }\r
+    void Scenario2_Client::STB_Factory_Dev1_Click()\r
+    {\r
+        OutputDebugString(L"[STBAPP] Factory1 click\n");\r
+        char *ds = device_register("k1r8dWlSOjM","474849404142","wZUBUo2vnR0LvMq9");\r
+        if (ds != NULL)\r
+        {\r
+            device_active("k1r8dWlSOjM", "474849404142", ds);\r
+        }\r
+        return;\r
+    }\r
+    void Scenario2_Client::STB_Factory_Dev2_Click()\r
+    {\r
+        OutputDebugString(L"[STBAPP] Factory2 click\n");\r
+        char* ds = device_register("k1r8dWlSOjM", "474849404140", "wZUBUo2vnR0LvMq9");\r
+        if (ds != NULL)\r
+        {\r
+            device_active("k1r8dWlSOjM", "474849404140", ds);\r
+        }\r
+        return;\r
+    }\r
+    void Scenario2_Client::STB_Factory_Dev3_Click()\r
+    {\r
+        OutputDebugString(L"[STBAPP] Factory3 click\n");\r
+\r
+        return;\r
+    }\r
+#pragma region Enumerating Characteristics\r
+    fire_and_forget Scenario2_Client::ServiceList_SelectionChanged()\r
+    {\r
+        auto lifetime = get_strong();\r
+\r
+        auto selectedItem = ServiceList().SelectedItem().as<ComboBoxItem>();\r
+        GattDeviceService service = selectedItem ? selectedItem.Tag().as<GattDeviceService>() : nullptr;\r
+\r
+        CharacteristicList().Items().Clear();\r
+        RemoveValueChangedHandler();\r
+\r
+        IVectorView<GattCharacteristic> characteristics{ nullptr };\r
+        try\r
+        {\r
+            // Ensure we have access to the device.\r
+            auto accessStatus = co_await service.RequestAccessAsync();\r
+            if (accessStatus == DeviceAccessStatus::Allowed)\r
+            {\r
+                // BT_Code: Get all the child characteristics of a service. Use the cache mode to specify uncached characterstics only \r
+                // and the new Async functions to get the characteristics of unpaired devices as well. \r
+                GattCharacteristicsResult result = co_await service.GetCharacteristicsAsync(BluetoothCacheMode::Uncached);\r
+                if (result.Status() == GattCommunicationStatus::Success)\r
+                {\r
+                    characteristics = result.Characteristics();\r
+                }\r
+                else\r
+                {\r
+                    rootPage.NotifyUser(L"Error accessing service.", NotifyType::ErrorMessage);\r
+                }\r
+            }\r
+            else\r
+            {\r
+                // Not granted access\r
+                rootPage.NotifyUser(L"Error accessing service.", NotifyType::ErrorMessage);\r
+\r
+            }\r
+        }\r
+        catch (hresult_error& ex)\r
+        {\r
+            rootPage.NotifyUser(L"Restricted service. Can't read characteristics: " + ex.message(), NotifyType::ErrorMessage);\r
+        }\r
+\r
+        if (characteristics)\r
+        {\r
+            for (GattCharacteristic&& c : characteristics)\r
+            {\r
+                ComboBoxItem item;\r
+                item.Content(box_value(DisplayHelpers::GetCharacteristicName(c)));\r
+                item.Tag(c);\r
+                CharacteristicList().Items().Append(item);\r
+            }\r
+        }\r
+        CharacteristicList().Visibility(Visibility::Visible);\r
+    }\r
+#pragma endregion\r
+\r
+    void Scenario2_Client::AddValueChangedHandler()\r
+    {\r
+        ValueChangedSubscribeToggle().Content(box_value(L"Unsubscribe from value changes"));\r
+        if (!notificationsToken)\r
+        {\r
+            registeredCharacteristic = selectedCharacteristic;\r
+            notificationsToken = registeredCharacteristic.ValueChanged({ get_weak(), &Scenario2_Client::Characteristic_ValueChanged });\r
+        }\r
+    }\r
+    void Scenario2_Client::RemoveValueChangedHandler()\r
+    {\r
+        ValueChangedSubscribeToggle().Content(box_value(L"Subscribe to value changes"));\r
+        if (notificationsToken)\r
+        {\r
+            registeredCharacteristic.ValueChanged(std::exchange(notificationsToken, {}));\r
+            registeredCharacteristic = nullptr;\r
+        }\r
+    }\r
+\r
+    fire_and_forget Scenario2_Client::CharacteristicList_SelectionChanged()\r
+    {\r
+        auto lifetime = get_strong();\r
+\r
+        auto selectedItem = CharacteristicList().SelectedItem().as<ComboBoxItem>();\r
+        selectedCharacteristic = selectedItem ? selectedItem.Tag().as<GattCharacteristic>() : nullptr;\r
+        if ((selectedCharacteristic.CharacteristicProperties() & (GattCharacteristicProperties::Indicate | GattCharacteristicProperties::Notify)) != GattCharacteristicProperties::None)\r
+        {\r
+            OutputDebugString(L"[STBAPP] NotifyChar defined\n");\r
+            NotifyCharacteristic = selectedCharacteristic;\r
+        }\r
+        if ((selectedCharacteristic.CharacteristicProperties() & (GattCharacteristicProperties::Write | GattCharacteristicProperties::WriteWithoutResponse)) != GattCharacteristicProperties::None)\r
+        {\r
+            OutputDebugString(L"[STBAPP] WriteChar defined\n");\r
+            CusWriteCharacteristic = selectedCharacteristic;\r
+        }\r
+       \r
+        \r
+\r
+        if (selectedCharacteristic == nullptr)\r
+        {\r
+            EnableCharacteristicPanels(GattCharacteristicProperties::None);\r
+            rootPage.NotifyUser(L"No characteristic selected", NotifyType::ErrorMessage);\r
+            co_return;\r
+        }\r
+\r
+        // Get all the child descriptors of a characteristics. Use the cache mode to specify uncached descriptors only \r
+        // and the new Async functions to get the descriptors of unpaired devices as well. \r
+        GattDescriptorsResult result = co_await selectedCharacteristic.GetDescriptorsAsync(BluetoothCacheMode::Uncached);\r
+        if (result.Status() != GattCommunicationStatus::Success)\r
+        {\r
+            rootPage.NotifyUser(L"Descriptor read failure: " + to_hstring(result.Status()), NotifyType::ErrorMessage);\r
+        }\r
+\r
+        // BT_Code: There's no need to access presentation format unless there's at least one. \r
+        presentationFormat = nullptr;\r
+        if (selectedCharacteristic.PresentationFormats().Size() > 0)\r
+        {\r
+\r
+            if (selectedCharacteristic.PresentationFormats().Size() == 1)\r
+            {\r
+                // Get the presentation format since there's only one way of presenting it\r
+                presentationFormat = selectedCharacteristic.PresentationFormats().GetAt(0);\r
+            }\r
+            else\r
+            {\r
+                // It's difficult to figure out how to split up a characteristic and encode its different parts properly.\r
+                // In this case, we'll just encode the whole thing to a string to make it easy to print out.\r
+            }\r
+        }\r
+\r
+        // Enable/disable operations based on the GattCharacteristicProperties.\r
+        EnableCharacteristicPanels(selectedCharacteristic.CharacteristicProperties());\r
+    }\r
+\r
+    void Scenario2_Client::EnableCharacteristicPanels(GattCharacteristicProperties properties)\r
+    {\r
+        // BT_Code: Hide the controls which do not apply to this characteristic.\r
+        SetVisibility(CharacteristicReadButton(),\r
+            (properties & GattCharacteristicProperties::Read) != GattCharacteristicProperties::None);\r
+\r
+        SetVisibility(CharacteristicWritePanel(),\r
+            (properties & (GattCharacteristicProperties::Write | GattCharacteristicProperties::WriteWithoutResponse)) != GattCharacteristicProperties::None);\r
+        CharacteristicWriteValue().Text(L"");\r
+\r
+        SetVisibility(ValueChangedSubscribeToggle(),\r
+            (properties & (GattCharacteristicProperties::Indicate | GattCharacteristicProperties::Notify)) != GattCharacteristicProperties::None);\r
+    }\r
+\r
+    fire_and_forget Scenario2_Client::CharacteristicReadButton_Click()\r
+    {\r
+        auto lifetime = get_strong();\r
+\r
+        // BT_Code: Read the actual value from the device by using Uncached.\r
+        GattReadResult result = co_await selectedCharacteristic.ReadValueAsync(BluetoothCacheMode::Uncached);\r
+        if (result.Status() == GattCommunicationStatus::Success)\r
+        {\r
+            rootPage.NotifyUser(L"Read result: " + FormatValueByPresentation(result.Value(), presentationFormat), NotifyType::StatusMessage);\r
+        }\r
+        else\r
+        {\r
+            rootPage.NotifyUser(L"Read failed: Status = " + to_hstring(result.Status()), NotifyType::ErrorMessage);\r
+        }\r
+    }\r
+\r
+    fire_and_forget Scenario2_Client::CharacteristicWriteButton_Click()\r
+    {\r
+#if 1\r
+        auto lifetime = get_strong();\r
+\r
+        hstring text = CharacteristicWriteValue().Text();\r
+        if (!text.empty())\r
+        {\r
+            std::vector<std::wstring> byteStrings;\r
+            std::wstringstream wss(text.c_str());\r
+            std::wstring byteStr;\r
+            while (wss >> byteStr)\r
+            {\r
+                byteStrings.push_back(byteStr);\r
+            }\r
+\r
+            // 转换并格式化字节为十六进制字符串,添加 "0x" 前缀\r
+            std::vector<uint8_t> bytes;\r
+            std::wstringstream hexStream;\r
+            for (const auto& byteStr : byteStrings)\r
+            {\r
+                uint8_t byteValue = static_cast<uint8_t>(std::stoi(byteStr, nullptr, 16));\r
+                bytes.push_back(byteValue);\r
+                hexStream << L"0x" << std::hex << std::setw(2) << std::setfill(L'0') << static_cast<int>(byteValue) << L", ";\r
+            }\r
+            std::wstring formattedHexStr = hexStream.str();\r
+            // 去除末尾的逗号和空格\r
+            if (!formattedHexStr.empty())\r
+            {\r
+                formattedHexStr.pop_back();\r
+                formattedHexStr.pop_back();\r
+            }\r
+\r
+            // 使用格式化后的十六进制数据\r
+            IBuffer writeBuffer;\r
+            DataWriter writer;\r
+            for (const auto& byte : bytes)\r
+            {\r
+                writer.WriteByte(byte);\r
+            }\r
+            writeBuffer = writer.DetachBuffer();\r
+\r
+            co_await WriteBufferToSelectedCharacteristicAsync(writeBuffer);\r
+            }\r
+            else\r
+            {\r
+                rootPage.NotifyUser(L"No data to write to device", NotifyType::ErrorMessage);\r
+            }\r
+#else\r
+        auto lifetime = get_strong();\r
+\r
+        hstring text = CharacteristicWriteValue().Text();\r
+        if (!text.empty())\r
+        {\r
+            IBuffer writeBuffer = CryptographicBuffer::ConvertStringToBinary(CharacteristicWriteValue().Text(), BinaryStringEncoding::Utf8);\r
+\r
+            co_await WriteBufferToSelectedCharacteristicAsync(writeBuffer);\r
+        }\r
+        else\r
+        {\r
+            rootPage.NotifyUser(L"No data to write to device", NotifyType::ErrorMessage);\r
+        }\r
+#endif\r
+    }\r
+\r
+    fire_and_forget Scenario2_Client::CharacteristicWriteButtonInt_Click()\r
+    {\r
+        auto lifetime = get_strong();\r
+\r
+        int32_t readValue;\r
+        if (TryParseInt(CharacteristicWriteValue().Text().begin(), readValue))\r
+        {\r
+            DataWriter writer;\r
+            writer.ByteOrder(ByteOrder::LittleEndian);\r
+            writer.WriteInt32(readValue);\r
+\r
+            co_await WriteBufferToSelectedCharacteristicAsync(writer.DetachBuffer());\r
+        }\r
+        else\r
+        {\r
+            rootPage.NotifyUser(L"Data to write has to be an int32", NotifyType::ErrorMessage);\r
+        }\r
+    }\r
+\r
+    IAsyncOperation<bool> Scenario2_Client::WriteBufferToSelectedCharacteristicAsync(IBuffer buffer)\r
+    {\r
+        auto lifetime = get_strong();\r
+\r
+        try\r
+        {\r
+            // BT_Code: Writes the value from the buffer to the characteristic.\r
+            GattWriteResult result = co_await selectedCharacteristic.WriteValueWithResultAsync(buffer);\r
+\r
+            if (result.Status() == GattCommunicationStatus::Success)\r
+            {\r
+                rootPage.NotifyUser(L"Successfully wrote value to device", NotifyType::StatusMessage);\r
+                co_return true;\r
+            }\r
+            else\r
+            {\r
+                rootPage.NotifyUser(L"Write failed: Status = " + to_hstring(result.Status()), NotifyType::ErrorMessage);\r
+                co_return false;\r
+            }\r
+        }\r
+        catch (hresult_error& ex)\r
+        {\r
+            if (ex.code() == E_BLUETOOTH_ATT_INVALID_PDU)\r
+            {\r
+                rootPage.NotifyUser(ex.message(), NotifyType::ErrorMessage);\r
+                co_return false;\r
+            }\r
+            if (ex.code() == E_BLUETOOTH_ATT_WRITE_NOT_PERMITTED || ex.code() == E_ACCESSDENIED)\r
+            {\r
+                // This usually happens when a device reports that it support writing, but it actually doesn't.\r
+                rootPage.NotifyUser(ex.message(), NotifyType::ErrorMessage);\r
+                co_return false;\r
+            }\r
+            throw;\r
+        }\r
+    }\r
+\r
+    fire_and_forget Scenario2_Client::ValueChangedSubscribeToggle_Click()\r
+    {\r
+        auto lifetime = get_strong();\r
+\r
+        if (!notificationsToken)\r
+        {\r
+            GattClientCharacteristicConfigurationDescriptorValue cccdValue = GattClientCharacteristicConfigurationDescriptorValue::None;\r
+            if ((selectedCharacteristic.CharacteristicProperties() & GattCharacteristicProperties::Indicate) != GattCharacteristicProperties::None)\r
+            {\r
+                cccdValue = GattClientCharacteristicConfigurationDescriptorValue::Indicate;\r
+            }\r
+\r
+            else if ((selectedCharacteristic.CharacteristicProperties() & GattCharacteristicProperties::Notify) != GattCharacteristicProperties::None)\r
+            {\r
+                cccdValue = GattClientCharacteristicConfigurationDescriptorValue::Notify;\r
+            }\r
+\r
+            try\r
+            {\r
+                // BT_Code: Must write the CCCD in order for server to send indications.\r
+                // We receive them in the ValueChanged event handler.\r
+                GattCommunicationStatus status = co_await selectedCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(cccdValue);\r
+\r
+                if (status == GattCommunicationStatus::Success)\r
+                {\r
+                    AddValueChangedHandler();\r
+                    rootPage.NotifyUser(L"Successfully subscribed for value changes", NotifyType::StatusMessage);\r
+                }\r
+                else\r
+                {\r
+                    rootPage.NotifyUser(L"Error registering for value changes: Status = " + to_hstring(status), NotifyType::ErrorMessage);\r
+                }\r
+            }\r
+            catch (hresult_access_denied& ex)\r
+            {\r
+                // This usually happens when a device reports that it support indicate, but it actually doesn't.\r
+                rootPage.NotifyUser(ex.message(), NotifyType::ErrorMessage);\r
+            }\r
+        }\r
+        else\r
+        {\r
+            try\r
+            {\r
+                // BT_Code: Must write the CCCD in order for server to send notifications.\r
+                // We receive them in the ValueChanged event handler.\r
+                // Note that this sample configures either Indicate or Notify, but not both.\r
+                GattCommunicationStatus result = co_await\r
+                    selectedCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(\r
+                        GattClientCharacteristicConfigurationDescriptorValue::None);\r
+                if (result == GattCommunicationStatus::Success)\r
+                {\r
+                    RemoveValueChangedHandler();\r
+                    rootPage.NotifyUser(L"Successfully un-registered for notifications", NotifyType::StatusMessage);\r
+                }\r
+                else\r
+                {\r
+                    rootPage.NotifyUser(L"Error un-registering for notifications: Status = " + to_hstring(result), NotifyType::ErrorMessage);\r
+                }\r
+            }\r
+            catch (hresult_access_denied& ex)\r
+            {\r
+                // This usually happens when a device reports that it support notify, but it actually doesn't.\r
+                rootPage.NotifyUser(ex.message(), NotifyType::ErrorMessage);\r
+            }\r
+        }\r
+    }\r
+\r
+    fire_and_forget Scenario2_Client::Characteristic_ValueChanged(GattCharacteristic const&, GattValueChangedEventArgs args)\r
+    {\r
+        auto lifetime = get_strong();\r
+\r
+        // BT_Code: An Indicate or Notify reported that the value has changed.\r
+        // Display the new value with a timestamp.\r
+        hstring newValue = FormatValueByPresentation(args.CharacteristicValue(), presentationFormat);\r
+        std::time_t now = clock::to_time_t(clock::now());\r
+        char buffer[26];\r
+        ctime_s(buffer, ARRAYSIZE(buffer), &now);\r
+        hstring message = L"Value at " + to_hstring(buffer) + L": " + newValue;\r
+        co_await resume_foreground(Dispatcher());\r
+        CharacteristicLatestValue().Text(message);\r
+    }\r
+\r
+    /// <summary>\r
+    /// Process the raw data received from the device into application usable data,\r
+    /// according the the Bluetooth Heart Rate Profile.\r
+    /// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.heart_rate_measurement.xml&u=org.bluetooth.characteristic.heart_rate_measurement.xml\r
+    /// This function throws an std::out_of_range if the data cannot be parsed.\r
+    /// </summary>\r
+    /// <param name="data">Raw data received from the heart rate monitor.</param>\r
+    /// <returns>The heart rate measurement value.</returns>\r
+    int32_t ParseHeartRateValue(IBuffer const& buffer)\r
+    {\r
+        // Heart Rate profile defined flag values\r
+        const uint8_t heartRateValueFormat = 0x1;\r
+\r
+        com_array<uint8_t> bytes;\r
+        CryptographicBuffer::CopyToByteArray(buffer, bytes);\r
+        \r
+        if (bytes.at(0) & heartRateValueFormat)\r
+        {\r
+            return bytes.at(1) | (bytes.at(2) << 8);\r
+        }\r
+        return bytes.at(1);\r
+    }\r
+\r
+    hstring Scenario2_Client::FormatValueByPresentation(IBuffer const& buffer, GenericAttributeProfile::GattPresentationFormat const& format)\r
+    {\r
+        // BT_Code: For the purpose of this sample, this function converts only UInt32 and\r
+        // UTF-8 buffers to readable text. It can be extended to support other formats if your app needs them.\r
+        if (format != nullptr)\r
+        {\r
+            if (format.FormatType() == GattPresentationFormatTypes::UInt32())\r
+            {\r
+                uint32_t value;\r
+                if (TryExtract(buffer, value))\r
+                {\r
+                    return to_hstring(value);\r
+                }\r
+                return L"(error: Invalid UInt32)";\r
+\r
+            }\r
+            else if (format.FormatType() == GattPresentationFormatTypes::Utf8())\r
+            {\r
+                try\r
+                {\r
+                    return CryptographicBuffer::ConvertBinaryToString(BinaryStringEncoding::Utf8, buffer);\r
+                }\r
+                catch (hresult_invalid_argument&)\r
+                {\r
+                    return L"(error: Invalid UTF-8 string)";\r
+                }\r
+            }\r
+            else\r
+            {\r
+                // Add support for other format types as needed.\r
+                return L"Unsupported format: " + CryptographicBuffer::EncodeToHexString(buffer);\r
+            }\r
+        }\r
+        else if (buffer != nullptr)\r
+        {\r
+            // We don't know what format to use. Let's try some well-known profiles, or default back to UTF-8.\r
+            if (selectedCharacteristic.Uuid() == GattCharacteristicUuids::HeartRateMeasurement())\r
+            {\r
+                try\r
+                {\r
+                    return L"Heart Rate: " + to_hstring(ParseHeartRateValue(buffer));\r
+                }\r
+                catch (std::out_of_range&)\r
+                {\r
+                    return L"Heart Rate: (unable to parse)";\r
+                }\r
+            }\r
+            else if (selectedCharacteristic.Uuid() == GattCharacteristicUuids::BatteryLevel())\r
+            {\r
+                // battery level is encoded as a percentage value in the first byte according to\r
+                // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.battery_level.xml\r
+                uint8_t percent;\r
+                if (TryExtract(buffer, percent))\r
+                {\r
+                    return L"Battery Level: " + to_hstring(percent) + L"%";\r
+                }\r
+                return L"Battery Level: (unable to parse)";\r
+            }\r
+            // This is our custom calc service Result UUID. Format it like an Int\r
+            else if (selectedCharacteristic.Uuid() == Constants::ResultCharacteristicUuid)\r
+            {\r
+                int32_t value;\r
+                if (TryExtract(buffer, value))\r
+                {\r
+                    return to_hstring(value);\r
+                }\r
+                return L"Invalid response from calc server";\r
+            }\r
+            else if (NotifyCharacteristic.Uuid() == Constants::MicCharacteristicUuid)\r
+            {\r
+                return L"Mic data: " + CryptographicBuffer::EncodeToHexString(buffer);\r
+            }\r
+            else if (NotifyCharacteristic.Uuid() == Constants::IdentifyCharacteristicUuid)\r
+            {\r
+                com_array<uint8_t> bytes;\r
+                CryptographicBuffer::CopyToByteArray(buffer, bytes);\r
+                stb_app_recv_data_from_device(bytes.data(), static_cast<uint32_t>(bytes.size()));\r
+                return L"Bizbus data: " + CryptographicBuffer::EncodeToHexString(buffer);\r
+            }\r
+            // No guarantees on if a characteristic is registered for notifications.\r
+            else if (registeredCharacteristic != nullptr)\r
+            {\r
+                // This is our custom calc service Result UUID. Format it like an Int\r
+                if (registeredCharacteristic.Uuid() == Constants::ResultCharacteristicUuid)\r
+                {\r
+                    int32_t value;\r
+                    if (TryExtract(buffer, value))\r
+                    {\r
+                        return to_hstring(value);\r
+                    }\r
+                    return L"Invalid response from calc server";\r
+                }\r
+            }\r
+            else\r
+            {\r
+                try\r
+                {\r
+                    return L"Unknown format: " + CryptographicBuffer::ConvertBinaryToString(BinaryStringEncoding::Utf8, buffer);\r
+\r
+                }\r
+                catch (hresult_invalid_argument&)\r
+                {\r
+                    return L"Unknown format";\r
+                }\r
+            }\r
+        }\r
+        else\r
+        {\r
+            return L"Empty data received";\r
+        }\r
+        return L"Unknown format";\r
+    }\r
+}\r
+\r
+\r
+\r
index 60fcca3..cf220de 100644 (file)
                18E0C5922D0FF8E30093BA8F /* stb_identify.so in Frameworks */ = {isa = PBXBuildFile; fileRef = 18E0C58F2D0FF8E30093BA8F /* stb_identify.so */; };
                18E0C5932D0FF8E40093BA8F /* stb_app.h in Headers */ = {isa = PBXBuildFile; fileRef = 18E0C5902D0FF8E30093BA8F /* stb_app.h */; };
                18E0C5942D0FF8E40093BA8F /* stb_identify.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18E0C5912D0FF8E30093BA8F /* stb_identify.a */; };
-               18E0C5972D1000DF0093BA8F /* ByteDanceSdk.h in Headers */ = {isa = PBXBuildFile; fileRef = 18E0C5952D1000DF0093BA8F /* ByteDanceSdk.h */; };
+               18E0C5972D1000DF0093BA8F /* ByteDanceSdk.h in Headers */ = {isa = PBXBuildFile; fileRef = 18E0C5952D1000DF0093BA8F /* ByteDanceSdk.h */; settings = {ATTRIBUTES = (Public, ); }; };
                18E0C5982D1000DF0093BA8F /* ByteDanceSdk.m in Sources */ = {isa = PBXBuildFile; fileRef = 18E0C5962D1000DF0093BA8F /* ByteDanceSdk.m */; };
                18EF7AF92C7603E800AC5223 /* adpcm.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EF7AEA2C7603E800AC5223 /* adpcm.h */; };
                18EF7AFA2C7603E800AC5223 /* TlwMouseSdk.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EF7AEB2C7603E800AC5223 /* TlwMouseSdk.m */; };
                18EF7B052C7603E800AC5223 /* TlwConnectManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 18EF7AF62C7603E800AC5223 /* TlwConnectManager.h */; };
                18FCA3972C7F2AD100C44A37 /* AiMouseAuth.h in Headers */ = {isa = PBXBuildFile; fileRef = 18FCA3952C7F2AD100C44A37 /* AiMouseAuth.h */; };
                18FCA3982C7F2AD100C44A37 /* AiMouseAuth.m in Sources */ = {isa = PBXBuildFile; fileRef = 18FCA3962C7F2AD100C44A37 /* AiMouseAuth.m */; };
+               3FCF534F2D1A5C97007EC52F /* LogManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3FCF534E2D1A5C97007EC52F /* LogManager.m */; };
+               3FCF53502D1A5C97007EC52F /* LogManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FCF534D2D1A5C97007EC52F /* LogManager.h */; };
+               3FCF53512D1A5C97007EC52F /* LogManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FCF534D2D1A5C97007EC52F /* LogManager.h */; };
+               3FCF53522D1A5C97007EC52F /* LogManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3FCF534E2D1A5C97007EC52F /* LogManager.m */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
                188814BC2C85BB76009299A9 /* AiBkzhAuthManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiBkzhAuthManager.m; sourceTree = "<group>"; };
                188814C02C85C2BA009299A9 /* AESCBCHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AESCBCHelper.h; sourceTree = "<group>"; };
                188814C12C85C2BA009299A9 /* AESCBCHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AESCBCHelper.m; sourceTree = "<group>"; };
-               189365512CEB0C3700023B62 /* libAiMouseSdk copy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libAiMouseSdk copy.a"; path = "/Users/apple/Desktop/code/MouseSdk-MacOS/MouseSdk/AiMouseSdk/build/Debug/libAiMouseSdk copy.a"; sourceTree = "<absolute>"; };
                189365522CEB115200023B62 /* KeyboardHidManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyboardHidManager.h; sourceTree = "<group>"; };
                189365532CEB115200023B62 /* KeyboardHidManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeyboardHidManager.m; sourceTree = "<group>"; };
                189365562CEB153000023B62 /* MSUtilis.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSUtilis.h; sourceTree = "<group>"; };
                18EF7AF62C7603E800AC5223 /* TlwConnectManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TlwConnectManager.h; sourceTree = "<group>"; };
                18FCA3952C7F2AD100C44A37 /* AiMouseAuth.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiMouseAuth.h; sourceTree = "<group>"; };
                18FCA3962C7F2AD100C44A37 /* AiMouseAuth.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiMouseAuth.m; sourceTree = "<group>"; };
+               3FCF534C2D1A4E38007EC52F /* libAiMouseSdk copy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libAiMouseSdk copy.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+               3FCF534D2D1A5C97007EC52F /* LogManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogManager.h; sourceTree = "<group>"; };
+               3FCF534E2D1A5C97007EC52F /* LogManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LogManager.m; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                                180E7AA82BD7BB12008558E8 /* AiMouseSdk */,
                                180E7AA72BD7BB12008558E8 /* Products */,
                                180E7D092BD8FEB2008558E8 /* Frameworks */,
+                               3FCF534C2D1A4E38007EC52F /* libAiMouseSdk copy.a */,
                        );
                        sourceTree = "<group>";
                };
                                1888148D2C85766B009299A9 /* AiDeviceAuthManager.m */,
                                189365562CEB153000023B62 /* MSUtilis.h */,
                                189365572CEB153000023B62 /* MSUtilis.m */,
+                               3FCF534D2D1A5C97007EC52F /* LogManager.h */,
+                               3FCF534E2D1A5C97007EC52F /* LogManager.m */,
                        );
                        path = Manager;
                        sourceTree = "<group>";
                                18EF7B052C7603E800AC5223 /* TlwConnectManager.h in Headers */,
                                180E7CF92BD8FC4F008558E8 /* dirac.h in Headers */,
                                18E0C5932D0FF8E40093BA8F /* stb_app.h in Headers */,
+                               3FCF53502D1A5C97007EC52F /* LogManager.h in Headers */,
                                184A71032BDA4C050025A332 /* AFNetworkReachabilityManager.h in Headers */,
                                184A71242BDE2DA60025A332 /* AiSecretModel.h in Headers */,
                                180E7CCF2BD8FC4E008558E8 /* video_enc_params.h in Headers */,
                                18862B282C806BD900D3564D /* hwcontext_mediacodec.h in Headers */,
                                18862B292C806BD900D3564D /* AiAudioDecoder.h in Headers */,
                                18862B2A2C806BD900D3564D /* encryption_info.h in Headers */,
+                               3FCF53512D1A5C97007EC52F /* LogManager.h in Headers */,
                                18862B2B2C806BD900D3564D /* blowfish.h in Headers */,
                                18862B2C2C806BD900D3564D /* AiAliAuthManager.h in Headers */,
                                18862B2D2C806BD900D3564D /* jni.h in Headers */,
                        );
                        name = "AiMouseSdk copy";
                        productName = AiMouseSdk;
-                       productReference = 189365512CEB0C3700023B62 /* libAiMouseSdk copy.a */;
+                       productReference = 3FCF534C2D1A4E38007EC52F /* libAiMouseSdk copy.a */;
                        productType = "com.apple.product-type.library.static";
                };
 /* End PBXNativeTarget section */
                                18EF7B042C7603E800AC5223 /* TlwAudioManager.m in Sources */,
                                18E0C5982D1000DF0093BA8F /* ByteDanceSdk.m in Sources */,
                                189960112CEAD7B50042505F /* KeyboardSdk.m in Sources */,
+                               3FCF534F2D1A5C97007EC52F /* LogManager.m in Sources */,
                                180E7BE72BD7BD84008558E8 /* AiAudioManager.m in Sources */,
                                18EF7AFB2C7603E800AC5223 /* TlwTools.m in Sources */,
                                18EF7AFA2C7603E800AC5223 /* TlwMouseSdk.m in Sources */,
                                18862BAF2C806BD900D3564D /* TimerManager.m in Sources */,
                                18862BB02C806BD900D3564D /* HidManager.m in Sources */,
                                18862BB22C806BD900D3564D /* AiMouseTools2.m in Sources */,
+                               3FCF53522D1A5C97007EC52F /* LogManager.m in Sources */,
                                18862BB32C806BD900D3564D /* AiSecretModel.m in Sources */,
                                18862BB42C806BD900D3564D /* AiSender.m in Sources */,
                                18862BB52C806BD900D3564D /* AiTrippleModel.m in Sources */,
diff --git a/MouseSdk/AiMouseSdk/AiMouseSdk.xcodeproj/xcuserdata/yaozuopan.xcuserdatad/xcschemes/xcschememanagement.plist b/MouseSdk/AiMouseSdk/AiMouseSdk.xcodeproj/xcuserdata/yaozuopan.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644 (file)
index 0000000..6349347
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>SchemeUserState</key>
+       <dict>
+               <key>AiMouseSdk copy.xcscheme_^#shared#^_</key>
+               <dict>
+                       <key>orderHint</key>
+                       <integer>3</integer>
+               </dict>
+               <key>AiMouseSdk.xcscheme_^#shared#^_</key>
+               <dict>
+                       <key>orderHint</key>
+                       <integer>0</integer>
+               </dict>
+       </dict>
+</dict>
+</plist>
index e0ff37e..fad4a25 100644 (file)
 @property (nonatomic, strong) NSString *mac;///设备MAC地址
 @end
 
-typedef NS_ENUM(NSInteger,AiMouseAuthType) {
-    AiMouseAuthType_none = 0,///不鉴权
-    AiMouseAuthType_BeiKeZhiHui = 1,/// 北科智慧
-    AiMouseAuthType_Ali = 2,/// 阿里
-};
-
 typedef NS_ENUM(NSInteger,AiMouseErrorCode) {
     AiMouseErrorCode_timeOut = 1001,///请求超时
     AiMouseErrorCode_busy = 1002,/// 繁忙,有命令未执行完
     AiMouseErrorCode_unknown = 1003,/// 未知错误
 };
 
-/// 日志等级
-typedef NS_ENUM(NSInteger,AiMouseLogLevel) {
-    AiMouseLogLevel_none = 0,
-    AiMouseLogLevel_error,
-    AiMouseLogLevel_info,
-};
-
 typedef NS_ENUM(NSInteger,AiMouseConnectType) {
     AiMouseConnectType_bluetooth = 0,///蓝牙
     AiMouseConnectType_hid = 1,///hid
@@ -85,7 +72,6 @@ typedef NS_ENUM(NSInteger,AiMouseAuthState) {
 @end
 
 @interface AiMouse : NSObject
-@property (nonatomic, readonly) NSString *version;/// 版本号
 @property (nonatomic, weak) id<AiMouseDelegate> delegate;/// 代理
 @property (nonatomic, readonly) AiMouseConnectType connectType;//连接类型
 @property (nonatomic, assign) BOOL connected;//是否已连接
@@ -93,10 +79,6 @@ typedef NS_ENUM(NSInteger,AiMouseAuthState) {
 /// 单利
 +(AiMouse *)shared;
 
-/// 设置日志等级
-/// - Parameter level: 等级
-- (void)setLogLevel:(AiMouseLogLevel)level;
-
 
 /// 断开连接
 - (void)didDisconnect;
@@ -105,10 +87,6 @@ typedef NS_ENUM(NSInteger,AiMouseAuthState) {
 /// - Parameter type: 连接类型
 - (void)switchConnect:(AiMouseConnectType)type isConnected:(BOOL)isConneted;
 
-///// 开始鉴权
-///// - Parameter finished: 鉴权结果回调
-//- (void)startAuthentication:(void (^)(AiMouseAuthState state))complete;
-
 /// 传输业务数据给sdk
 /// - Parameter data:ai特征传过来的数据
 - (void)sendAiDataToSdk:(NSData *)data;
index b95a2e4..e3c303e 100644 (file)
 @end
 @implementation AiMouseDeviceInfo
 -(NSString *)description{
-//    NSString *info = [NSString stringWithFormat:@"\n battery_power = %@\n CPI = %@\n CPI_list = %@\n version = %@\n brand = %@\n sn = %@\n mac = %@\n productKey = %@\n secretKey = %@\n deviceSecret = %@ \n record_mode = %@ \n mouse_mode = %@ \n url = %@ \n urlActive = %@ ",self.battery_power,self.CPI,self.CPI_list,self.version,self.brand,self.sn,self.mac,self.productKey,self.secretKey,self.deviceSecret,self.record_mode,self.mouse_mode,self.url,self.urlActive];
-    
     NSString *info = [NSString stringWithFormat:@"\n type = %d \n battery_power = %@\n CPI = %@\n CPI_list = %@\n version = %@\n brand = %@\n sn = %@\n mac = %@\n productKey = %@\n secretKey = %@\n deviceSecret = %@ ",self.type,self.battery_power,self.CPI,self.CPI_list,self.version,self.brand,self.sn,self.mac,self.productKey,self.secretKey,self.deviceSecret];
     return info;
 }
 @end
 
 @interface AiMouse()
-@property (nonatomic, assign) AiMouseLogLevel logLevel;
-
-@property (nonatomic, strong) AiAuthManager *authManager;
-@property (nonatomic, strong) AiAliAuthManager *aliAuthManager;
-@property (nonatomic, strong) AiBkzhAuthManager *bkAuthManager;
 
 @property (nonatomic, strong) AiAudioManager *audioManager;
 @property (nonatomic, strong) AiRecordManager *recordManager;
@@ -46,7 +39,6 @@
 @property (nonatomic, strong) AiDeviceInfoManager *deviceInfoManager;
 @property (nonatomic, strong) NSString *updateDeviceSecret;//更新的deviceSecret
 
-@property (nonatomic, assign) BOOL isAuthing;
 @end
 
 @implementation AiMouse
 
 -(instancetype)init{
     if (self = [super init]) {
-        _logLevel = AiMouseLogLevel_none;
         _connectType =  AiMouseConnectType_bluetooth;
-//        NSLog(@"[AiMouseSdk]%@",[NSString stringWithFormat:@"AiMouseSdk_v%@",self.version]);
         [self.recordManager checkPermissions];
     }
     return self;
 }
 
--(NSString *)version{
-    return @"1.0.33";
-}
 
 -(AiDeviceInfoManager *)deviceInfoManager{
     if (!_deviceInfoManager) {
     return _deviceInfoManager;;
 }
 
--(AiAuthManager *)authManager{
-    if (!_authManager) {
-        _authManager = [[AiAuthManager alloc] init];
-        __weak typeof(self) ws = self;
-        _authManager.outputLog = ^(NSString * _Nonnull log) {
-            [ws showLog:log];
-        };
-        _authManager.setDeviceSecret = ^(NSString * _Nonnull value, AiCmdFinishBlock  _Nonnull finished) {
-            [ws setDeviceSecret:value completation:finished];
-        };
-        _authManager.authCallBack = ^(BOOL isSuccess) {
-            [ws authResult:isSuccess];
-//            [ws setDeviceSecret:@"" completation:nil];
-        };
-    }
-    return _authManager;
-}
-
--(AiAliAuthManager *)aliAuthManager{
-    if (!_aliAuthManager) {
-        _aliAuthManager = [[AiAliAuthManager alloc] init];
-        __weak typeof(self) ws = self;
-        _aliAuthManager.outputLog = ^(NSString * _Nonnull log) {
-            [ws showLog:log];
-        };
-        _aliAuthManager.setDeviceSecret = ^(NSString * _Nonnull value, AiAliCmdFinishBlock  _Nonnull finished) {
-            [ws setDeviceSecret:value completation:finished];
-        };
-        _aliAuthManager.authCallBack = ^(BOOL isSuccess) {
-            [ws authResult:isSuccess];
-//            [ws setDeviceSecret:@"" completation:nil];
-        };
-    }
-    return _aliAuthManager;
-}
--(AiBkzhAuthManager *)bkAuthManager{
-    if (!_bkAuthManager) {
-        _bkAuthManager = [[AiBkzhAuthManager alloc] init];
-        __weak typeof(self) ws = self;
-        _bkAuthManager.outputLog = ^(NSString * _Nonnull log) {
-            [ws showLog:log];
-        };
-        _bkAuthManager.setDeviceSecret = ^(NSString * _Nonnull value, AiBkzhCmdFinishBlock  _Nonnull finished) {
-            [ws setDeviceSecret:value completation:finished];
-        };
-        _bkAuthManager.authCallBack = ^(BOOL isSuccess) {
-            [ws authResult:isSuccess];
-        };
-    }
-    return _bkAuthManager;
-}
-
 -(AiAudioManager *)audioManager{
     if (!_audioManager) {
         _audioManager = [[AiAudioManager alloc] init];
 }
 
 #pragma mark - pub Api
-- (void)setLogLevel:(AiMouseLogLevel)level{
-    _logLevel = level;
-}
 - (void)didDisconnect{
     [self stopRecord:true];
 //    [self.connectManager disConnected];
         }
     }
 }
-//开始鉴权
-- (void)startAuthentication:(AiMouseAuthType)type finished:(void (^)(AiMouseAuthState))complete{
-    if (type == AiMouseAuthType_none){
-        complete(AiMouseAuthState_Success);
-        return;
-    }
-    [self showLog:@"开始鉴权"];
-    self.authBlock = complete;
-    __block typeof(self) ws = self;
-    [self getDeviceInfo:^(AiMouseDeviceInfo *deviceInfo, NSError *error) {
-        if (error ) {
-            ws.authBlock(AiMouseAuthState_Failure);
-        }
-        else{
-            if(type == AiMouseAuthType_Ali){
-                [ws.aliAuthManager loginWith:deviceInfo];
-            }
-            else if(type == AiMouseAuthType_BeiKeZhiHui){
-                [ws.bkAuthManager loginWith:deviceInfo];
-            }
-            else{
-                [ws.authManager loginWith:deviceInfo];
-            }
-        }
-    }];
-}
 
 - (void)sendAiDataToSdk:(NSData *)data{
 //    [self showLog:[NSString stringWithFormat:@"[receive][Voice] %@",data]];
     
     [self.deviceInfoManager receiveData:data];
 }
-- (void)setDeviceSecret:(NSString *)value completation:(AiCmdFinishBlock)complete{
-    self.updateDeviceSecret = value;
-    __weak typeof(self) ws = self;
-    [self.deviceInfoManager setDeviceSecret:value completation:^(BOOL isSuccess) {
-        if (isSuccess) {
-            [ws showLog:@"写入deviceSecret成功,查询是否获读取成功..."];
-            //更新成功,检查是否读取到
-            [ws.deviceInfoManager getDeviceInfo:^(AiMouseDeviceInfo * _Nonnull deviceInfo, NSError * _Nonnull error) {
-                if ([deviceInfo.deviceSecret isEqualToString:value]) {
-                    [ws showLog:@"写入deviceSecret成功,读取成功!"];
-                    complete(true);
-                }
-                else{
-                    //查不到,继续写入
-                    [ws showLog:@"查询不到deviceSecret,继续写入!!!"];
-                    [ws setDeviceSecret:ws.updateDeviceSecret completation:complete];
-                }
-            }];
-        }
-        else{
-            [ws showLog:@"写入deviceSecret失败!"];
-            [ws setDeviceSecret:ws.updateDeviceSecret completation:complete];
-        }
-    }];
-}
+
 - (void)getDeviceInfo:(void (^)(AiMouseDeviceInfo *deviceInfo,NSError *error))complete{
     
     __weak typeof(self) ws = self;
 }
 #pragma mark - other
 - (void)sendRecordData:(NSData *)data{
-//    if (self.authState != AiMouseAuthState_Success){
-//        [self showLog:@"设备还未鉴权!!!"];
-//        return;
-//    };
 //    [self showLog:[NSString stringWithFormat:@"[audio] %@",data]];
     if (self.delegate)  [self.delegate aiMouseSendRecordData:data];
 }
 - (void)sendCmdData:(NSData *)data{
-//    if (self.authState != AiMouseAuthState_Success){
-//        [self showLog:@"设备还未鉴权!!!"];
-//        return;
-//    }
     [self showLog:[NSString stringWithFormat:@"[send] %@",data]];
     if (self.delegate) [self.delegate aiMouseSendCmdData:data];
 }
     if (self.delegate && [self.delegate respondsToSelector:@selector(aiMouseAddLog:)]) {
         [self.delegate aiMouseAddLog:[NSString stringWithFormat:@"[frk]%@",log]];
     }
-//    if(self.logLevel == AiMouseLogLevel_info){
-//        NSLog(@"[frk]%@",log);
-//    }
 }
 
 - (void)checkAuthState{
-    if (self.isAuthing) {
-        return;
-    }
-    self.isAuthing = true;
-    __weak typeof(self) ws = self;
-    [self startAuthentication:AiMouseAuthType_none finished:^(AiMouseAuthState state) {
-        ws.isAuthing = false;
-        [ws showLog:state == AiMouseAuthState_Success? @"鉴权成功":@"鉴权失败"];
-        if(ws.delegate) [ws.delegate aiMouseAuthenticationResult:state];
-    }];
+    if(self.delegate) [self.delegate aiMouseAuthenticationResult:AiMouseAuthState_Success];
 }
 #pragma mark - deviceInfo
 - (void)startRecord{
index 510a131..059156d 100644 (file)
@@ -7,28 +7,87 @@
 
 #import "ByteDanceSdk.h"
 #import "stb_app.h"
+#import "AiMouseTools.h"
+#import "LogManager.h"
+//appID:tis_test
+//
+//token:x3hWlrnUZXG2mlIlmvQ35gUUSTkmOa0m
+//
+//expireTime:1734588385677
+//
+//host:ainf.tis.cn-beijing.volces.com
+//
+//urlParam:productKey=k1r8dWlSOjM&deviceName=1A2B3C4D5E6F&iotInstanceId=iot-060aenzm&timestamp=1734501985677&sign=f140c796052fbd3a66cad9814e19d6f9ac571fcf3595c1116e1be39225295033
 
 @implementation ByteDanceSdk
 
-+(ByteDanceSdk *)shared{
-    static ByteDanceSdk *manager = nil;
-    static dispatch_once_t oncePredicate;
-    dispatch_once(&oncePredicate, ^{
-        manager = [[ByteDanceSdk alloc]init];
-        [manager initSdk];
-    });
-    return manager;
+//+(ByteDanceSdk *)shared{
+//    static ByteDanceSdk *manager = nil;
+//    static dispatch_once_t oncePredicate;
+//    dispatch_once(&oncePredicate, ^{
+//        manager = [[ByteDanceSdk alloc]init];
+//        [manager initSdk];
+//    });
+//    return manager;
+//}
+
+-(instancetype)init{
+    if (self = [super init]) {
+        [self initSdk];
+    }
+    return self;
 }
 
 - (void)initSdk{
-    NSString *appId = @"";
+    [[LogManager shared] addLog:@"开始初始化"];
+    stb_app_printf_str_register(cus_printf_str);
+    NSString *appId = @"tis_test";
     int code = stb_app_init([appId UTF8String]);
-    stb_app_event_callback_register(eventCallBack);
+    stb_app_event_callback_register(cust_event_callback_func);
+    stb_app_send_data_to_device_register(cus_hal_send_data2device);
 }
 
 
-static void eventCallBack(uint32_t type,uint8_t *report, uint32_t data_len){
+- (void)startAuth{
+    stb_app_start_identify();
+}
+
+#pragma mark - ByteDance
+void STB_STDCALL cus_printf_str(char* str)
+{
+    NSString *logStr = [NSString stringWithFormat:@"%s", str];
+    [[LogManager shared] addLog:logStr];
+    return;
+}
+static void cust_event_callback_func(uint32_t type,uint8_t *report, uint32_t data_len){
     NSData *data = [[NSData alloc] initWithBytes:report length:data_len];
-    NSLog(@"type = ,data = %@,data_len = %d",type,data,data_len);
+    [[LogManager shared] addLog:[NSString stringWithFormat:@"type = ,data = %@,data_len = %d",type,data,data_len]];
 }
+
+int32_t STB_STDCALL cus_hal_send_data2device(uint8_t* data, uint32_t len)
+{
+    NSData *sendData = [[NSData alloc] initWithBytes:data length:len];
+    [[LogManager shared] addLog:[NSString stringWithFormat:@"sendData = %@",[AiMouseTools dataToHexString_placeholder:sendData]]];
+//    std::ostringstream oss;
+//    // 把数据转换成十六进制字符串
+//    IBuffer buffer;
+//    for (uint32_t i = 0; i < len; ++i)
+//    {
+//        oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(data[i]) << " ";
+//    }
+//    // 转换为字符串并使用 OutputDebugString 输出
+//    std::string hexData = oss.str();
+//    OutputDebugString(L"[STBAPP] send data 2 device:\n");
+//    OutputDebugStringA(hexData.c_str());
+//    DataWriter writer;
+//    for (uint32_t i = 0; i < len; ++i)
+//    {
+//        writer.WriteByte(data[i]);
+//    }
+//    writer.WriteByte('\n');
+//    buffer = writer.DetachBuffer();
+//    CusWriteCharacteristic.WriteValueAsync(buffer);
+    return 0;
+}
+
 @end
index 215acec..ea26770 100644 (file)
@@ -110,6 +110,7 @@ NS_ASSUME_NONNULL_BEGIN
 /// - finished: 执行结果回调
 - (void)closeRecord:(void (^)(BOOL isSuccess,NSError *error))finished;
 
+
 @end
 
 NS_ASSUME_NONNULL_END
index 433ba2d..c570ca9 100644 (file)
@@ -53,8 +53,6 @@
         [self setupBle];
         [self setupHid];
         [self setupTimer];
-//        [self setupKeyboard];
-        [[ByteDanceSdk shared] init];
     }
     return self;
 }
     
     self.tlwSdk = [[TlwMouse alloc] init];
     [self.tlwSdk setDelegate:self];
-    [self.tlwSdk setLogLevel:(TlwMouseLogLevel_none)];
     
     self.frkSdk = [AiMouse shared];
     [self.frkSdk setDelegate:self];
-    [self.frkSdk setLogLevel:AiMouseLogLevel_none];
 }
 
-- (void)setupKeyboard{
-    [KeyboardHidManager shared].receiveInfoDataCallBack = ^(NSData * _Nonnull data) {
-        
-    };
-    [KeyboardHidManager shared].connectStateCallBack = ^(BOOL connected) {
-        [self.kbSdk switchConnect:AiMouseConnectType_hid isConnected:true];
-    };
-    [KeyboardHidManager shared].logCallBack = ^(NSString * _Nonnull log) {
-        [self showLog:log];
-    };
-    [[KeyboardHidManager shared] open];
-}
 - (void)setupTimer{
     [TimerManager shared].timerCallBack = ^{
 //        [self showLog:@"timer action。。。"];
diff --git a/MouseSdk/AiMouseSdk/Manager/LogManager.h b/MouseSdk/AiMouseSdk/Manager/LogManager.h
new file mode 100644 (file)
index 0000000..afbdf05
--- /dev/null
@@ -0,0 +1,20 @@
+//
+//  LogManager.h
+//  AiMouseManager
+//
+//  Created by liangshi on 2024/12/24.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface LogManager : NSObject
++(LogManager *)shared;
+
+- (void)addLog:(NSString *)log type:(NSString *)type;
+
+- (void)addLog:(NSString *)log;
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/MouseSdk/AiMouseSdk/Manager/LogManager.m b/MouseSdk/AiMouseSdk/Manager/LogManager.m
new file mode 100644 (file)
index 0000000..dab9a3a
--- /dev/null
@@ -0,0 +1,26 @@
+//
+//  LogManager.m
+//  AiMouseManager
+//
+//  Created by liangshi on 2024/12/24.
+//
+
+#import "LogManager.h"
+
+@implementation LogManager
+
++(LogManager *)shared{
+    static LogManager *manager = nil;
+    static dispatch_once_t oncePredicate;
+    dispatch_once(&oncePredicate, ^{
+        manager = [[LogManager alloc]init];
+//        [manager initSdk];
+    });
+    return manager;
+}
+
+- (void)addLog:(NSString *)log{
+    NSString *str = [NSString stringWithFormat:@"%@",log];
+    NSLog(str);
+}
+@end
index 4888b3a..dd6cc23 100644 (file)
@@ -68,9 +68,6 @@ typedef NS_ENUM(NSInteger,TlwMouseLogLevel) {
 @property (nonatomic, readonly) AiMouseConnectType connectType;//连接类型
 @property (nonatomic, readonly) BOOL connected;//是否已连接
 
-/// 设置日志等级
-/// - Parameter level: 等级
-- (void)setLogLevel:(TlwMouseLogLevel)level;
 
 /// 断开连接
 - (void)didDisconnect;
index ba115f3..a3b98f2 100644 (file)
@@ -25,7 +25,6 @@
 
 @interface TlwMouse()
 
-@property (nonatomic, assign) TlwMouseLogLevel logLevel;
 @property (nonatomic, strong) TlwAudioManager *audioManager;
 @property (nonatomic, strong) AiRecordManager *recordManager;
 
@@ -51,7 +50,6 @@
 
 -(instancetype)init{
     if (self = [super init]) {
-        _logLevel = TlwMouseLogLevel_none;
         _connectType = AiMouseConnectType_bluetooth;
 //        NSLog(@"[TlwMouseSdk]%@",[NSString stringWithFormat:@"AiMouseSdk_v%@",self.version]);
         [self.recordManager checkPermissions];
 }
 
 #pragma mark - pub Api
-- (void)setLogLevel:(TlwMouseLogLevel)level{
-    _logLevel = level;
-}
 - (void)didDisconnect{
     _connected = false;
     [self stopRecord];
     if (self.delegate && [self.delegate respondsToSelector:@selector(tlwMouseAddLog:)]) {
         [self.delegate tlwMouseAddLog:[NSString stringWithFormat:@"[tlw]%@",log]];
     }
-    //    if(self.logLevel == TlwMouseLogLevel_info){
-    //        NSLog(@"[tlw]%@",log);
-    //    }
 }
 
 
diff --git a/MouseSdk/MouseSdk.xcodeproj/xcuserdata/yaozuopan.xcuserdatad/xcschemes/xcschememanagement.plist b/MouseSdk/MouseSdk.xcodeproj/xcuserdata/yaozuopan.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644 (file)
index 0000000..4333a46
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>SchemeUserState</key>
+       <dict>
+               <key>MouseSdk.xcscheme_^#shared#^_</key>
+               <dict>
+                       <key>orderHint</key>
+                       <integer>1</integer>
+               </dict>
+       </dict>
+</dict>
+</plist>
diff --git a/MouseSdk/MouseSdk.xcworkspace/xcuserdata/yaozuopan.xcuserdatad/UserInterfaceState.xcuserstate b/MouseSdk/MouseSdk.xcworkspace/xcuserdata/yaozuopan.xcuserdatad/UserInterfaceState.xcuserstate
new file mode 100644 (file)
index 0000000..4b64755
Binary files /dev/null and b/MouseSdk/MouseSdk.xcworkspace/xcuserdata/yaozuopan.xcuserdatad/UserInterfaceState.xcuserstate differ
index 85ecaf6..5c68a7b 100644 (file)
         self.deviceInfoLabel = label;
         [self.view addSubview:label];
     }
+    
+    {
+        NSButton *btn = [[NSButton alloc]initWithFrame:NSMakeRect(50, self.view.bounds.size.height - 300, 100, 45)];
+        btn.bordered = true;
+        btn.title = @"字节";
+        [btn setTarget:self];
+        [btn setAction:@selector(byteDanceAction:)];
+        btn.state = 1;
+        [self.view addSubview:btn];
+    }
 }
 
 #pragma mark - action
         }
     }];
 }
+
+#pragma mark - byteDance
+- (void)byteDanceAction:(NSButton *)sender {
+    NSMenu *popupMenu = [[NSMenu alloc] initWithTitle:@"Popup Menu"];
+    NSMenuItem *item1 = [[NSMenuItem alloc] initWithTitle:@"鉴权" action:@selector(startAuth:) keyEquivalent:@"1"];
+//    NSMenuItem *item2 = [[NSMenuItem alloc] initWithTitle:@"语音停止" action:@selector(voiceStop:) keyEquivalent:@"2"];
+//    NSMenuItem *item3 = [[NSMenuItem alloc] initWithTitle:@"设置DPI" action:@selector(setDPI:) keyEquivalent:@"3"];
+//    NSMenuItem *item4 = [[NSMenuItem alloc] initWithTitle:@"鼠标状态查询" action:@selector(searchState:) keyEquivalent:@"4"];
+//    NSMenuItem *item5 = [[NSMenuItem alloc] initWithTitle:@"设置滚轮开关" action:@selector(setUrlState:) keyEquivalent:@"5"];
+//    NSMenuItem *item6 = [[NSMenuItem alloc] initWithTitle:@"获取滚轮开关" action:@selector(getUrlState:) keyEquivalent:@"6"];
+    
+    [popupMenu addItem:item1];
+//    [popupMenu addItem:item2];
+//    [popupMenu addItem:item3];
+//    [popupMenu addItem:item4];
+//    [popupMenu addItem:item5];
+//    [popupMenu addItem:item6];
+    
+    NSPoint buttonLocation = [sender convertPoint:NSZeroPoint toView:self.view];
+    [popupMenu popUpMenuPositioningItem:nil atLocation:buttonLocation inView:self.view];
+}
+
+- (void)startAuth:(NSMenuItem*)sender {
+//    [[DeviceManger shared] startByteDanceAuth];
+}
+
+
 @end
diff --git a/MouseSdk/Pods/Pods.xcodeproj/xcuserdata/yaozuopan.xcuserdatad/xcschemes/xcschememanagement.plist b/MouseSdk/Pods/Pods.xcodeproj/xcuserdata/yaozuopan.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644 (file)
index 0000000..d2ea65a
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>SchemeUserState</key>
+       <dict>
+               <key>Masonry.xcscheme_^#shared#^_</key>
+               <dict>
+                       <key>orderHint</key>
+                       <integer>4</integer>
+               </dict>
+               <key>Pods-MouseSdk.xcscheme_^#shared#^_</key>
+               <dict>
+                       <key>orderHint</key>
+                       <integer>2</integer>
+               </dict>
+       </dict>
+</dict>
+</plist>