#include "ShadeRequests.h" #include "ShadeMotion.h" bool shadeRequestUsesRadio(shade_request_type_t type) { switch(type) { case shade_request_type_t::set_positions: case shade_request_type_t::set_rolling_code: return false; default: return true; } } int8_t requestRepeat(int32_t repeat) { if(repeat < 0) return -1; return repeat > INT8_MAX ? INT8_MAX : static_cast(repeat); } int8_t requestTarget(int32_t target) { return target >= 0 && target <= 100 ? static_cast(target) : -1; } static bool inRange(int8_t pos) { return pos >= 0 && pos <= 100; } // Turning a client position round is the same sum as turning a stored one. static int8_t storedPosition(int8_t pos, bool flip) { return displayPosition(static_cast(pos), flip); } static uint8_t repeatsOr(int8_t repeat, uint8_t own) { return repeat >= 0 ? static_cast(repeat) : own; } bool ShadeRequests::run(const shade_request_t &req) { shade_info_t shade; uint8_t groupRepeats = 0; switch(req.type) { case shade_request_type_t::group_command: case shade_request_type_t::group_repeat: case shade_request_type_t::group_sensor: if(!this->ops.findGroup(req.id, groupRepeats)) return true; break; default: if(!this->ops.findShade(req.id, shade)) return true; break; } const bool flip = shade.flipPosition; switch(req.type) { case shade_request_type_t::shade_command: if(inRange(req.target)) return this->ops.moveToTarget(req.id, storedPosition(req.target, flip)); return this->ops.sendCommand(req.id, req.command, repeatsOr(req.repeat, shade.repeats), req.stepSize); case shade_request_type_t::group_command: return this->ops.sendGroupCommand(req.id, req.command, repeatsOr(req.repeat, groupRepeats), req.stepSize); case shade_request_type_t::tilt_command: if(inRange(req.target)) return this->ops.moveToTiltTarget(req.id, storedPosition(req.target, flip)); return this->ops.sendTiltCommand(req.id, req.command); case shade_request_type_t::shade_repeat: { // A single button garage door has no Prog, its button is Toggle. somfy_commands cmd = req.command; if(shade.shadeType == shade_types::garage1 && cmd == somfy_commands::Prog) cmd = somfy_commands::Toggle; const uint8_t repeat = repeatsOr(req.repeat, shade.repeats); if(this->ops.isLastCommand(req.id, cmd)) return this->ops.repeatFrame(req.id, repeat); return this->ops.sendCommand(req.id, cmd, repeat, req.stepSize); } case shade_request_type_t::group_repeat: { const uint8_t repeat = repeatsOr(req.repeat, groupRepeats); if(this->ops.isLastGroupCommand(req.id, req.command)) return this->ops.repeatGroupFrame(req.id, repeat); return this->ops.sendGroupCommand(req.id, req.command, repeat, req.stepSize); } case shade_request_type_t::set_positions: { const float pos = inRange(req.position) ? storedPosition(req.position, flip) : -1.0f; const float tilt = inRange(req.tiltPosition) && shade.tiltType != tilt_types::none ? storedPosition(req.tiltPosition, flip) : -1.0f; if(pos >= 0.0f || tilt >= 0.0f) this->ops.setPositions(req.id, pos, tilt); return true; } case shade_request_type_t::shade_sensor: return this->ops.sendSensorCommand(req.id, req.windy, req.sunny, repeatsOr(req.repeat, shade.repeats)); case shade_request_type_t::group_sensor: return this->ops.sendGroupSensorCommand(req.id, req.windy, req.sunny, repeatsOr(req.repeat, groupRepeats)); case shade_request_type_t::set_favorite: { const int8_t tilt = requestedFavoriteTilt(req.tiltPosition, shade.tiltType, shade.myTiltPos, flip); // Without a lift position only the tilt changes: the lift favorite stays, // or is set where the shade is when it has none. int8_t pos = req.position; if(!inRange(pos)) pos = displayPosition(shade.myPos >= 0.0f ? shade.myPos : shade.currentPos, flip); return this->ops.setMyPosition(req.id, storedPosition(pos, flip), storedPosition(tilt, flip)); } case shade_request_type_t::unpair: { // A 56-bit motor needs a longer Prog press than an 80-bit one. const bool sent = this->ops.sendCommand(req.id, somfy_commands::Prog, shade.bitLength == 56 ? 7 : 1, 0); if(sent) this->ops.setUnpaired(req.id); return sent; } case shade_request_type_t::set_rolling_code: this->ops.setRollingCode(req.id, req.rollingCode); return true; } return true; }