From 1377b184dc6c1d62d5442ab6b7a4c332923a6a57 Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Fri, 15 Mar 2024 13:20:19 +0300 Subject: [PATCH 01/16] Added sony base class and enums --- src/sony/Sony.cpp | 39 +++++++++++++++++++++++++++ src/sony/Sony.h | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 src/sony/Sony.cpp create mode 100644 src/sony/Sony.h diff --git a/src/sony/Sony.cpp b/src/sony/Sony.cpp new file mode 100644 index 0000000..7707322 --- /dev/null +++ b/src/sony/Sony.cpp @@ -0,0 +1,39 @@ +#include "Sony.h" +#include "Logger.h" + +namespace MagicPodsCore +{ + SonyBaseCmd::SonyBaseCmd(std::string tag) : _tag{tag} + { + } + void SonyBaseCmd::PrintAsHex() + { + LOG_DEBUG("%s ", _tag.c_str()); + std::vector bytes = Request(1); + for (int i = 0; i < bytes.size(); i++) + printf("%02x", bytes[i]); + } + + std::vector SonyBaseCmd::Request(unsigned char prefix){ + return SonyBaseCmd::CreateCompletePacket(SonyBaseCmd::CreatePacketBody(prefix)); + } + + std::vector SonyBaseCmd::CreateCompletePacket(std::vector packetBody) + { + unsigned char crc = 0; + + for (int i = 0; i < packetBody.size(); i++) + crc += packetBody[i]; + + packetBody.insert(packetBody.begin(), startByte); + packetBody.insert(packetBody.end(), crc); + packetBody.insert(packetBody.end(), endByte); + + return packetBody; + } + + void SonyBaseCmd::ProcessResponse(const std::vector& bytes){ + IsProcessed = true; + LOG_RELEASE("Request %s processed", _tag.c_str()); + } +} \ No newline at end of file diff --git a/src/sony/Sony.h b/src/sony/Sony.h new file mode 100644 index 0000000..fbbaba1 --- /dev/null +++ b/src/sony/Sony.h @@ -0,0 +1,68 @@ +#pragma once + +#include "AppleProductIds.h" +#include "BtVendorIds.h" +#include "Event.h" + +#include +#include +#include +#include +#include + +namespace MagicPodsCore +{ + + enum class SonyAncFilter : unsigned char + { + Ambient = 0x00, + Wind = 0x01, + Anc = 0x02, + }; + + enum class SonyAncFilter : unsigned char + { + Off = 0x00, + On = 0x01, + }; + + enum class SonyAncSwitch : unsigned char + { + Off = 0x00, + On = 0x10, + //Save current mode to headphones + //When user click switch mode button on headphones, the headphones will switch next mode based on saved setting. + //Default cycle: ANC -> Ambient -> Disable. + //If you Ambient, the next mode will be "Disable" when user click headphones button. + //if you Ambient, the next mode will be any, since we are not changing the default cycle. + //Option also write Volume and Voice settings for ambient mode. + //Option can override Ambient mode to Wind mode, the headphones will speak "Ambient mode", but the real mode will be wind. This is strange, but works. + OnAndSave = 0x11, + }; + + class SonyBaseCmd + { + protected: + std::string _tag{}; + + public: + bool IsProcessed; + explicit SonyBaseCmd(std::string tag); + std::vector Request(unsigned char prefix); + void PrintAsHex(); + virtual void ProcessResponse(const std::vector &bytes); + + protected: + // First byte of packet for battery, ANC commands + unsigned char startByte = 62; + + // The last byte of all packet. I do not know why + unsigned char endByte = 60; + + // Create packet body without beginning and end. This body used to calculate CRC. + virtual std::vector CreatePacketBody(unsigned char prefix) const = 0; + + // Add start and end bytes and calculate CRC to CreatePacketBody + std::vector CreateCompletePacket(std::vector packetBody); + }; +} \ No newline at end of file From ff4fb09c4f3041d7c194eb329629f28f1843ea39 Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Fri, 15 Mar 2024 17:20:58 +0300 Subject: [PATCH 02/16] Added SonyGetAnc --- src/sony/Sony.cpp | 85 +++++++++++++++++++++++++++++++++++++++++++++-- src/sony/Sony.h | 47 ++++++++++++++++++++++++-- 2 files changed, 127 insertions(+), 5 deletions(-) diff --git a/src/sony/Sony.cpp b/src/sony/Sony.cpp index 7707322..214f0f2 100644 --- a/src/sony/Sony.cpp +++ b/src/sony/Sony.cpp @@ -14,8 +14,14 @@ namespace MagicPodsCore printf("%02x", bytes[i]); } - std::vector SonyBaseCmd::Request(unsigned char prefix){ - return SonyBaseCmd::CreateCompletePacket(SonyBaseCmd::CreatePacketBody(prefix)); + std::vector SonyBaseCmd::Request(unsigned char prefix) + { + return CreateCompletePacket(CreatePacketBody(prefix)); + } + + std::vector SonyBaseCmd::CreatePacketBody(unsigned char prefix) const + { + return std::vector(); } std::vector SonyBaseCmd::CreateCompletePacket(std::vector packetBody) @@ -32,8 +38,81 @@ namespace MagicPodsCore return packetBody; } - void SonyBaseCmd::ProcessResponse(const std::vector& bytes){ + void SonyBaseCmd::ProcessResponse(const std::vector &bytes) + { IsProcessed = true; LOG_RELEASE("Request %s processed", _tag.c_str()); } + + SonyGetAnc::SonyGetAnc() : SonyBaseCmd{"SonyGetAnc"} + { + } + + std::vector SonyGetAnc::CreatePacketBody(unsigned char prefix) const + { + return std::vector{0x0c, prefix, 0x00, 0x00, 0x00, 0x02, 0x66, 0x02}; + } + + void SonyGetAnc::ProcessResponse(const std::vector &bytes) + { + if (bytes.size() == 17 && bytes[6] == 8 && bytes[7] == 103) + { + SonyAncState state; + state.AncSwitch = bytes[9] == 1 ? SonyAncSwitch::On : SonyAncSwitch::Off; + state.AncFilter = static_cast(bytes[11]); + state.AmbientVoice = static_cast(bytes[13]); + state.Volume = bytes[14]; + + LOG_RELEASE("%s %s %s Volume: %d", + DummyConvertSonyAncSwitch(state.AncSwitch).c_str(), + DummyConvertSonyAncFilter(state.AncFilter).c_str(), + DummyConvertSonyAncFilterAmbientVoice(state.AmbientVoice).c_str(), + state.Volume + ); + } + } + + std::string SonyGetAnc::DummyConvertSonyAncSwitch(SonyAncSwitch status) + { + switch (status) + { + case SonyAncSwitch::Off: + return "Off"; + case SonyAncSwitch::On: + return "On"; + case SonyAncSwitch::OnAndSave: + return "OnAndSave"; + default: + return "Unknown"; + } + } + + std::string SonyGetAnc::DummyConvertSonyAncFilter(SonyAncFilter status) + { + switch (status) + { + case SonyAncFilter::Ambient: + return "Ambient"; + + case SonyAncFilter::Anc: + return "Anc"; + case SonyAncFilter::Wind: + return "Wind"; + default: + return "Unknown"; + } + } + + std::string SonyGetAnc::DummyConvertSonyAncFilterAmbientVoice(SonyAncFilterAmbientVoice status) + { + switch (status) + { + case SonyAncFilterAmbientVoice::Off: + return "Off"; + case SonyAncFilterAmbientVoice::On: + return "On"; + default: + return "Unknown"; + } + } } \ No newline at end of file diff --git a/src/sony/Sony.h b/src/sony/Sony.h index fbbaba1..fb524aa 100644 --- a/src/sony/Sony.h +++ b/src/sony/Sony.h @@ -20,7 +20,7 @@ namespace MagicPodsCore Anc = 0x02, }; - enum class SonyAncFilter : unsigned char + enum class SonyAncFilterAmbientVoice : unsigned char { Off = 0x00, On = 0x01, @@ -40,6 +40,13 @@ namespace MagicPodsCore OnAndSave = 0x11, }; + struct SonyAncState { + SonyAncSwitch AncSwitch{}; + SonyAncFilter AncFilter{}; + SonyAncFilterAmbientVoice AmbientVoice{}; + unsigned char Volume{}; + }; + class SonyBaseCmd { protected: @@ -60,9 +67,45 @@ namespace MagicPodsCore unsigned char endByte = 60; // Create packet body without beginning and end. This body used to calculate CRC. - virtual std::vector CreatePacketBody(unsigned char prefix) const = 0; + virtual std::vector CreatePacketBody(unsigned char prefix) const; // Add start and end bytes and calculate CRC to CreatePacketBody std::vector CreateCompletePacket(std::vector packetBody); }; + + // --------------------------------------------------------------------------- + // Request + // 3e0c00000000026602763c + // |Body packet | + // 0 1 2 3 4 5 6 7 8 9 10 + // s p c cr e + // 3e 0c 00 00 00 00 02 66 02 76 3c + // + // 0 byte: + // 3e - Packet start (const) + // + // 2 byte: + // 00 - prefix + // 01 - prefix + // + // 7 byte: command + // + // 9 byte: CRC + // + // 10 byte: + // 3c - Packed end (const) + // --------------------------------------------------------------------------- + class SonyGetAnc : public SonyBaseCmd { + public: + SonyGetAnc(); + SonyAncState state{}; + void ProcessResponse(const std::vector &bytes) override; + protected: + std::vectorCreatePacketBody(unsigned char prefix) const override; + + private: + std::string DummyConvertSonyAncSwitch(SonyAncSwitch status); + std::string DummyConvertSonyAncFilter(SonyAncFilter status); + std::string DummyConvertSonyAncFilterAmbientVoice(SonyAncFilterAmbientVoice status); + }; } \ No newline at end of file From 574aef1685ccbd0e19576b06623e032c32ab0e75 Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Fri, 15 Mar 2024 19:21:56 +0300 Subject: [PATCH 03/16] Separated Sony.cpp Sony.h --- src/sony/SonyBaseCmd.cpp | 47 +++++++++++++++++++++ src/sony/SonyBaseCmd.h | 35 +++++++++++++++ src/sony/{Sony.cpp => SonyGetAnc.cpp} | 61 +++++---------------------- src/sony/{Sony.h => SonyGetAnc.h} | 34 +-------------- 4 files changed, 94 insertions(+), 83 deletions(-) create mode 100644 src/sony/SonyBaseCmd.cpp create mode 100644 src/sony/SonyBaseCmd.h rename src/sony/{Sony.cpp => SonyGetAnc.cpp} (54%) rename src/sony/{Sony.h => SonyGetAnc.h} (72%) diff --git a/src/sony/SonyBaseCmd.cpp b/src/sony/SonyBaseCmd.cpp new file mode 100644 index 0000000..12174f5 --- /dev/null +++ b/src/sony/SonyBaseCmd.cpp @@ -0,0 +1,47 @@ + +#include "SonyBaseCmd.h" +#include "Logger.h" + +namespace MagicPodsCore +{ + SonyBaseCmd::SonyBaseCmd(std::string tag) : _tag{tag} + { + } + void SonyBaseCmd::PrintAsHex() + { + LOG_DEBUG("%s ", _tag.c_str()); + std::vector bytes = Request(1); + for (int i = 0; i < bytes.size(); i++) + printf("%02x", bytes[i]); + } + + std::vector SonyBaseCmd::Request(unsigned char prefix) + { + return CreateCompletePacket(CreatePacketBody(prefix)); + } + + std::vector SonyBaseCmd::CreatePacketBody(unsigned char prefix) const + { + return std::vector(); + } + + std::vector SonyBaseCmd::CreateCompletePacket(std::vector packetBody) + { + unsigned char crc = 0; + + for (int i = 0; i < packetBody.size(); i++) + crc += packetBody[i]; + + packetBody.insert(packetBody.begin(), startByte); + packetBody.insert(packetBody.end(), crc); + packetBody.insert(packetBody.end(), endByte); + + return packetBody; + } + + void SonyBaseCmd::ProcessResponse(const std::vector &bytes) + { + IsProcessed = true; + LOG_RELEASE("Request %s processed", _tag.c_str()); + } +} \ No newline at end of file diff --git a/src/sony/SonyBaseCmd.h b/src/sony/SonyBaseCmd.h new file mode 100644 index 0000000..61ce876 --- /dev/null +++ b/src/sony/SonyBaseCmd.h @@ -0,0 +1,35 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace MagicPodsCore +{ + class SonyBaseCmd + { + protected: + std::string _tag{}; + + public: + bool IsProcessed; + explicit SonyBaseCmd(std::string tag); + std::vector Request(unsigned char prefix); + void PrintAsHex(); + virtual void ProcessResponse(const std::vector &bytes); + + protected: + // First byte of packet for battery, ANC commands + unsigned char startByte = 62; + + // The last byte of all packet. I do not know why + unsigned char endByte = 60; + + // Create packet body without beginning and end. This body used to calculate CRC. + virtual std::vector CreatePacketBody(unsigned char prefix) const; + + // Add start and end bytes and calculate CRC to CreatePacketBody + std::vector CreateCompletePacket(std::vector packetBody); + }; +} \ No newline at end of file diff --git a/src/sony/Sony.cpp b/src/sony/SonyGetAnc.cpp similarity index 54% rename from src/sony/Sony.cpp rename to src/sony/SonyGetAnc.cpp index 214f0f2..3b72deb 100644 --- a/src/sony/Sony.cpp +++ b/src/sony/SonyGetAnc.cpp @@ -1,49 +1,9 @@ -#include "Sony.h" + +#include "SonyGetAnc.h" #include "Logger.h" namespace MagicPodsCore { - SonyBaseCmd::SonyBaseCmd(std::string tag) : _tag{tag} - { - } - void SonyBaseCmd::PrintAsHex() - { - LOG_DEBUG("%s ", _tag.c_str()); - std::vector bytes = Request(1); - for (int i = 0; i < bytes.size(); i++) - printf("%02x", bytes[i]); - } - - std::vector SonyBaseCmd::Request(unsigned char prefix) - { - return CreateCompletePacket(CreatePacketBody(prefix)); - } - - std::vector SonyBaseCmd::CreatePacketBody(unsigned char prefix) const - { - return std::vector(); - } - - std::vector SonyBaseCmd::CreateCompletePacket(std::vector packetBody) - { - unsigned char crc = 0; - - for (int i = 0; i < packetBody.size(); i++) - crc += packetBody[i]; - - packetBody.insert(packetBody.begin(), startByte); - packetBody.insert(packetBody.end(), crc); - packetBody.insert(packetBody.end(), endByte); - - return packetBody; - } - - void SonyBaseCmd::ProcessResponse(const std::vector &bytes) - { - IsProcessed = true; - LOG_RELEASE("Request %s processed", _tag.c_str()); - } - SonyGetAnc::SonyGetAnc() : SonyBaseCmd{"SonyGetAnc"} { } @@ -56,19 +16,18 @@ namespace MagicPodsCore void SonyGetAnc::ProcessResponse(const std::vector &bytes) { if (bytes.size() == 17 && bytes[6] == 8 && bytes[7] == 103) - { - SonyAncState state; + { state.AncSwitch = bytes[9] == 1 ? SonyAncSwitch::On : SonyAncSwitch::Off; state.AncFilter = static_cast(bytes[11]); state.AmbientVoice = static_cast(bytes[13]); state.Volume = bytes[14]; LOG_RELEASE("%s %s %s Volume: %d", - DummyConvertSonyAncSwitch(state.AncSwitch).c_str(), - DummyConvertSonyAncFilter(state.AncFilter).c_str(), - DummyConvertSonyAncFilterAmbientVoice(state.AmbientVoice).c_str(), - state.Volume - ); + DummyConvertSonyAncSwitch(state.AncSwitch).c_str(), + DummyConvertSonyAncFilter(state.AncFilter).c_str(), + DummyConvertSonyAncFilterAmbientVoice(state.AmbientVoice).c_str(), + state.Volume); + SonyBaseCmd::ProcessResponse(bytes); } } @@ -84,7 +43,7 @@ namespace MagicPodsCore return "OnAndSave"; default: return "Unknown"; - } + } } std::string SonyGetAnc::DummyConvertSonyAncFilter(SonyAncFilter status) @@ -93,7 +52,7 @@ namespace MagicPodsCore { case SonyAncFilter::Ambient: return "Ambient"; - + case SonyAncFilter::Anc: return "Anc"; case SonyAncFilter::Wind: diff --git a/src/sony/Sony.h b/src/sony/SonyGetAnc.h similarity index 72% rename from src/sony/Sony.h rename to src/sony/SonyGetAnc.h index fb524aa..8625711 100644 --- a/src/sony/Sony.h +++ b/src/sony/SonyGetAnc.h @@ -1,14 +1,10 @@ #pragma once - -#include "AppleProductIds.h" -#include "BtVendorIds.h" -#include "Event.h" - #include #include #include #include #include +#include "SonyBaseCmd.h" namespace MagicPodsCore { @@ -47,32 +43,6 @@ namespace MagicPodsCore unsigned char Volume{}; }; - class SonyBaseCmd - { - protected: - std::string _tag{}; - - public: - bool IsProcessed; - explicit SonyBaseCmd(std::string tag); - std::vector Request(unsigned char prefix); - void PrintAsHex(); - virtual void ProcessResponse(const std::vector &bytes); - - protected: - // First byte of packet for battery, ANC commands - unsigned char startByte = 62; - - // The last byte of all packet. I do not know why - unsigned char endByte = 60; - - // Create packet body without beginning and end. This body used to calculate CRC. - virtual std::vector CreatePacketBody(unsigned char prefix) const; - - // Add start and end bytes and calculate CRC to CreatePacketBody - std::vector CreateCompletePacket(std::vector packetBody); - }; - // --------------------------------------------------------------------------- // Request // 3e0c00000000026602763c @@ -108,4 +78,4 @@ namespace MagicPodsCore std::string DummyConvertSonyAncFilter(SonyAncFilter status); std::string DummyConvertSonyAncFilterAmbientVoice(SonyAncFilterAmbientVoice status); }; -} \ No newline at end of file +} From 43f999a81d7669ed3ed3838ec878f0c5a61e9820 Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Mon, 18 Mar 2024 13:27:15 +0300 Subject: [PATCH 04/16] Added Sony case battery --- src/sony/SonyGetCaseBattery.cpp | 34 +++++++++++++++++++++++++++++++++ src/sony/SonyGetCaseBattery.h | 20 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/sony/SonyGetCaseBattery.cpp create mode 100644 src/sony/SonyGetCaseBattery.h diff --git a/src/sony/SonyGetCaseBattery.cpp b/src/sony/SonyGetCaseBattery.cpp new file mode 100644 index 0000000..dd4734f --- /dev/null +++ b/src/sony/SonyGetCaseBattery.cpp @@ -0,0 +1,34 @@ + +#include "SonyGetCaseBattery.h" +#include "Logger.h" + + +namespace MagicPodsCore +{ + SonyGetCaseBattery::SonyGetCaseBattery() : SonyBaseCmd{"SonyGetCaseBattery"} + { + } + + std::vector SonyGetCaseBattery::CreatePacketBody(unsigned char prefix) const + { + return std::vector{0x0c, prefix, 0x00, 0x00, 0x00, 0x02, 0x10, 0x02}; + } + + void SonyGetCaseBattery::ProcessResponse(const std::vector &bytes) + { + if (bytes.size() == 13 && bytes[6] == 4 && bytes[7] == 17) + { + auto c = bytes[9]; + + DeviceBatteryData battery; + battery.isCharging = false; + battery.Status = DeviceBatteryStatus::Cached; + battery.Battery = bytes[9]; + + Battery[DeviceBatteryType::Case] = battery; + // Event battery changed + LOG_DEBUG("Battery case: %d", battery.Battery); + SonyBaseCmd::ProcessResponse(bytes); + } + } +} \ No newline at end of file diff --git a/src/sony/SonyGetCaseBattery.h b/src/sony/SonyGetCaseBattery.h new file mode 100644 index 0000000..de210ed --- /dev/null +++ b/src/sony/SonyGetCaseBattery.h @@ -0,0 +1,20 @@ +#pragma once +#include +#include +#include +#include +#include +#include "SonyBaseCmd.h" +#include "../DeviceBattery.h" + +namespace MagicPodsCore +{ + class SonyGetCaseBattery : public SonyBaseCmd { + public: + std::map Battery; + SonyGetCaseBattery(); + void ProcessResponse(const std::vector &bytes) override; + protected: + std::vectorCreatePacketBody(unsigned char prefix) const override; + }; +} From 3e8970d313d798c966da86cebe4141f892a9502b Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Mon, 18 Mar 2024 14:49:46 +0300 Subject: [PATCH 05/16] SonyGetHeadphonesBattery --- src/sony/SonyGetHeadphonesBattery.cpp | 41 +++++++++++++++++++++++++++ src/sony/SonyGetHeadphonesBattery.h | 20 +++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/sony/SonyGetHeadphonesBattery.cpp create mode 100644 src/sony/SonyGetHeadphonesBattery.h diff --git a/src/sony/SonyGetHeadphonesBattery.cpp b/src/sony/SonyGetHeadphonesBattery.cpp new file mode 100644 index 0000000..2de023d --- /dev/null +++ b/src/sony/SonyGetHeadphonesBattery.cpp @@ -0,0 +1,41 @@ + +#include "SonyGetHeadphonesBattery.h" +#include "Logger.h" + +namespace MagicPodsCore +{ + SonyGetHeadphonesBattery::SonyGetHeadphonesBattery() : SonyBaseCmd{"SonyGetHeadphonesBattery"} + { + } + + std::vector SonyGetHeadphonesBattery::CreatePacketBody(unsigned char prefix) const + { + return std::vector{0x0c, prefix, 0x00, 0x00, 0x00, 0x02, 0x10, 0x01}; + } + + void SonyGetHeadphonesBattery::ProcessResponse(const std::vector &bytes) + { + if (bytes.size() == 15 && bytes[6] == 6 && bytes[7] == 17) + { + auto l = bytes[9]; + auto r = bytes[11]; + + DeviceBatteryData batteryL; + batteryL.isCharging = false; + batteryL.Status = l == 0 ? DeviceBatteryStatus::Disconnected : DeviceBatteryStatus::Connected; + batteryL.Battery = l; + + DeviceBatteryData batteryR; + batteryR.isCharging = false; + batteryR.Status = r == 0 ? DeviceBatteryStatus::Disconnected : DeviceBatteryStatus::Connected; + batteryR.Battery = r; + + Battery[DeviceBatteryType::Left] = batteryL; + Battery[DeviceBatteryType::Right] = batteryR; + + // Event battery changed + LOG_DEBUG("Battery Left: %d Right %d", batteryL.Battery, batteryR.Battery); + SonyBaseCmd::ProcessResponse(bytes); + } + } +} \ No newline at end of file diff --git a/src/sony/SonyGetHeadphonesBattery.h b/src/sony/SonyGetHeadphonesBattery.h new file mode 100644 index 0000000..99de400 --- /dev/null +++ b/src/sony/SonyGetHeadphonesBattery.h @@ -0,0 +1,20 @@ +#pragma once +#include +#include +#include +#include +#include +#include "SonyBaseCmd.h" +#include "../DeviceBattery.h" + +namespace MagicPodsCore +{ + class SonyGetHeadphonesBattery : public SonyBaseCmd { + public: + std::map Battery; + SonyGetHeadphonesBattery(); + void ProcessResponse(const std::vector &bytes) override; + protected: + std::vectorCreatePacketBody(unsigned char prefix) const override; + }; +} From a761de8fd937fa312292fe3863c5ee50f0c4beeb Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Mon, 18 Mar 2024 15:20:13 +0300 Subject: [PATCH 06/16] Improved battery parse --- src/sony/SonyGetHeadphonesBattery.cpp | 42 +++++++++++++++++---------- src/sony/SonyGetHeadphonesBattery.h | 5 +++- src/sony/SonyProductIds.h | 12 ++++++++ 3 files changed, 43 insertions(+), 16 deletions(-) create mode 100644 src/sony/SonyProductIds.h diff --git a/src/sony/SonyGetHeadphonesBattery.cpp b/src/sony/SonyGetHeadphonesBattery.cpp index 2de023d..d44cede 100644 --- a/src/sony/SonyGetHeadphonesBattery.cpp +++ b/src/sony/SonyGetHeadphonesBattery.cpp @@ -4,8 +4,9 @@ namespace MagicPodsCore { - SonyGetHeadphonesBattery::SonyGetHeadphonesBattery() : SonyBaseCmd{"SonyGetHeadphonesBattery"} + SonyGetHeadphonesBattery::SonyGetHeadphonesBattery(SonyProductIds model) : SonyBaseCmd{"SonyGetHeadphonesBattery"} { + SonyGetHeadphonesBattery::model = model; } std::vector SonyGetHeadphonesBattery::CreatePacketBody(unsigned char prefix) const @@ -20,21 +21,32 @@ namespace MagicPodsCore auto l = bytes[9]; auto r = bytes[11]; - DeviceBatteryData batteryL; - batteryL.isCharging = false; - batteryL.Status = l == 0 ? DeviceBatteryStatus::Disconnected : DeviceBatteryStatus::Connected; - batteryL.Battery = l; - - DeviceBatteryData batteryR; - batteryR.isCharging = false; - batteryR.Status = r == 0 ? DeviceBatteryStatus::Disconnected : DeviceBatteryStatus::Connected; - batteryR.Battery = r; - - Battery[DeviceBatteryType::Left] = batteryL; - Battery[DeviceBatteryType::Right] = batteryR; - + if (model == SonyProductIds::WH_1000XM4){ + DeviceBatteryData batteryS; + batteryS.isCharging = false; + batteryS.Status = l == 0 ? DeviceBatteryStatus::Disconnected : DeviceBatteryStatus::Connected; + batteryS.Battery = l; + + Battery[DeviceBatteryType::Single] = batteryS; + } + else{ + DeviceBatteryData batteryL; + batteryL.isCharging = false; + batteryL.Status = l == 0 ? DeviceBatteryStatus::Disconnected : DeviceBatteryStatus::Connected; + batteryL.Battery = l; + + DeviceBatteryData batteryR; + batteryR.isCharging = false; + batteryR.Status = r == 0 ? DeviceBatteryStatus::Disconnected : DeviceBatteryStatus::Connected; + batteryR.Battery = r; + + Battery[DeviceBatteryType::Left] = batteryL; + Battery[DeviceBatteryType::Right] = batteryR; + + } // Event battery changed - LOG_DEBUG("Battery Left: %d Right %d", batteryL.Battery, batteryR.Battery); + LOG_DEBUG("Battery Left: %d Right %d", l, r); + SonyBaseCmd::ProcessResponse(bytes); } } diff --git a/src/sony/SonyGetHeadphonesBattery.h b/src/sony/SonyGetHeadphonesBattery.h index 99de400..b2e47bf 100644 --- a/src/sony/SonyGetHeadphonesBattery.h +++ b/src/sony/SonyGetHeadphonesBattery.h @@ -5,6 +5,7 @@ #include #include #include "SonyBaseCmd.h" +#include "SonyProductIds.h" #include "../DeviceBattery.h" namespace MagicPodsCore @@ -12,8 +13,10 @@ namespace MagicPodsCore class SonyGetHeadphonesBattery : public SonyBaseCmd { public: std::map Battery; - SonyGetHeadphonesBattery(); + SonyGetHeadphonesBattery(SonyProductIds model); void ProcessResponse(const std::vector &bytes) override; + private: + SonyProductIds model; protected: std::vectorCreatePacketBody(unsigned char prefix) const override; }; diff --git a/src/sony/SonyProductIds.h b/src/sony/SonyProductIds.h new file mode 100644 index 0000000..ceb6e9d --- /dev/null +++ b/src/sony/SonyProductIds.h @@ -0,0 +1,12 @@ +#pragma once + +// Modalias: bluetooth:v{VendorIds}p{AppleProductIds}dB087 +enum class SonyProductIds : unsigned short { + WH_1000XM4 = 0x0d58, + WF_1000XM3 = 0x0ce0, +}; + +static const SonyProductIds AllSonyProductIds[] = { + SonyProductIds::WH_1000XM4, + SonyProductIds::WF_1000XM3, +}; \ No newline at end of file From b9309a2f63fa32e31ce7bfb85830e590c54eb729 Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Mon, 18 Mar 2024 16:03:41 +0300 Subject: [PATCH 07/16] Added SonySetAnc --- src/sony/SonySetAnc.cpp | 24 ++++++++++++++++++++++++ src/sony/SonySetAnc.h | 20 ++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/sony/SonySetAnc.cpp create mode 100644 src/sony/SonySetAnc.h diff --git a/src/sony/SonySetAnc.cpp b/src/sony/SonySetAnc.cpp new file mode 100644 index 0000000..e5c8dac --- /dev/null +++ b/src/sony/SonySetAnc.cpp @@ -0,0 +1,24 @@ + +#include "SonySetAnc.h" +#include "Logger.h" + +namespace MagicPodsCore +{ + SonySetAnc::SonySetAnc(SonyAncState state) : SonyBaseCmd{"SonySetAnc"} + { + SonySetAnc::state = state; + } + + std::vector SonySetAnc::CreatePacketBody(unsigned char prefix) const + { + return std::vector{0x0c, prefix, 0x00, 0x00, 0x00, 0x08, 0x68, 0x02, (unsigned char)state.AncSwitch, 0x02, (unsigned char)state.AncFilter, 0x01, (unsigned char)state.AmbientVoice, state.Volume }; + } + + void SonySetAnc::ProcessResponse(const std::vector &bytes) + { + if (bytes.size() == 9 && bytes[1] == 1) + { + SonyBaseCmd::ProcessResponse(bytes); + } + } +} \ No newline at end of file diff --git a/src/sony/SonySetAnc.h b/src/sony/SonySetAnc.h new file mode 100644 index 0000000..8e4d9a3 --- /dev/null +++ b/src/sony/SonySetAnc.h @@ -0,0 +1,20 @@ +#pragma once +#include +#include +#include +#include +#include +#include "SonyBaseCmd.h" +#include "SonyGetAnc.h" + +namespace MagicPodsCore +{ + class SonySetAnc : public SonyBaseCmd { + public: + SonySetAnc(SonyAncState state); + SonyAncState state{}; + void ProcessResponse(const std::vector &bytes) override; + protected: + std::vectorCreatePacketBody(unsigned char prefix) const override; + }; +} From 86985dfbdc559b1eeaca5c87e113b75163be8812 Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Mon, 18 Mar 2024 20:56:30 +0300 Subject: [PATCH 08/16] Added SonyAncWatcher. Refactor code --- CMakeLists.txt | 7 ++++ src/sony/SonyAncWatcher.cpp | 73 ++++++++++++++++++++++++++++++++++++ src/sony/SonyAncWatcher.h | 30 +++++++++++++++ src/sony/SonyBaseCmd.cpp | 2 +- src/sony/SonyBaseWatcher.cpp | 15 ++++++++ src/sony/SonyBaseWatcher.h | 19 ++++++++++ 6 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 src/sony/SonyAncWatcher.cpp create mode 100644 src/sony/SonyAncWatcher.h create mode 100644 src/sony/SonyBaseWatcher.cpp create mode 100644 src/sony/SonyBaseWatcher.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 033025a..fb4d6ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,13 @@ add_executable(MagicPodsCore src/DeviceAnc.cpp src/aap/Aap.cpp src/aap/AapClient.cpp + src/sony/SonyBaseCmd.cpp + src/sony/SonyGetAnc.cpp + src/sony/SonySetAnc.cpp + src/sony/SonyGetCaseBattery.cpp + src/sony/SonyGetHeadphonesBattery.cpp + src/sony/SonyBaseWatcher.cpp + src/sony/SonyAncWatcher.cpp ) add_subdirectory(dependencies) target_include_directories(MagicPodsCore PRIVATE src dependencies/json ${PROJECT_BINARY_DIR}/src) diff --git a/src/sony/SonyAncWatcher.cpp b/src/sony/SonyAncWatcher.cpp new file mode 100644 index 0000000..3905c40 --- /dev/null +++ b/src/sony/SonyAncWatcher.cpp @@ -0,0 +1,73 @@ +#include "SonyAncWatcher.h" +#include "Logger.h" + +namespace MagicPodsCore +{ + SonyAncWatcher::SonyAncWatcher() : SonyBaseWatcher{"SonyAncWatcher"} + { + } + + void SonyAncWatcher::ProcessResponse(const std::vector &bytes) + { + if (bytes.size() == 17 && bytes[6] == 8 && bytes[7] == 105) + { + State.AncSwitch = bytes[9] == 1 ? SonyAncSwitch::On : SonyAncSwitch::Off; + State.AncFilter = static_cast(bytes[11]); + State.AmbientVoice = static_cast(bytes[13]); + State.Volume = bytes[14]; + + LOG_RELEASE("%s %s %s Volume: %d", + DummyConvertSonyAncSwitch(State.AncSwitch).c_str(), + DummyConvertSonyAncFilter(State.AncFilter).c_str(), + DummyConvertSonyAncFilterAmbientVoice(State.AmbientVoice).c_str(), + State.Volume); + + _event.FireEvent(State); + SonyBaseWatcher::ProcessResponse(bytes); + } + } + + std::string SonyAncWatcher::DummyConvertSonyAncSwitch(SonyAncSwitch status) + { + switch (status) + { + case SonyAncSwitch::Off: + return "Off"; + case SonyAncSwitch::On: + return "On"; + case SonyAncSwitch::OnAndSave: + return "OnAndSave"; + default: + return "Unknown"; + } + } + + std::string SonyAncWatcher::DummyConvertSonyAncFilter(SonyAncFilter status) + { + switch (status) + { + case SonyAncFilter::Ambient: + return "Ambient"; + + case SonyAncFilter::Anc: + return "Anc"; + case SonyAncFilter::Wind: + return "Wind"; + default: + return "Unknown"; + } + } + + std::string SonyAncWatcher::DummyConvertSonyAncFilterAmbientVoice(SonyAncFilterAmbientVoice status) + { + switch (status) + { + case SonyAncFilterAmbientVoice::Off: + return "Off"; + case SonyAncFilterAmbientVoice::On: + return "On"; + default: + return "Unknown"; + } + } +} \ No newline at end of file diff --git a/src/sony/SonyAncWatcher.h b/src/sony/SonyAncWatcher.h new file mode 100644 index 0000000..51b010d --- /dev/null +++ b/src/sony/SonyAncWatcher.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include +#include +#include +#include +#include "SonyBaseWatcher.h" +#include "SonyGetAnc.h" +#include "../DeviceBattery.h" + +namespace MagicPodsCore +{ + class SonyAncWatcher : public SonyBaseWatcher + { + public: + SonyAncState State{}; + SonyAncWatcher(); + void ProcessResponse(const std::vector &bytes) override; + Event &GetEvent() + { + return _event; + } + + private: + Event _event{}; + std::string DummyConvertSonyAncSwitch(SonyAncSwitch status); + std::string DummyConvertSonyAncFilter(SonyAncFilter status); + std::string DummyConvertSonyAncFilterAmbientVoice(SonyAncFilterAmbientVoice status); + }; +} diff --git a/src/sony/SonyBaseCmd.cpp b/src/sony/SonyBaseCmd.cpp index 12174f5..fd4367b 100644 --- a/src/sony/SonyBaseCmd.cpp +++ b/src/sony/SonyBaseCmd.cpp @@ -42,6 +42,6 @@ namespace MagicPodsCore void SonyBaseCmd::ProcessResponse(const std::vector &bytes) { IsProcessed = true; - LOG_RELEASE("Request %s processed", _tag.c_str()); + LOG_DEBUG("Request %s processed", _tag.c_str()); } } \ No newline at end of file diff --git a/src/sony/SonyBaseWatcher.cpp b/src/sony/SonyBaseWatcher.cpp new file mode 100644 index 0000000..1b183fb --- /dev/null +++ b/src/sony/SonyBaseWatcher.cpp @@ -0,0 +1,15 @@ +#include "SonyBaseWatcher.h" +#include "Logger.h" + +namespace MagicPodsCore +{ + SonyBaseWatcher::SonyBaseWatcher(std::string tag) : _tag{tag} + { + } + + + void SonyBaseWatcher::ProcessResponse(const std::vector &bytes) + { + LOG_DEBUG("Watcher %s processed", _tag.c_str()); + } +} \ No newline at end of file diff --git a/src/sony/SonyBaseWatcher.h b/src/sony/SonyBaseWatcher.h new file mode 100644 index 0000000..f565f9d --- /dev/null +++ b/src/sony/SonyBaseWatcher.h @@ -0,0 +1,19 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace MagicPodsCore +{ + class SonyBaseWatcher + { + protected: + std::string _tag{}; + + public: + explicit SonyBaseWatcher(std::string tag); + virtual void ProcessResponse(const std::vector &bytes); + }; +} \ No newline at end of file From 31bcdc6ddf825b50b654a56e6dad3ed8ba86f6a2 Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Mon, 18 Mar 2024 21:09:59 +0300 Subject: [PATCH 09/16] Added SonyAncHelper --- CMakeLists.txt | 1 + src/sony/SonyAncHelper.cpp | 49 +++++++++++++++++++++++++++++++++ src/sony/SonyAncHelper.h | 18 ++++++++++++ src/sony/SonyAncWatcher.cpp | 55 ++++--------------------------------- src/sony/SonyAncWatcher.h | 3 -- src/sony/SonyGetAnc.cpp | 51 +++------------------------------- src/sony/SonyGetAnc.h | 5 ---- 7 files changed, 78 insertions(+), 104 deletions(-) create mode 100644 src/sony/SonyAncHelper.cpp create mode 100644 src/sony/SonyAncHelper.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fb4d6ba..e1b952f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ add_executable(MagicPodsCore src/sony/SonyGetHeadphonesBattery.cpp src/sony/SonyBaseWatcher.cpp src/sony/SonyAncWatcher.cpp + src/sony/SonyAncHelper.cpp ) add_subdirectory(dependencies) target_include_directories(MagicPodsCore PRIVATE src dependencies/json ${PROJECT_BINARY_DIR}/src) diff --git a/src/sony/SonyAncHelper.cpp b/src/sony/SonyAncHelper.cpp new file mode 100644 index 0000000..0ee0d24 --- /dev/null +++ b/src/sony/SonyAncHelper.cpp @@ -0,0 +1,49 @@ +#include "SonyAncHelper.h" +#include "Logger.h" + +namespace MagicPodsCore +{ +std::string SonyAncHelper::DummyConvertSonyAncSwitch(SonyAncSwitch status) + { + switch (status) + { + case SonyAncSwitch::Off: + return "Off"; + case SonyAncSwitch::On: + return "On"; + case SonyAncSwitch::OnAndSave: + return "OnAndSave"; + default: + return "Unknown"; + } + } + + std::string SonyAncHelper::DummyConvertSonyAncFilter(SonyAncFilter status) + { + switch (status) + { + case SonyAncFilter::Ambient: + return "Ambient"; + + case SonyAncFilter::Anc: + return "Anc"; + case SonyAncFilter::Wind: + return "Wind"; + default: + return "Unknown"; + } + } + + std::string SonyAncHelper::DummyConvertSonyAncFilterAmbientVoice(SonyAncFilterAmbientVoice status) + { + switch (status) + { + case SonyAncFilterAmbientVoice::Off: + return "Off"; + case SonyAncFilterAmbientVoice::On: + return "On"; + default: + return "Unknown"; + } + } +} \ No newline at end of file diff --git a/src/sony/SonyAncHelper.h b/src/sony/SonyAncHelper.h new file mode 100644 index 0000000..a94485e --- /dev/null +++ b/src/sony/SonyAncHelper.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include +#include +#include +#include +#include "SonyGetAnc.h" + +namespace MagicPodsCore +{ + class SonyAncHelper + { + public: + static std::string DummyConvertSonyAncSwitch(SonyAncSwitch status); + static std::string DummyConvertSonyAncFilter(SonyAncFilter status); + static std::string DummyConvertSonyAncFilterAmbientVoice(SonyAncFilterAmbientVoice status); + }; +} \ No newline at end of file diff --git a/src/sony/SonyAncWatcher.cpp b/src/sony/SonyAncWatcher.cpp index 3905c40..a268a1b 100644 --- a/src/sony/SonyAncWatcher.cpp +++ b/src/sony/SonyAncWatcher.cpp @@ -1,4 +1,5 @@ #include "SonyAncWatcher.h" +#include "SonyAncHelper.h" #include "Logger.h" namespace MagicPodsCore @@ -15,59 +16,15 @@ namespace MagicPodsCore State.AncFilter = static_cast(bytes[11]); State.AmbientVoice = static_cast(bytes[13]); State.Volume = bytes[14]; - + LOG_RELEASE("%s %s %s Volume: %d", - DummyConvertSonyAncSwitch(State.AncSwitch).c_str(), - DummyConvertSonyAncFilter(State.AncFilter).c_str(), - DummyConvertSonyAncFilterAmbientVoice(State.AmbientVoice).c_str(), + SonyAncHelper::DummyConvertSonyAncSwitch(State.AncSwitch).c_str(), + SonyAncHelper::DummyConvertSonyAncFilter(State.AncFilter).c_str(), + SonyAncHelper::DummyConvertSonyAncFilterAmbientVoice(State.AmbientVoice).c_str(), State.Volume); - + _event.FireEvent(State); SonyBaseWatcher::ProcessResponse(bytes); } } - - std::string SonyAncWatcher::DummyConvertSonyAncSwitch(SonyAncSwitch status) - { - switch (status) - { - case SonyAncSwitch::Off: - return "Off"; - case SonyAncSwitch::On: - return "On"; - case SonyAncSwitch::OnAndSave: - return "OnAndSave"; - default: - return "Unknown"; - } - } - - std::string SonyAncWatcher::DummyConvertSonyAncFilter(SonyAncFilter status) - { - switch (status) - { - case SonyAncFilter::Ambient: - return "Ambient"; - - case SonyAncFilter::Anc: - return "Anc"; - case SonyAncFilter::Wind: - return "Wind"; - default: - return "Unknown"; - } - } - - std::string SonyAncWatcher::DummyConvertSonyAncFilterAmbientVoice(SonyAncFilterAmbientVoice status) - { - switch (status) - { - case SonyAncFilterAmbientVoice::Off: - return "Off"; - case SonyAncFilterAmbientVoice::On: - return "On"; - default: - return "Unknown"; - } - } } \ No newline at end of file diff --git a/src/sony/SonyAncWatcher.h b/src/sony/SonyAncWatcher.h index 51b010d..ac3695a 100644 --- a/src/sony/SonyAncWatcher.h +++ b/src/sony/SonyAncWatcher.h @@ -23,8 +23,5 @@ namespace MagicPodsCore private: Event _event{}; - std::string DummyConvertSonyAncSwitch(SonyAncSwitch status); - std::string DummyConvertSonyAncFilter(SonyAncFilter status); - std::string DummyConvertSonyAncFilterAmbientVoice(SonyAncFilterAmbientVoice status); }; } diff --git a/src/sony/SonyGetAnc.cpp b/src/sony/SonyGetAnc.cpp index 3b72deb..a45e3aa 100644 --- a/src/sony/SonyGetAnc.cpp +++ b/src/sony/SonyGetAnc.cpp @@ -1,5 +1,6 @@ #include "SonyGetAnc.h" +#include "SonyAncHelper.h" #include "Logger.h" namespace MagicPodsCore @@ -23,55 +24,11 @@ namespace MagicPodsCore state.Volume = bytes[14]; LOG_RELEASE("%s %s %s Volume: %d", - DummyConvertSonyAncSwitch(state.AncSwitch).c_str(), - DummyConvertSonyAncFilter(state.AncFilter).c_str(), - DummyConvertSonyAncFilterAmbientVoice(state.AmbientVoice).c_str(), + SonyAncHelper::DummyConvertSonyAncSwitch(state.AncSwitch).c_str(), + SonyAncHelper::DummyConvertSonyAncFilter(state.AncFilter).c_str(), + SonyAncHelper::DummyConvertSonyAncFilterAmbientVoice(state.AmbientVoice).c_str(), state.Volume); SonyBaseCmd::ProcessResponse(bytes); } } - - std::string SonyGetAnc::DummyConvertSonyAncSwitch(SonyAncSwitch status) - { - switch (status) - { - case SonyAncSwitch::Off: - return "Off"; - case SonyAncSwitch::On: - return "On"; - case SonyAncSwitch::OnAndSave: - return "OnAndSave"; - default: - return "Unknown"; - } - } - - std::string SonyGetAnc::DummyConvertSonyAncFilter(SonyAncFilter status) - { - switch (status) - { - case SonyAncFilter::Ambient: - return "Ambient"; - - case SonyAncFilter::Anc: - return "Anc"; - case SonyAncFilter::Wind: - return "Wind"; - default: - return "Unknown"; - } - } - - std::string SonyGetAnc::DummyConvertSonyAncFilterAmbientVoice(SonyAncFilterAmbientVoice status) - { - switch (status) - { - case SonyAncFilterAmbientVoice::Off: - return "Off"; - case SonyAncFilterAmbientVoice::On: - return "On"; - default: - return "Unknown"; - } - } } \ No newline at end of file diff --git a/src/sony/SonyGetAnc.h b/src/sony/SonyGetAnc.h index 8625711..2065754 100644 --- a/src/sony/SonyGetAnc.h +++ b/src/sony/SonyGetAnc.h @@ -72,10 +72,5 @@ namespace MagicPodsCore void ProcessResponse(const std::vector &bytes) override; protected: std::vectorCreatePacketBody(unsigned char prefix) const override; - - private: - std::string DummyConvertSonyAncSwitch(SonyAncSwitch status); - std::string DummyConvertSonyAncFilter(SonyAncFilter status); - std::string DummyConvertSonyAncFilterAmbientVoice(SonyAncFilterAmbientVoice status); }; } From c09aab2dbac03700e68ab4c916e99df3de14ee55 Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Tue, 19 Mar 2024 13:18:44 +0300 Subject: [PATCH 10/16] Simplify code --- src/sony/SonyAncWatcher.cpp | 1 - src/sony/SonyBaseWatcher.cpp | 6 ------ src/sony/SonyBaseWatcher.h | 2 +- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/sony/SonyAncWatcher.cpp b/src/sony/SonyAncWatcher.cpp index a268a1b..bacc4b4 100644 --- a/src/sony/SonyAncWatcher.cpp +++ b/src/sony/SonyAncWatcher.cpp @@ -24,7 +24,6 @@ namespace MagicPodsCore State.Volume); _event.FireEvent(State); - SonyBaseWatcher::ProcessResponse(bytes); } } } \ No newline at end of file diff --git a/src/sony/SonyBaseWatcher.cpp b/src/sony/SonyBaseWatcher.cpp index 1b183fb..5deea74 100644 --- a/src/sony/SonyBaseWatcher.cpp +++ b/src/sony/SonyBaseWatcher.cpp @@ -6,10 +6,4 @@ namespace MagicPodsCore SonyBaseWatcher::SonyBaseWatcher(std::string tag) : _tag{tag} { } - - - void SonyBaseWatcher::ProcessResponse(const std::vector &bytes) - { - LOG_DEBUG("Watcher %s processed", _tag.c_str()); - } } \ No newline at end of file diff --git a/src/sony/SonyBaseWatcher.h b/src/sony/SonyBaseWatcher.h index f565f9d..fcb06bc 100644 --- a/src/sony/SonyBaseWatcher.h +++ b/src/sony/SonyBaseWatcher.h @@ -14,6 +14,6 @@ namespace MagicPodsCore public: explicit SonyBaseWatcher(std::string tag); - virtual void ProcessResponse(const std::vector &bytes); + virtual void ProcessResponse(const std::vector &bytes) = 0; }; } \ No newline at end of file From ab336e3a5c32c45943456bb913338d206295f078 Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Tue, 19 Mar 2024 13:34:36 +0300 Subject: [PATCH 11/16] Create H for enum and struct --- src/sony/SonyAncHelper.h | 2 +- src/sony/SonyEnums.h | 32 ++++++++++++++++++++++++++++++++ src/sony/SonyGetAnc.h | 36 +----------------------------------- src/sony/SonySetAnc.h | 2 +- src/sony/SonyStructs.h | 12 ++++++++++++ 5 files changed, 47 insertions(+), 37 deletions(-) create mode 100644 src/sony/SonyEnums.h create mode 100644 src/sony/SonyStructs.h diff --git a/src/sony/SonyAncHelper.h b/src/sony/SonyAncHelper.h index a94485e..46e3caf 100644 --- a/src/sony/SonyAncHelper.h +++ b/src/sony/SonyAncHelper.h @@ -4,7 +4,7 @@ #include #include #include -#include "SonyGetAnc.h" +#include "SonyEnums.h" namespace MagicPodsCore { diff --git a/src/sony/SonyEnums.h b/src/sony/SonyEnums.h new file mode 100644 index 0000000..beb2a4b --- /dev/null +++ b/src/sony/SonyEnums.h @@ -0,0 +1,32 @@ +#pragma once + +namespace MagicPodsCore +{ + + enum class SonyAncFilter : unsigned char + { + Ambient = 0x00, + Wind = 0x01, + Anc = 0x02, + }; + + enum class SonyAncFilterAmbientVoice : unsigned char + { + Off = 0x00, + On = 0x01, + }; + + enum class SonyAncSwitch : unsigned char + { + Off = 0x00, + On = 0x10, + //Save current mode to headphones + //When user click switch mode button on headphones, the headphones will switch next mode based on saved setting. + //Default cycle: ANC -> Ambient -> Disable. + //If you Ambient, the next mode will be "Disable" when user click headphones button. + //if you Ambient, the next mode will be any, since we are not changing the default cycle. + //Option also write Volume and Voice settings for ambient mode. + //Option can override Ambient mode to Wind mode, the headphones will speak "Ambient mode", but the real mode will be wind. This is strange, but works. + OnAndSave = 0x11, + }; +} diff --git a/src/sony/SonyGetAnc.h b/src/sony/SonyGetAnc.h index 2065754..7e115b1 100644 --- a/src/sony/SonyGetAnc.h +++ b/src/sony/SonyGetAnc.h @@ -5,44 +5,10 @@ #include #include #include "SonyBaseCmd.h" +#include "SonyStructs.h" namespace MagicPodsCore { - - enum class SonyAncFilter : unsigned char - { - Ambient = 0x00, - Wind = 0x01, - Anc = 0x02, - }; - - enum class SonyAncFilterAmbientVoice : unsigned char - { - Off = 0x00, - On = 0x01, - }; - - enum class SonyAncSwitch : unsigned char - { - Off = 0x00, - On = 0x10, - //Save current mode to headphones - //When user click switch mode button on headphones, the headphones will switch next mode based on saved setting. - //Default cycle: ANC -> Ambient -> Disable. - //If you Ambient, the next mode will be "Disable" when user click headphones button. - //if you Ambient, the next mode will be any, since we are not changing the default cycle. - //Option also write Volume and Voice settings for ambient mode. - //Option can override Ambient mode to Wind mode, the headphones will speak "Ambient mode", but the real mode will be wind. This is strange, but works. - OnAndSave = 0x11, - }; - - struct SonyAncState { - SonyAncSwitch AncSwitch{}; - SonyAncFilter AncFilter{}; - SonyAncFilterAmbientVoice AmbientVoice{}; - unsigned char Volume{}; - }; - // --------------------------------------------------------------------------- // Request // 3e0c00000000026602763c diff --git a/src/sony/SonySetAnc.h b/src/sony/SonySetAnc.h index 8e4d9a3..d488122 100644 --- a/src/sony/SonySetAnc.h +++ b/src/sony/SonySetAnc.h @@ -5,7 +5,7 @@ #include #include #include "SonyBaseCmd.h" -#include "SonyGetAnc.h" +#include "SonyStructs.h" namespace MagicPodsCore { diff --git a/src/sony/SonyStructs.h b/src/sony/SonyStructs.h new file mode 100644 index 0000000..3065949 --- /dev/null +++ b/src/sony/SonyStructs.h @@ -0,0 +1,12 @@ +#pragma once +#include "SonyEnums.h" + +namespace MagicPodsCore +{ + struct SonyAncState { + SonyAncSwitch AncSwitch{}; + SonyAncFilter AncFilter{}; + SonyAncFilterAmbientVoice AmbientVoice{}; + unsigned char Volume{}; + }; +} From 32d3e350ba920d0f2423b3e955e937d01bc8d6f6 Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Tue, 19 Mar 2024 13:42:57 +0300 Subject: [PATCH 12/16] Removed unnecessary includes --- src/sony/SonyAncHelper.h | 4 ---- src/sony/SonyAncWatcher.h | 5 ----- src/sony/SonyGetAnc.h | 5 ----- src/sony/SonyGetCaseBattery.h | 5 ----- src/sony/SonyGetHeadphonesBattery.h | 5 ----- src/sony/SonySetAnc.h | 5 ----- 6 files changed, 29 deletions(-) diff --git a/src/sony/SonyAncHelper.h b/src/sony/SonyAncHelper.h index 46e3caf..8602230 100644 --- a/src/sony/SonyAncHelper.h +++ b/src/sony/SonyAncHelper.h @@ -1,9 +1,5 @@ #pragma once -#include -#include #include -#include -#include #include "SonyEnums.h" namespace MagicPodsCore diff --git a/src/sony/SonyAncWatcher.h b/src/sony/SonyAncWatcher.h index ac3695a..8c93d4c 100644 --- a/src/sony/SonyAncWatcher.h +++ b/src/sony/SonyAncWatcher.h @@ -1,9 +1,4 @@ #pragma once -#include -#include -#include -#include -#include #include "SonyBaseWatcher.h" #include "SonyGetAnc.h" #include "../DeviceBattery.h" diff --git a/src/sony/SonyGetAnc.h b/src/sony/SonyGetAnc.h index 7e115b1..cb35a48 100644 --- a/src/sony/SonyGetAnc.h +++ b/src/sony/SonyGetAnc.h @@ -1,9 +1,4 @@ #pragma once -#include -#include -#include -#include -#include #include "SonyBaseCmd.h" #include "SonyStructs.h" diff --git a/src/sony/SonyGetCaseBattery.h b/src/sony/SonyGetCaseBattery.h index de210ed..54d60bc 100644 --- a/src/sony/SonyGetCaseBattery.h +++ b/src/sony/SonyGetCaseBattery.h @@ -1,9 +1,4 @@ #pragma once -#include -#include -#include -#include -#include #include "SonyBaseCmd.h" #include "../DeviceBattery.h" diff --git a/src/sony/SonyGetHeadphonesBattery.h b/src/sony/SonyGetHeadphonesBattery.h index b2e47bf..4bd276e 100644 --- a/src/sony/SonyGetHeadphonesBattery.h +++ b/src/sony/SonyGetHeadphonesBattery.h @@ -1,9 +1,4 @@ #pragma once -#include -#include -#include -#include -#include #include "SonyBaseCmd.h" #include "SonyProductIds.h" #include "../DeviceBattery.h" diff --git a/src/sony/SonySetAnc.h b/src/sony/SonySetAnc.h index d488122..1ba4c1e 100644 --- a/src/sony/SonySetAnc.h +++ b/src/sony/SonySetAnc.h @@ -1,9 +1,4 @@ #pragma once -#include -#include -#include -#include -#include #include "SonyBaseCmd.h" #include "SonyStructs.h" From 764f0e463123202454e0fbb9c7223aa3609bfd06 Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Tue, 19 Mar 2024 13:43:13 +0300 Subject: [PATCH 13/16] Add H to CMake --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index e1b952f..18889f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,8 @@ add_executable(MagicPodsCore src/sony/SonyBaseWatcher.cpp src/sony/SonyAncWatcher.cpp src/sony/SonyAncHelper.cpp + src/sony/SonyEnums.h + src/sony/SonyStructs.h ) add_subdirectory(dependencies) target_include_directories(MagicPodsCore PRIVATE src dependencies/json ${PROJECT_BINARY_DIR}/src) From 1efbd1aaf91f9855698873b62b804d3510c34c6f Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Tue, 19 Mar 2024 14:37:09 +0300 Subject: [PATCH 14/16] Test Sony SDK --- src/mainSonyTests.cpp | 378 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 378 insertions(+) create mode 100644 src/mainSonyTests.cpp diff --git a/src/mainSonyTests.cpp b/src/mainSonyTests.cpp new file mode 100644 index 0000000..3a5de45 --- /dev/null +++ b/src/mainSonyTests.cpp @@ -0,0 +1,378 @@ +#include +#include +#include +#include "Logger.h" +#include +#include "sony/SonyBaseCmd.h" +#include "sony/SonyGetAnc.h" +#include "sony/SonyGetCaseBattery.h" +#include "sony/SonyGetHeadphonesBattery.h" +#include "sony/SonySetAnc.h" +#include "sony/SonyAncWatcher.h" +using namespace MagicPodsCore; + +void PrintBytes(std::vector bytes) +{ + #ifdef DEBUG + printf(" "); + for (int i = 0; i < bytes.size(); i++) + { + printf("%02x", bytes[i]); + } + printf("\n"); + #endif +} + +void TestRequest(SonyBaseCmd &cmd, std::vector bytesP0, std::vector bytesP1) +{ + PrintBytes(cmd.Request(0)); + if (cmd.Request(0) == bytesP0) + { + LOG_RELEASE(" [ ] Prefix 0"); + } + else + { + LOG_RELEASE(" [x] Prefix 0"); + } + + PrintBytes(cmd.Request(1)); + if (cmd.Request(1) == bytesP1) + { + LOG_RELEASE(" [ ] Prefix 1"); + } + else + { + LOG_RELEASE(" [x] Prefix 1"); + } +} + +void CompareAncStates(bool isProcessed, SonyAncState stateActual, SonyAncState stateExpected){ + if (isProcessed) + { + LOG_RELEASE(" [ ] isProcessed"); + if (stateActual.AmbientVoice == stateExpected.AmbientVoice) + { + LOG_RELEASE(" [ ] AmbientVoice"); + } + else + { + LOG_RELEASE(" [x] AmbientVoice"); + } + + if (stateActual.AncFilter == stateExpected.AncFilter) + { + LOG_RELEASE(" [ ] AncFilter"); + } + else + { + LOG_RELEASE(" [x] AncFilter"); + } + + if (stateActual.AncSwitch == stateExpected.AncSwitch) + { + LOG_RELEASE(" [ ] AncSwitch"); + } + else + { + LOG_RELEASE(" [x] AncSwitch"); + } + + if (stateActual.Volume == stateExpected.Volume) + { + LOG_RELEASE(" [ ] Volume"); + } + else + { + LOG_RELEASE(" [x] Volume"); + } + } + else + { + LOG_RELEASE(" [x] isProcessed"); + } +} + +void TestSonyGetAncResponse(std::vector bytes, SonyAncState state) +{ + SonyGetAnc cmd = SonyGetAnc(); + cmd.ProcessResponse(bytes); + CompareAncStates(cmd.IsProcessed, cmd.state, state); + +} + +void TestSonyAncWatcher(std::vector bytes, SonyAncState state) +{ + SonyAncWatcher cmd = SonyAncWatcher(); + cmd.ProcessResponse(bytes); + CompareAncStates(true, cmd.State, state); + +} + + +std::string DummyConvertDeviceBatteryType(DeviceBatteryType status) +{ + switch (status) + { + case DeviceBatteryType::Case: + return "Case"; + case DeviceBatteryType::Left: + return "Left"; + case DeviceBatteryType::Right: + return "Right"; + case DeviceBatteryType::Single: + return "Single"; + default: + return "Unknown"; + } +} + +void TestSonyGetCaseBatteryResponse(std::vector bytes, std::map Battery) +{ + SonyGetCaseBattery cmd = SonyGetCaseBattery(); + cmd.ProcessResponse(bytes); + + if (cmd.IsProcessed) + { + LOG_RELEASE(" [ ] isProcessed"); + for (auto const &b : Battery) + { + if (cmd.Battery.contains(b.first) && cmd.Battery[b.first].Battery == b.second.Battery) + { + LOG_RELEASE(" [ ] Battery %s: %d", DummyConvertDeviceBatteryType(b.first).c_str(), cmd.Battery[b.first].Battery); + } + else + { + LOG_RELEASE(" [x] Battery %s", DummyConvertDeviceBatteryType(b.first).c_str()); + } + } + } + else + { + LOG_RELEASE(" [x] isProcessed"); + } +} + +void TestSonyGetHeadphonesBatteryResponse(SonyProductIds model, std::vector bytes, std::map Battery) +{ + SonyGetHeadphonesBattery cmd = SonyGetHeadphonesBattery(model); + cmd.ProcessResponse(bytes); + + if (cmd.IsProcessed) + { + LOG_RELEASE(" [ ] isProcessed"); + for (auto const &b : Battery) + { + if (cmd.Battery.contains(b.first) && cmd.Battery[b.first].Battery == b.second.Battery) + { + LOG_RELEASE(" [ ] Battery %s: %d", DummyConvertDeviceBatteryType(b.first).c_str(), cmd.Battery[b.first].Battery); + } + else + { + LOG_RELEASE(" [x] Battery %s", DummyConvertDeviceBatteryType(b.first).c_str()); + } + } + } + else + { + LOG_RELEASE(" [x] isProcessed"); + } +} + +int main() +{ + setvbuf(stdout, NULL, _IONBF, 0); + + LOG_RELEASE("Test SonyBaseCmd request:"); + SonyBaseCmd sonyBaseCmd = SonyBaseCmd("SonyBaseCmd"); + TestRequest( + sonyBaseCmd, + std::vector{0x3e, 0x00, 0x3c}, + std::vector{0x3e, 0x00, 0x3c}); + + LOG_RELEASE("Test SonyGetAnc request:"); + SonyGetAnc sonyGetAnc = SonyGetAnc(); + TestRequest( + sonyGetAnc, + std::vector{0x3e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x66, 0x02, 0x76, 0x3c}, + std::vector{0x3e, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x02, 0x66, 0x02, 0x77, 0x3c}); + + SonyAncState state; + LOG_RELEASE("Test SonyGetAnc response Anc:"); + state.AncSwitch = SonyAncSwitch::On; + state.AncFilter = SonyAncFilter::Anc; + state.AmbientVoice = SonyAncFilterAmbientVoice::Off; + state.Volume = 0; + TestSonyGetAncResponse( + std::vector{0x3e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x67, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x00, 0x83, 0x3c}, + state); + + LOG_RELEASE("Test SonyGetAnc response Ambient:"); + state.AncSwitch = SonyAncSwitch::On; + state.AncFilter = SonyAncFilter::Ambient; + state.AmbientVoice = SonyAncFilterAmbientVoice::Off; + state.Volume = 1; + TestSonyGetAncResponse( + std::vector{0x3e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x67, 0x02, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0x82, 0x3c}, + state); + + LOG_RELEASE("Test SonyGetAnc response Off:"); + state.AncSwitch = SonyAncSwitch::Off; + state.AncFilter = SonyAncFilter::Ambient; + state.AmbientVoice = SonyAncFilterAmbientVoice::Off; + state.Volume = 1; + TestSonyGetAncResponse( + std::vector{0x3e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x67, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x81, 0x3c}, + state); + + LOG_RELEASE("Test SonyGetAnc response Wind:"); + state.AncSwitch = SonyAncSwitch::On; + state.AncFilter = SonyAncFilter::Wind; + state.AmbientVoice = SonyAncFilterAmbientVoice::Off; + state.Volume = 0; + TestSonyGetAncResponse( + std::vector{0x3e, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x08, 0x67, 0x02, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0x83, 0x3c}, + state); + + LOG_RELEASE("Test SonyGetCaseBattery request:"); + SonyGetCaseBattery sonyGetCaseBattery = SonyGetCaseBattery(); + TestRequest( + sonyGetCaseBattery, + std::vector{0x3e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x02, 0x20, 0x3c}, + std::vector{0x3e, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x02, 0x10, 0x02, 0x21, 0x3c}); + + LOG_RELEASE("Test SonyGetCaseBattery response:"); + + std::map BatteryCase70; + DeviceBatteryData battery; + battery.isCharging = false; + battery.Status = DeviceBatteryStatus::Cached; + battery.Battery = 70; + BatteryCase70[DeviceBatteryType::Case] = battery; + + TestSonyGetCaseBatteryResponse( + std::vector{0x3e, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x04, 0x11, 0x02, 0x46, 0x00, 0x6a, 0x3c}, + BatteryCase70); + + LOG_RELEASE("Test SonyGetHeadphonesBattery request:"); + SonyGetHeadphonesBattery sonyGetHeadphonesBattery = SonyGetHeadphonesBattery(SonyProductIds::WF_1000XM3); + TestRequest( + sonyGetHeadphonesBattery, + std::vector{0x3e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x01, 0x1f, 0x3c}, + std::vector{0x3e, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x02, 0x10, 0x01, 0x20, 0x3c}); + + LOG_RELEASE("Test SonyGetHeadphonesBatteryL20R50response:"); + + std::map BatteryL20R50; + DeviceBatteryData batteryL; + batteryL.isCharging = false; + batteryL.Status = DeviceBatteryStatus::Connected; + batteryL.Battery = 20; + BatteryL20R50[DeviceBatteryType::Left] = batteryL; + + DeviceBatteryData batteryR; + batteryR.isCharging = false; + batteryR.Status = DeviceBatteryStatus::Connected; + batteryR.Battery = 50; + BatteryL20R50[DeviceBatteryType::Right] = batteryR; + + TestSonyGetHeadphonesBatteryResponse( + SonyProductIds::WF_1000XM3, + std::vector{0x3e, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x06, 0x11, 0x01, 0x14, 0x00, 0x32, 0x00, 0x6b, 0x3c}, + BatteryL20R50); + + LOG_RELEASE("Test SonyGetHeadphonesBatteryL80R0 response:"); + + std::map BatteryL80R0; + DeviceBatteryData batteryS; + batteryS.isCharging = false; + batteryS.Status = DeviceBatteryStatus::Connected; + batteryS.Battery = 80; + BatteryL80R0[DeviceBatteryType::Single] = batteryS; + + TestSonyGetHeadphonesBatteryResponse( + SonyProductIds::WH_1000XM4, + std::vector{0x3e, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x06, 0x11, 0x01, 0x50, 0x00, 0x00, 0x00, 0x75, 0x3c}, + BatteryL80R0); + + + LOG_RELEASE("Test SonySetAnc Anc request:"); + state.AncSwitch = SonyAncSwitch::On; + state.AncFilter = SonyAncFilter::Anc; + state.AmbientVoice = SonyAncFilterAmbientVoice::Off; + state.Volume = 0; + + SonySetAnc sonySetAncAnc = SonySetAnc(state); + TestRequest( + sonySetAncAnc, + std::vector{0x3e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x68, 0x02, 0x10, 0x02, 0x02, 0x01, 0x00, 0x00, 0x93, 0x3c}, + std::vector{0x3e, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x08, 0x68, 0x02, 0x10, 0x02, 0x02, 0x01, 0x00, 0x00, 0x94, 0x3c}); + + + LOG_RELEASE("Test SonySetAnc Wind request:"); + state.AncSwitch = SonyAncSwitch::On; + state.AncFilter = SonyAncFilter::Wind; + state.AmbientVoice = SonyAncFilterAmbientVoice::Off; + state.Volume = 0; + + SonySetAnc sonySetAncWind = SonySetAnc(state); + TestRequest( + sonySetAncWind, + std::vector{0x3e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x68, 0x02, 0x10, 0x02, 0x01, 0x01, 0x00, 0x00, 0x92, 0x3c}, + std::vector{0x3e, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x08, 0x68, 0x02, 0x10, 0x02, 0x01, 0x01, 0x00, 0x00, 0x93, 0x3c}); + + + LOG_RELEASE("Test SonySetAnc AmbientVoiceFalseVolume1 Override request:"); + state.AncSwitch = SonyAncSwitch::OnAndSave; + state.AncFilter = SonyAncFilter::Ambient; + state.AmbientVoice = SonyAncFilterAmbientVoice::Off; + state.Volume = 1; + + SonySetAnc sonySetAncAmbientFalse = SonySetAnc(state); + TestRequest( + sonySetAncAmbientFalse, + std::vector{0x3e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x68, 0x02, 0x11, 0x02, 0x00, 0x01, 0x00, 0x01, 0x93, 0x3c}, + std::vector{0x3e, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x08, 0x68, 0x02, 0x11, 0x02, 0x00, 0x01, 0x00, 0x01, 0x94, 0x3c}); + + + LOG_RELEASE("Test SonySetAnc Disable request:"); + state.AncSwitch = SonyAncSwitch::Off; + state.AncFilter = SonyAncFilter::Ambient; + state.AmbientVoice = SonyAncFilterAmbientVoice::Off; + state.Volume = 0; + + SonySetAnc sonySetAncDisable = SonySetAnc(state); + TestRequest( + sonySetAncDisable, + std::vector{0x3e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x68, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x81, 0x3c}, + std::vector{0x3e, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x08, 0x68, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x82, 0x3c}); + + + LOG_RELEASE("Test SonyAncWatcher response Anc:"); + state.AncSwitch = SonyAncSwitch::On; + state.AncFilter = SonyAncFilter::Anc; + state.AmbientVoice = SonyAncFilterAmbientVoice::Off; + state.Volume = 0; + TestSonyAncWatcher( + std::vector{0x3e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x69, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x00, 0x85, 0x3c}, + state); + + LOG_RELEASE("Test SonyAncWatcher response Ambient:"); + state.AncSwitch = SonyAncSwitch::On; + state.AncFilter = SonyAncFilter::Ambient; + state.AmbientVoice = SonyAncFilterAmbientVoice::Off; + state.Volume = 1; + TestSonyAncWatcher( + std::vector{0x3e, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x08, 0x69, 0x02, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0x85, 0x3c}, + state); + + LOG_RELEASE("Test SonyAncWatcher response Off:"); + state.AncSwitch = SonyAncSwitch::Off; + state.AncFilter = SonyAncFilter::Ambient; + state.AmbientVoice = SonyAncFilterAmbientVoice::Off; + state.Volume = 1; + TestSonyAncWatcher( + std::vector{0x3e, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x08, 0x69, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x84, 0x3c}, + state); + + return 0; +} \ No newline at end of file From f4c90a887fc68420ee054f029334fa5ac0cca426 Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Sat, 23 Mar 2024 18:10:54 +0300 Subject: [PATCH 15/16] Added draft SonyClient --- CMakeLists.txt | 1 + src/mainSonyTests.cpp | 2 +- src/sony/SonyClient.cpp | 64 +++++++++++++++++++++++++++++++++++++++++ src/sony/SonyClient.h | 24 ++++++++++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/sony/SonyClient.cpp create mode 100644 src/sony/SonyClient.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 18889f9..578e8f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ add_executable(MagicPodsCore src/sony/SonyBaseWatcher.cpp src/sony/SonyAncWatcher.cpp src/sony/SonyAncHelper.cpp + src/sony/SonyClient.cpp src/sony/SonyEnums.h src/sony/SonyStructs.h ) diff --git a/src/mainSonyTests.cpp b/src/mainSonyTests.cpp index 3a5de45..c8a4105 100644 --- a/src/mainSonyTests.cpp +++ b/src/mainSonyTests.cpp @@ -178,7 +178,7 @@ void TestSonyGetHeadphonesBatteryResponse(SonyProductIds model, std::vector +#include // UNIX ONLY + + +namespace MagicPodsCore +{ + SonyClient::SonyClient(std::string tag) : _tag{tag} + { + } + + void SonyClient::WaitResult(SonyBaseCmd &cmd, int timeOutSeconds) + { + //TODO: Check connection. If connection is disconnected we unable to send cmd + + //TODO: Subscribe to bytes from headphones cmd.ProcessResponse += + + unsigned char prefix = Prefix; + + for (size_t i = 0; i <= 1; i++) + { + if (i == 1){ + prefix = prefix == 0? (unsigned char)1 : (unsigned char)0; + } + + auto requestBytes = cmd.Request(prefix); + //TODO: Send requestBytes to headphones + + auto timeout = std::chrono::system_clock::now() + std::chrono::seconds(timeOutSeconds); + while (std::chrono::system_clock::now() < timeout) + { + usleep(10000); //10 ms UNIX only + + if (cmd.IsProcessed) + break; + } + + if (cmd.IsProcessed) + break; + } + } + + void SonyClient::ProcessResponse(const std::vector &bytes) + { + if (bytes.size() >= 2 && bytes.size() != 9 && bytes[1] != 1) + { + + // Next command should use inverse prefix. + // If headphones send command with prefix 0, + // command from our application must set prefix 1 and vice versa + auto response = bytes[2] == 0 ? std::vector{0x3e, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3c} : std::vector{0x3e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3c}; + Prefix = bytes[2] == 0 ? (unsigned char)1 : (unsigned char)0; + LOG_DEBUG("%s New prefix %d", _tag.c_str(), Prefix); + + // Notifies the headphones that the command has been successfully received + // Send verification response like 3e010000000000013c or 3e010100000000023c + // TODO: Send response to Sony headphones + } + + // TODO: Event bytes received from Sony headphones + } +} \ No newline at end of file diff --git a/src/sony/SonyClient.h b/src/sony/SonyClient.h new file mode 100644 index 0000000..d5f4f06 --- /dev/null +++ b/src/sony/SonyClient.h @@ -0,0 +1,24 @@ +#pragma once +#include +#include +#include +#include +#include +#include "SonyBaseCmd.h" + +namespace MagicPodsCore +{ + //CLASS NOT TESTED + class SonyClient + { + protected: + std::string _tag{}; + + public: + unsigned char Prefix; + explicit SonyClient(std::string tag); + void WaitResult(SonyBaseCmd &cmd, int timeOutSeconds = 2); + private: + void ProcessResponse(const std::vector &bytes); + }; +} \ No newline at end of file From de92169fec8c957adc601dd04e85b952e11ec4b6 Mon Sep 17 00:00:00 2001 From: Alexander Maslov Date: Sun, 24 Mar 2024 16:59:38 +0300 Subject: [PATCH 16/16] Added comment to SonyClient.cpp --- src/sony/SonyClient.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sony/SonyClient.cpp b/src/sony/SonyClient.cpp index b9d4f57..f0c9c98 100644 --- a/src/sony/SonyClient.cpp +++ b/src/sony/SonyClient.cpp @@ -39,7 +39,8 @@ namespace MagicPodsCore if (cmd.IsProcessed) break; - } + } + //TODO: Unsubscribe to bytes from headphones cmd.ProcessResponse -= } void SonyClient::ProcessResponse(const std::vector &bytes)