Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
3.1 KiB

  1. /*
  2. TUYA MODULE
  3. Copyright (C) 2019 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
  4. */
  5. #pragma once
  6. #include <cstdint>
  7. #include "tuya_dataframe.h"
  8. #include "tuya_types.h"
  9. #include "tuya_transport.h"
  10. namespace Tuya {
  11. // 2 known Data Protocols:
  12. //
  13. // id type len value
  14. // 0x?? 0x01 0x00 0x01 0x00 - bool (0 for false, 1 for true)
  15. // 0x?? 0x02 0x00 0x04 0x00 0x00 0x00 0x00 - int
  16. //
  17. // Note: 'id' varies between devices. instead, matching DP in sequence with local controllers
  18. // Note: 'int' type is mostly used for dimmer and while it is 4 byte value,
  19. // only the first byte is used (i.e. value is between 0 and 255)
  20. Type dataType(const DataFrame& frame) {
  21. if (!frame.length) return Type::UNKNOWN;
  22. const Type type = static_cast<Type>(frame[1]);
  23. switch (type) {
  24. case Type::BOOL:
  25. if (frame.length != 5) break;
  26. if (frame[3] != 0x01) break;
  27. return type;
  28. case Type::INT:
  29. if (frame.length != 8) break;
  30. if (frame[3] != 0x04) break;
  31. return type;
  32. default:
  33. return Type::UNKNOWN;
  34. }
  35. return Type::UNKNOWN;
  36. }
  37. // Since we know of the type only at runtime, specialize the protocol container
  38. template <typename T>
  39. class DataProtocol {
  40. public:
  41. DataProtocol(const uint8_t id, const T value) :
  42. _id(id), _value(value)
  43. {}
  44. DataProtocol(const DataFrame& frame);
  45. uint8_t id() const { return _id; }
  46. T value() const { return _value; }
  47. std::vector<uint8_t> serialize();
  48. private:
  49. uint8_t _id;
  50. T _value;
  51. };
  52. template <typename T>
  53. DataProtocol<T>::DataProtocol(const DataFrame& frame) {
  54. static_assert(sizeof(T) != sizeof(T), "No constructor yet for this type!");
  55. }
  56. template <>
  57. DataProtocol<bool>::DataProtocol(const DataFrame& frame) {
  58. auto data = frame.cbegin();
  59. _id = data[0],
  60. _value = data[4];
  61. }
  62. template <>
  63. DataProtocol<uint32_t>::DataProtocol(const DataFrame& frame) {
  64. auto data = frame.cbegin();
  65. _id = data[0];
  66. _value = static_cast<uint32_t>(data[4] << 24)
  67. | static_cast<uint32_t>(data[5] << 16)
  68. | static_cast<uint32_t>(data[6] << 8)
  69. | static_cast<uint32_t>(data[7]);
  70. }
  71. template <>
  72. std::vector<uint8_t> DataProtocol<bool>::serialize() {
  73. return std::vector<uint8_t> {
  74. _id, static_cast<uint8_t>(Type::BOOL), 0x00, 0x01,
  75. static_cast<uint8_t>(_value)
  76. };
  77. }
  78. template <>
  79. std::vector<uint8_t> DataProtocol<uint32_t>::serialize() {
  80. return std::vector<uint8_t> {
  81. _id, static_cast<uint8_t>(Type::INT), 0x00, 0x04,
  82. static_cast<uint8_t>((_value >> 24) & 0xff),
  83. static_cast<uint8_t>((_value >> 16) & 0xff),
  84. static_cast<uint8_t>((_value >> 8) & 0xff),
  85. static_cast<uint8_t>(_value & 0xff)
  86. };
  87. }
  88. }