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.

161 lines
4.6 KiB

api: rework plain and JSON implementations (#2405) - match paths through a custom AsyncWebHandler instead of using generic not-found fallback handler - allow MQTT-like patterns when registering paths (`simple/path`, `path/+/something`, `path/#`) Replaces `relay/0`, `relay/1` etc. with `relay/+`. Magnitudes are plain paths, but using `/+` in case there's more than 1 magnitude of the same type. - restore `std::function` as callback container (no more single-byte arg nonsense). Still, limit to 1 type per handler type - adds JSON handlers which will receive JsonObject root as both input and output. Same logic as plain - GET returns resource data, PUT updates it. - breaking change to `apiAuthenticate(request)`, it no longer will do `request->send(403)` and expect this to be handled externally. - allow `Api-Key` header containing the key, works for both GET & PUT plain requests. The only way to set apikey for JSON. - add `ApiRequest::param` to retrieve both GET and PUT params (aka args), remove ApiBuffer - remove `API_BUFFER_SIZE`. Allow custom form-data key=value pairs for requests, allow to send basic `String`. - add `API_JSON_BUFFER_SIZE` for the JSON buffer (both input and output) - `/apis` replaced with `/api/list`, no longer uses custom handler and is an `apiRegister` callback - `/api/rpc` custom handler replaced with an `apiRegister` callback WIP further down: - no more `webLog` for API requests, unless `webAccessLog` / `WEB_ACCESS_LOG` is set to `1`. This also needs to happen to the other handlers. - migrate to ArduinoJson v6, since it become apparent it is actually a good upgrade :) - actually make use of JSON endpoints more, right now it's just existing GET for sensors and relays - fork ESPAsyncWebServer to cleanup path parsing and temporary objects attached to the request (also, fix things a lot of things based on PRs there...)
3 years ago
  1. /*
  2. ENCODER MODULE
  3. Copyright (C) 2018-2019 by Xose Pérez <xose dot perez at gmail dot com>
  4. */
  5. #include "encoder.h"
  6. #if ENCODER_SUPPORT && (LIGHT_PROVIDER != LIGHT_PROVIDER_NONE)
  7. #include "light.h"
  8. #include "libs/Encoder.h"
  9. #include <vector>
  10. struct encoder_t {
  11. Encoder * encoder;
  12. unsigned char button_pin;
  13. unsigned char button_logic;
  14. unsigned char button_mode;
  15. unsigned char mode;
  16. unsigned char channel1; // default
  17. unsigned char channel2; // only if button defined and pressed
  18. };
  19. std::vector<encoder_t> _encoders;
  20. unsigned long _encoder_min_delta = 1;
  21. void _encoderConfigure() {
  22. _encoder_min_delta = getSetting("encMinDelta", ENCODER_MINIMUM_DELTA);
  23. if (!_encoder_min_delta) _encoder_min_delta = 1;
  24. // no need to reload objects right now
  25. if (_encoders.size()) return;
  26. // Clean previous encoders and re-add them
  27. for (auto& encoder : _encoders) {
  28. delete encoder.encoder;
  29. }
  30. _encoders.clear();
  31. // TODO: encEnable
  32. // TODO: implement reloading without re-allocating objects
  33. #if (ENCODER1_PIN1 != GPIO_NONE) && (ENCODER1_PIN2 != GPIO_NONE)
  34. {
  35. _encoders.push_back({
  36. new Encoder(ENCODER1_PIN1, ENCODER1_PIN2),
  37. ENCODER1_BUTTON_PIN, ENCODER1_BUTTON_LOGIC, ENCODER1_BUTTON_MODE, ENCODER1_MODE,
  38. ENCODER1_CHANNEL1, ENCODER1_CHANNEL2
  39. });
  40. }
  41. #endif
  42. #if (ENCODER2_PIN1 != GPIO_NONE) && (ENCODER2_PIN2 != GPIO_NONE)
  43. {
  44. _encoders.push_back({
  45. new Encoder(ENCODER2_PIN1, ENCODER2_PIN2),
  46. ENCODER2_BUTTON_PIN, ENCODER2_BUTTON_LOGIC, ENCODER2_BUTTON_MODE, ENCODER2_MODE,
  47. ENCODER2_CHANNEL1, ENCODER2_CHANNEL2
  48. });
  49. }
  50. #endif
  51. #if (ENCODER3_PIN1 != GPIO_NONE) && (ENCODER3_PIN2 != GPIO_NONE)
  52. {
  53. _encoders.push_back({
  54. new Encoder(ENCODER3_PIN1, ENCODER3_PIN2),
  55. ENCODER3_BUTTON_PIN, ENCODER3_BUTTON_LOGIC, ENCODER3_BUTTON_MODE, ENCODER3_MODE,
  56. ENCODER3_CHANNEL1, ENCODER3_CHANNEL2
  57. });
  58. }
  59. #endif
  60. #if (ENCODER4_PIN1 != GPIO_NONE) && (ENCODER4_PIN2 != GPIO_NONE)
  61. {
  62. _encoders.push_back({
  63. new Encoder(ENCODER4_PIN1, ENCODER4_PIN2),
  64. ENCODER4_BUTTON_PIN, ENCODER4_BUTTON_LOGIC, ENCODER4_BUTTON_MODE, ENCODER4_MODE,
  65. ENCODER4_CHANNEL1, ENCODER4_CHANNEL2
  66. });
  67. }
  68. #endif
  69. #if (ENCODER5_PIN1 != GPIO_NONE) && (ENCODER5_PIN2 != GPIO_NONE)
  70. {
  71. _encoders.push_back({
  72. new Encoder(ENCODER5_PIN1, ENCODER5_PIN2),
  73. ENCODER5_BUTTON_PIN, ENCODER5_BUTTON_LOGIC, ENCODER5_BUTTON_MODE, ENCODER5_MODE,
  74. ENCODER5_CHANNEL1, ENCODER5_CHANNEL2
  75. });
  76. }
  77. #endif
  78. // TODO: manage buttons through debounceevent?
  79. for (auto& encoder : _encoders) {
  80. if (GPIO_NONE != encoder.button_pin) {
  81. pinMode(encoder.button_pin, encoder.button_mode);
  82. }
  83. }
  84. }
  85. void _encoderLoop() {
  86. // for each encoder, read delta (read()) and map button action
  87. for (auto& encoder : _encoders) {
  88. const auto delta = encoder.encoder->read();
  89. encoder.encoder->write(0);
  90. if ((0 == delta) || (_encoder_min_delta > abs(delta))) continue;
  91. if (encoder.button_pin == GPIO_NONE) {
  92. // if there is no button, the encoder drives CHANNEL1
  93. lightChannelStep(encoder.channel1, delta);
  94. } else {
  95. // otherwise, use button based on encoder mode
  96. bool pressed = (digitalRead(encoder.button_pin) != encoder.button_logic);
  97. if (ENCODER_MODE_CHANNEL == encoder.mode) {
  98. // the button controls what channel we are changing
  99. lightChannelStep(pressed ? encoder.channel2 : encoder.channel1, delta);
  100. } if (ENCODER_MODE_RATIO == encoder.mode) {
  101. // the button controls if we are changing the channel ratio or the overall brightness
  102. if (pressed) {
  103. lightChannelStep(encoder.channel1, delta);
  104. lightChannelStep(encoder.channel2, -delta);
  105. } else {
  106. lightBrightnessStep(delta);
  107. }
  108. }
  109. }
  110. lightUpdate(true, true);
  111. }
  112. }
  113. // -----------------------------------------------------------------------------
  114. void encoderSetup() {
  115. // Configure encoders
  116. _encoderConfigure();
  117. // Main callbacks
  118. espurnaRegisterLoop(_encoderLoop);
  119. espurnaRegisterReload(_encoderConfigure);
  120. DEBUG_MSG_P(PSTR("[ENCODER] Number of encoders: %u\n"), _encoders.size());
  121. }
  122. #endif // ENCODER_SUPPORT && (LIGHT_PROVIDER != LIGHT_PROVIDER_NONE)