ShadeRequests.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "ShadeRequests.h" | ||
| 2 | #include "ShadeMotion.h" | ||
| 3 | |||
| 4 | 33 | bool shadeRequestUsesRadio(shade_request_type_t type) { | |
| 5 | 33 | switch(type) { | |
| 6 | 6 | case shade_request_type_t::set_positions: | |
| 7 | case shade_request_type_t::set_rolling_code: | ||
| 8 | 6 | return false; | |
| 9 | 27 | default: | |
| 10 | 27 | return true; | |
| 11 | } | ||
| 12 | } | ||
| 13 | 40 | bool shadeRequestIsForGroup(shade_request_type_t type) { | |
| 14 | 40 | switch(type) { | |
| 15 | 10 | case shade_request_type_t::group_command: | |
| 16 | case shade_request_type_t::group_repeat: | ||
| 17 | case shade_request_type_t::group_sensor: | ||
| 18 | 10 | return true; | |
| 19 | 30 | default: | |
| 20 | 30 | return false; | |
| 21 | } | ||
| 22 | } | ||
| 23 | 3 | int8_t requestRepeat(int32_t repeat) { | |
| 24 | 3 | if(repeat < 0) return -1; | |
| 25 | 2 | return repeat > INT8_MAX ? INT8_MAX : static_cast<int8_t>(repeat); | |
| 26 | } | ||
| 27 | 4 | int8_t requestTarget(int32_t target) { return target >= 0 && target <= 100 ? static_cast<int8_t>(target) : -1; } | |
| 28 | |||
| 29 | 23 | static bool inRange(int8_t pos) { return pos >= 0 && pos <= 100; } | |
| 30 | // Turning a client position round is the same sum as turning a stored one. | ||
| 31 | 17 | static int8_t storedPosition(int8_t pos, bool flip) { return displayPosition(static_cast<float>(pos), flip); } | |
| 32 | 11 | static uint8_t repeatsOr(int8_t repeat, uint8_t own) { return repeat >= 0 ? static_cast<uint8_t>(repeat) : own; } | |
| 33 | |||
| 34 | 24 | static shade_request_result_t sent(bool taken) { return taken ? shade_request_result_t::done : shade_request_result_t::radio_refused; } | |
| 35 | |||
| 36 | 33 | shade_request_result_t ShadeRequests::run(const shade_request_t &req) { | |
| 37 | 33 | shade_info_t shade; | |
| 38 | 33 | uint8_t groupRepeats = 0; | |
| 39 | 33 | if(shadeRequestIsForGroup(req.type)) { | |
| 40 | 6 | if(!this->ops.findGroup(req.id, groupRepeats)) return shade_request_result_t::not_found; | |
| 41 | } | ||
| 42 | 27 | else if(!this->ops.findShade(req.id, shade)) return shade_request_result_t::not_found; | |
| 43 | 30 | const bool flip = shade.flipPosition; | |
| 44 | 30 | switch(req.type) { | |
| 45 | 6 | case shade_request_type_t::shade_command: | |
| 46 | 6 | if(inRange(req.target)) return sent(this->ops.moveToTarget(req.id, storedPosition(req.target, flip))); | |
| 47 | 3 | return sent(this->ops.sendCommand(req.id, req.command, repeatsOr(req.repeat, shade.repeats), req.stepSize)); | |
| 48 | 2 | case shade_request_type_t::group_command: | |
| 49 | 2 | return sent(this->ops.sendGroupCommand(req.id, req.command, repeatsOr(req.repeat, groupRepeats), req.stepSize)); | |
| 50 | 2 | case shade_request_type_t::tilt_command: | |
| 51 | 2 | if(inRange(req.target)) return sent(this->ops.moveToTiltTarget(req.id, storedPosition(req.target, flip))); | |
| 52 | 1 | return sent(this->ops.sendTiltCommand(req.id, req.command)); | |
| 53 | 3 | case shade_request_type_t::shade_repeat: { | |
| 54 | // A single button garage door has no Prog, its button is Toggle. | ||
| 55 | 3 | somfy_commands cmd = req.command; | |
| 56 | 3 | if(shade.shadeType == shade_types::garage1 && cmd == somfy_commands::Prog) cmd = somfy_commands::Toggle; | |
| 57 | 3 | const uint8_t repeat = repeatsOr(req.repeat, shade.repeats); | |
| 58 | 3 | if(this->ops.isLastCommand(req.id, cmd)) return sent(this->ops.repeatFrame(req.id, repeat)); | |
| 59 | 2 | return sent(this->ops.sendCommand(req.id, cmd, repeat, req.stepSize)); | |
| 60 | } | ||
| 61 | 1 | case shade_request_type_t::group_repeat: { | |
| 62 | 1 | const uint8_t repeat = repeatsOr(req.repeat, groupRepeats); | |
| 63 | 1 | if(this->ops.isLastGroupCommand(req.id, req.command)) return sent(this->ops.repeatGroupFrame(req.id, repeat)); | |
| 64 | ✗ | return sent(this->ops.sendGroupCommand(req.id, req.command, repeat, req.stepSize)); | |
| 65 | } | ||
| 66 | 4 | case shade_request_type_t::set_positions: { | |
| 67 | 4 | const float pos = inRange(req.position) ? storedPosition(req.position, flip) : -1.0f; | |
| 68 | 4 | const float tilt = inRange(req.tiltPosition) && shade.tiltType != tilt_types::none ? storedPosition(req.tiltPosition, flip) : -1.0f; | |
| 69 | // A tilt on its own for a shade without one has nothing to set. | ||
| 70 | 4 | if(pos < 0.0f && inRange(req.tiltPosition) && shade.tiltType == tilt_types::none) return shade_request_result_t::no_tilt; | |
| 71 | 3 | if(pos >= 0.0f || tilt >= 0.0f) this->ops.setPositions(req.id, pos, tilt); | |
| 72 | 3 | return shade_request_result_t::done; | |
| 73 | } | ||
| 74 | 1 | case shade_request_type_t::shade_sensor: | |
| 75 | 1 | return sent(this->ops.sendSensorCommand(req.id, req.windy, req.sunny, repeatsOr(req.repeat, shade.repeats))); | |
| 76 | 1 | case shade_request_type_t::group_sensor: | |
| 77 | 1 | return sent(this->ops.sendGroupSensorCommand(req.id, req.windy, req.sunny, repeatsOr(req.repeat, groupRepeats))); | |
| 78 | 6 | case shade_request_type_t::set_favorite: { | |
| 79 | // The shade only takes a favorite at rest, and would ignore it. | ||
| 80 | 6 | if(!shade.idle) return shade_request_result_t::shade_moving; | |
| 81 | 5 | const int8_t tilt = requestedFavoriteTilt(req.tiltPosition, shade.tiltType, shade.myTiltPos, flip); | |
| 82 | // Without a lift position only the tilt changes: the lift favorite stays, | ||
| 83 | // or is set where the shade is when it has none. | ||
| 84 | 5 | int8_t pos = req.position; | |
| 85 | 5 | if(!inRange(pos)) pos = displayPosition(shade.myPos >= 0.0f ? shade.myPos : shade.currentPos, flip); | |
| 86 | 5 | return sent(this->ops.setMyPosition(req.id, storedPosition(pos, flip), storedPosition(tilt, flip))); | |
| 87 | } | ||
| 88 | 3 | case shade_request_type_t::unpair: { | |
| 89 | // A 56-bit motor needs a longer Prog press than an 80-bit one. | ||
| 90 | 3 | const bool taken = this->ops.sendCommand(req.id, somfy_commands::Prog, shade.bitLength == 56 ? 7 : 1, 0); | |
| 91 | 3 | if(taken) this->ops.setUnpaired(req.id); | |
| 92 | 3 | return sent(taken); | |
| 93 | } | ||
| 94 | 1 | case shade_request_type_t::set_rolling_code: | |
| 95 | 1 | this->ops.setRollingCode(req.id, req.rollingCode); | |
| 96 | 1 | return shade_request_result_t::done; | |
| 97 | } | ||
| 98 | ✗ | return shade_request_result_t::done; | |
| 99 | } | ||
| 100 |