Skip to content

Commit

Permalink
blinds - add optimization for longer upward movement
Browse files Browse the repository at this point in the history
  • Loading branch information
ph4r05 committed Sep 8, 2024
1 parent 79369fa commit 766101f
Showing 1 changed file with 77 additions and 7 deletions.
84 changes: 77 additions & 7 deletions shelly/shelly-curt-auto.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,44 @@ const State = {
STOPPING_TILT: "STOPPING_TILT",
MOVING_TO_POSITION: "MOVING_TO_POSITION",
TILTING: "TILTING",
TILTING2: "TILTING2"
TILTING2: "TILTING2",
TILTING_UPWARDS: "TILTING_UPWARDS",
};

const MIN_MOVEMENT_TO_KNOWN_STATE = 2; // move x% to get to a known angle
const TIME_CLOSING_TO_KNOWN_STATE = 1.5; // move x s downwards to get to a known state
const TIME_OPENING_TO_KNOWN_STATE = 1.5; // move x s upwards to get to a known state
const TIME_TO_STRAIGHT_FROM_OPEN_STATE = 0.5; // time to move down from open state to get blinds to straight angle
const TIME_TO_STRAIGHT_FROM_CLOSE_STATE = 0.9; // time to move up from closed state to get blinds to straight angle
const ALLOW_DOWN_OPTIMIZATION = true;

let currentState = State.IDLE;
let currentOperation = null;
let currentCoverStatus = null;

function max(a, b) {
return a > b ? a : b;
}

function min(a, b) {
return a < b ? a : b;
}

function recomputeTiltForSwitchedDirection(duration) {
// TIME_TO_STRAIGHT_FROM_CLOSE_STATE -> TIME_TO_STRAIGHT_FROM_OPEN_STATE
const x1 = TIME_TO_STRAIGHT_FROM_CLOSE_STATE, y1 = TIME_TO_STRAIGHT_FROM_OPEN_STATE;

// Calculate slope (m) and intercept (b) for the line equation y = mx + b
const slope = (0 - y1) / (TIME_OPENING_TO_KNOWN_STATE - x1);
const intercept = y1 - slope * x1;

// Use the linear equation to map the value
const res = slope * duration + intercept;

// Make sure movement is in the [0, TIME_OPENING_TO_KNOWN_STATE] interval
return max(0, min(TIME_OPENING_TO_KNOWN_STATE, res))
}

function transitionState(newState, operation) {
currentState = newState;
currentOperation = operation;
Expand All @@ -21,7 +52,18 @@ function transitionState(newState, operation) {
function performTiltClosing(){
Shelly.call("Cover.Close", {
id: 0,
duration: 1.2,
duration: TIME_CLOSING_TO_KNOWN_STATE,
}, function (r, error_code, error_message, userdata1) {
if (r !== null){
transitionState(State.IDLE, {error: error_code})
}
});
}

function performTiltOpening(){
Shelly.call("Cover.Open", {
id: 0,
duration: TIME_OPENING_TO_KNOWN_STATE,
}, function (r, error_code, error_message, userdata1) {
if (r !== null){
transitionState(State.IDLE, {error: error_code})
Expand All @@ -40,6 +82,17 @@ function performTilt(duration) {
});
}

function performTiltDownwards(duration) {
Shelly.call("Cover.Close", {
id: 0,
duration: duration,
}, function (r, error_code, error_message, userdata1) {
if (r !== null){
transitionState(State.IDLE, {error: error_code})
}
});
}

function loadStatus(callback) {
Shelly.call("Cover.GetStatus", { id: 0 }, function (r, error_code, error_message, userdata1) {
print("posAndTilt status: ", JSON.stringify(r));
Expand All @@ -65,17 +118,23 @@ function processEvent() {
}
break;

case State.MOVING_TO_POSITION:
if (currentCoverStatus && currentCoverStatus.current_pos - currentOperation.pos >= 2) {
case State.MOVING_TO_POSITION: // was moving to the position X and stopped, what next?
const movementDiff = currentCoverStatus ? currentCoverStatus.current_pos - currentOperation.pos : null;
if (movementDiff !== null && movementDiff >= MIN_MOVEMENT_TO_KNOWN_STATE) {
// if blinds moved at least 2% downwards, TILTING will be skipped as the blinds angle is already known
transitionState(State.TILTING, currentOperation);
return processEvent();
} else if (ALLOW_DOWN_OPTIMIZATION && movementDiff !== null && movementDiff <= -2*MIN_MOVEMENT_TO_KNOWN_STATE) {
// if blinds moved at least 2% upwards, TILTING will be skipped as the blinds angle is already known
transitionState(State.TILTING_UPWARDS, currentOperation);
return processEvent();
} else {
transitionState(State.TILTING, currentOperation);
performTiltClosing();
}
break;

case State.TILTING:
case State.TILTING: // was tilting and stopped, what next?
if (currentOperation.tilt_duration < 0.05) {
transitionState(State.TILTING2, currentOperation);
return processEvent();
Expand All @@ -84,7 +143,18 @@ function processEvent() {
performTilt(currentOperation.tilt_duration);
break;

case State.TILTING2:
case State.TILTING_UPWARDS: // was tilting and stopped, what next?
const newDuration = recomputeTiltForSwitchedDirection(currentOperation.tilt_duration);
print("Optimizing by tilt down, original duration ", currentOperation.tilt_duration, ", recomputed ", newDuration);
if (newDuration < 0.05) {
transitionState(State.TILTING2, currentOperation);
return processEvent();
}
transitionState(State.TILTING2, currentOperation);
performTiltDownwards(newDuration);
break;

case State.TILTING2: // final tilt finished, what next?
transitionState(State.IDLE, null);
print("Tilting done.");
break;
Expand All @@ -95,7 +165,7 @@ function processEvent() {
Shelly.addEventHandler(function (event) {
print("Global event handler: ", JSON.stringify(event));

if (event.info && (event.info.event === "stopped" || event.info.event === "closed")) {
if (event.info && (event.info.event === "stopped" || event.info.event === "closed" || event.info.event === "opened")) {
processEvent();
}
}, null);
Expand Down

0 comments on commit 766101f

Please sign in to comment.