changeset 485:0062162318d2

WIP on power transition, keeps getting better, I think I'm gonna change apply_cnt to count the number of periods left instead of going up
author Louis Opter <kalessin@kalessin.fr>
date Sat, 09 Jul 2016 19:17:07 -0700
parents 8f5a1a4862dc
children 5afd4568a2f6
files add_power_transition.patch ask_for_remote_dest_before_running_hg_out.patch series
diffstat 3 files changed, 87 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/add_power_transition.patch	Sat Jul 09 13:23:18 2016 -0700
+++ b/add_power_transition.patch	Sat Jul 09 19:17:07 2016 -0700
@@ -1,5 +1,5 @@
 # HG changeset patch
-# Parent  401bd90c164a23e6b23aa4842135d4ad142894b2
+# Parent  b711b804c1c54e31174c68fc13e3227967f16786
 Add a transition argument to the power functions
 
 Unlike LIFX's implementation, lightsd will properly get the bulbs to
@@ -59,7 +59,7 @@
 new file mode 100644
 --- /dev/null
 +++ b/core/effect.c
-@@ -0,0 +1,242 @@
+@@ -0,0 +1,243 @@
 +// Copyright (c) 2015, Louis Opter <kalessin@kalessin.fr>
 +//
 +// This file is part of lighstd.
@@ -121,7 +121,8 @@
 +    struct lgtd_effect *effect = (struct lgtd_effect *)ctx.as_ptr;
 +    if (effect->duration_cb) {
 +        lgtd_time_mono_t now = lgtd_time_monotonic_msecs();
-+        if (effect->ends_at - now < LGTD_EFFECT_STALE_THRESHOLD_MS) {
++        if (effect->ends_at < now || // let's not go negative with unsigned ints
++            effect->ends_at - now < LGTD_EFFECT_STALE_THRESHOLD_MS) {
 +            lgtd_info(
 +                "calling duration callback for effect %s, id=%p",
 +                effect->name, effect
@@ -131,8 +132,8 @@
 +            lgtd_warnx(
 +                "not calling duration callback for stale effect %s created "
 +                "%jums ago, id=%p, duration=%jums",
-+                effect->name, now - effect->created_at, effect,
-+                effect->ends_at - effect->created_at
++                effect->name, (uintmax_t)(now - effect->created_at), effect,
++                (uintmax_t)(effect->ends_at - effect->created_at)
 +            );
 +        }
 +    }
@@ -150,21 +151,21 @@
 +    if (effect->ends_at && now > effect->ends_at) {
 +        // check if the effect is stale (e.g: the computer went to sleep)
 +        // and stop it if it is the case:
-+        if (effect->ends_at - now > LGTD_EFFECT_STALE_THRESHOLD_MS) {
++        if (now - effect->ends_at > LGTD_EFFECT_STALE_THRESHOLD_MS) {
 +            lgtd_warnx(
 +                "stopping stale periodic effect %s created %jums ago, "
 +                "id=%p, duration=%jums",
-+                effect->name, now - effect->created_at, effect,
-+                effect->ends_at - effect->created_at
++                effect->name, (uintmax_t)(now - effect->created_at), effect,
++                (uintmax_t)(effect->ends_at - effect->created_at)
 +            );
 +            lgtd_effect_stop(effect);
 +            return;
 +        }
-+        // if there is a duration callback pending then stop the periodic
-+        // timer but apply the effect one last time (we're not stale yet).
++        // if a duration callback pending then just stop the periodic timer:
 +        if (event_pending(effect->duration_timer->event, EV_TIMEOUT, NULL)) {
 +            lgtd_timer_stop(effect->timer);
 +            effect->timer = NULL;
++            return;
 +        }
 +    }
 +
@@ -246,13 +247,13 @@
 +            lgtd_info(
 +                "starting effect %s, id=%p, created_at=%jums, "
 +                "tick=%dms, duration=%dms",
-+                name, effect, effect->created_at, timer_ms, duration
++                name, effect, (uintmax_t)effect->created_at, timer_ms, duration
 +            );
 +        } else {
 +            lgtd_info(
 +                "starting effect %s, id=%p, created_a=%jums, "
 +                "tick=%dms, duration=infinite",
-+                name, effect, effect->created_at, timer_ms
++                name, effect, (uintmax_t)effect->created_at, timer_ms
 +            );
 +        }
 +    } else { // finite or instant effect
@@ -260,13 +261,13 @@
 +            lgtd_info(
 +                "starting effect %s, id=%p, created_at=%jums, "
 +                "duration=%dms",
-+                name, effect, effect->created_at, duration
++                name, effect, (uintmax_t)effect->created_at, duration
 +            );
 +        } else {
 +            lgtd_info(
 +                "starting effect %s, id=%p, created_at=%jums, "
 +                "duration=instant",
-+                name, effect, effect->created_at
++                name, effect, (uintmax_t)effect->created_at
 +            );
 +        }
 +        if (effect->apply_cb) {
@@ -306,7 +307,7 @@
 new file mode 100644
 --- /dev/null
 +++ b/core/effect.h
-@@ -0,0 +1,59 @@
+@@ -0,0 +1,61 @@
 +// Copyright (c) 2015, Louis Opter <kalessin@kalessin.fr>
 +//
 +// This file is part of lighstd.
@@ -340,6 +341,8 @@
 +    void                            (*duration_cb)(const struct lgtd_effect *);
 +    struct lgtd_timer               *timer;
 +    void                            (*apply_cb)(const struct lgtd_effect *);
++    // number of times apply_cb has been called (therefore this will be 0 the
++    // first time apply_cb is called):
 +    uint32_t                        apply_cnt;
 +    union lgtd_effect_ctx           ctx;
 +};
@@ -940,22 +943,13 @@
  struct lgtd_timer *
  lgtd_timer_start(int flags,
                   int ms,
-@@ -60,6 +72,8 @@
-     timer->ctx = ctx;
-     LIST_INSERT_HEAD(&lgtd_timers, timer, link);
- 
-+    enum lgtd_event_priority priority = lgtd_timer_flags_to_priority(flags);
-+    lgtd_info("timer priority = %u", priority);
-     struct timeval tv = LGTD_MSECS_TO_TIMEVAL(ms);
-     timer->event = event_new(
-         lgtd_ev_base,
-@@ -68,7 +82,9 @@
+@@ -68,7 +80,9 @@
          lgtd_timer_callback,
          timer
      );
 -    if (!timer->event || evtimer_add(timer->event, &tv)) {
 +    if (!timer->event
-+        || event_priority_set(timer->event, priority)
++        || event_priority_set(timer->event, lgtd_timer_flags_to_priority(flags))
 +        || evtimer_add(timer->event, &tv)) {
          LIST_REMOVE(timer, link);
          if (timer->event) {
@@ -1063,7 +1057,7 @@
 new file mode 100644
 --- /dev/null
 +++ b/effects/power_transition.c
-@@ -0,0 +1,333 @@
+@@ -0,0 +1,345 @@
 +// Copyright (c) 2015, Louis Opter <kalessin@kalessin.fr>
 +//
 +// This file is part of lighstd.
@@ -1121,17 +1115,16 @@
 +}
 +
 +static struct lgtd_lifx_bulb *
-+lgtd_effect_power_transition_off_possibly_get_bulb(uint8_t *device_id)
++lgtd_effect_power_transition_possibly_get_bulb(uint8_t *device_id)
 +{
 +    assert(device_id);
 +
 +    struct lgtd_lifx_bulb *bulb = lgtd_lifx_bulb_get(device_id);
 +    if (!bulb) {
 +        char addr[LGTD_LIFX_ADDR_STRLEN];
-+        LGTD_IEEE8023MACTOA(device_id, addr);
 +        lgtd_warnx(
-+            "bulb %s is unavailable: can't restore its original brightness "
-+            "at the end of a power_off transition", addr
++            "bulb %s is unavailable: can't apply a power transition on it",
++            LGTD_IEEE8023MACTOA(device_id, addr)
 +        );
 +    }
 +    return bulb;
@@ -1143,16 +1136,18 @@
 +{
 +    assert(effect);
 +
++    lgtd_info(
++        "now = %ju, effect->ends_at=%ju",
++        (uintmax_t)lgtd_time_monotonic_msecs(), (uintmax_t)effect->ends_at
++    );
++
 +    struct lgtd_effect_power_transition_ctx *ctx = effect->ctx.as_ptr;
-+    lgtd_info(
-+        "now = %ju, end_time=%ju", lgtd_time_monotonic_msecs(), ctx->end_time
-+    );
 +
 +    struct lgtd_effect_power_transition_target *target;
 +    SLIST_FOREACH(target, &ctx->targets, link) {
 +        struct lgtd_lifx_bulb *bulb;
 +        uint8_t *device_id = target->device_id;
-+        bulb = lgtd_effect_power_transition_off_possibly_get_bulb(device_id);
++        bulb = lgtd_effect_power_transition_possibly_get_bulb(device_id);
 +        if (bulb) { // restore the original brightness
 +            struct lgtd_lifx_packet_light_color pkt_light_color = {
 +                .hue = bulb->state.hue,
@@ -1186,7 +1181,7 @@
 +        // condition:
 +        struct lgtd_lifx_bulb *bulb;
 +        uint8_t *device_id = target->device_id;
-+        bulb = lgtd_effect_power_transition_off_possibly_get_bulb(device_id);
++        bulb = lgtd_effect_power_transition_possibly_get_bulb(device_id);
 +        if (bulb) {
 +            struct lgtd_lifx_packet_light_color pkt = {
 +                .hue = bulb->state.hue,
@@ -1211,7 +1206,7 @@
 +    SLIST_FOREACH(target, targets, link) {
 +        struct lgtd_lifx_bulb *bulb;
 +        uint8_t *device_id = target->device_id;
-+        bulb = lgtd_effect_power_transition_off_possibly_get_bulb(device_id);
++        bulb = lgtd_effect_power_transition_possibly_get_bulb(device_id);
 +        if (bulb) {
 +            struct lgtd_lifx_packet_power pkt = {
 +                .power = LGTD_LIFX_POWER_OFF
@@ -1227,18 +1222,20 @@
 +    assert(effect);
 +
 +    struct lgtd_effect_power_transition_ctx *ctx = effect->ctx.as_ptr;
++
 +    lgtd_time_mono_t now = lgtd_time_monotonic_msecs();
-+    lgtd_time_mono_t next_tick = (
-+         now + LGTD_EFFECT_POWER_TRANSITION_TIMER_MS
++    lgtd_info(
++        "now = %ju, next_tick = %ju, ends_at=%ju, apply_cnt=%d/%d",
++        (uintmax_t)now, (uintmax_t)now + LGTD_EFFECT_POWER_TRANSITION_TIMER_MS,
++        (uintmax_t)ctx->ends_at, effect->apply_cnt, ctx->periods
 +    );
 +
-+    lgtd_info("now = %ju, next_tick = %ju, end_time=%ju", now, next_tick, ctx->end_time);
-+    if (next_tick >= ctx->end_time) {
++    if (effect->apply_cnt >= ctx->periods) {
 +        lgtd_effect_power_transition_off_power_off(&ctx->targets);
 +        return;
 +    }
 +    lgtd_effect_power_transition_off_set_brightness_to_zero(
-+        &ctx->targets, ctx->end_time - lgtd_time_monotonic_msecs()
++        &ctx->targets, ctx->ends_at - lgtd_time_monotonic_msecs()
 +    );
 +}
 +
@@ -1247,10 +1244,12 @@
 +{
 +    assert(effect);
 +
++    lgtd_info(
++        "now = %ju, effect->ends_at=%ju",
++        (uintmax_t)lgtd_time_monotonic_msecs(), (uintmax_t)effect->ends_at
++    );
++
 +    struct lgtd_effect_power_transition_ctx *ctx = effect->ctx.as_ptr;
-+    lgtd_info(
-+        "now = %ju, end_time=%ju", lgtd_time_monotonic_msecs(), ctx->end_time
-+    );
 +    lgtd_effect_power_transition_clear_target_list(&ctx->targets);
 +    free(ctx);
 +}
@@ -1262,19 +1261,21 @@
 +
 +    struct lgtd_effect_power_transition_ctx *ctx = effect->ctx.as_ptr;
 +    uint32_t transition = LGTD_MIN(
-+        UINT32_MAX, ctx->end_time - lgtd_time_monotonic_msecs()
++        UINT32_MAX, ctx->ends_at - lgtd_time_monotonic_msecs()
 +    );
 +
 +    lgtd_time_mono_t now = lgtd_time_monotonic_msecs();
-+    lgtd_time_mono_t next_tick = (
-+         now + LGTD_EFFECT_POWER_TRANSITION_TIMER_MS
++    lgtd_info(
++        "now = %ju, next_tick = %ju, ends_at=%ju",
++        (uintmax_t)now, (uintmax_t)now + LGTD_EFFECT_POWER_TRANSITION_TIMER_MS,
++        (uintmax_t)ctx->ends_at
 +    );
-+    lgtd_info("now = %ju, next_tick = %ju, end_time=%ju", now, next_tick, ctx->end_time);
++
 +    struct lgtd_effect_power_transition_target *target;
 +    SLIST_FOREACH(target, &ctx->targets, link) {
 +        struct lgtd_lifx_bulb *bulb;
 +        uint8_t *device_id = target->device_id;
-+        bulb = lgtd_effect_power_transition_off_possibly_get_bulb(device_id);
++        bulb = lgtd_effect_power_transition_possibly_get_bulb(device_id);
 +        if (!bulb) {
 +            continue;
 +        }
@@ -1357,7 +1358,12 @@
 +    const char *name = NULL;
 +    void (*duration_cb)(const struct lgtd_effect *) = NULL;
 +    void (*apply_cb)(const struct lgtd_effect *) = NULL;
-+    lgtd_time_mono_t end_time = duration;
++    int timer_ms = LGTD_EFFECT_POWER_TRANSITION_TIMER_MS;
++    ctx->periods = duration / timer_ms;
++    // align the timer with the duration:
++    timer_ms += (duration % timer_ms) / ctx->periods;
++    // save the duration before it gets skewed for the power off transition:
++    ctx->ends_at = duration;
 +    if (state == LGTD_EFFECT_POWER_TRANSITION_OFF) {
 +        name = "power_transition[off]";
 +        apply_cb = lgtd_effect_power_transition_off_apply_callback;
@@ -1375,12 +1381,12 @@
 +        duration,
 +        duration_cb,
 +        LGTD_TIMER_ACTIVATE_NOW|LGTD_TIMER_PERSISTENT,
-+        LGTD_EFFECT_POWER_TRANSITION_TIMER_MS,
++        timer_ms,
 +        apply_cb,
 +        effect_ctx
 +    );
 +    if (effect) {
-+        ctx->end_time = effect->created_at + end_time;
++        ctx->ends_at += effect->created_at;
 +        return effect;
 +    }
 +
@@ -1401,7 +1407,7 @@
 new file mode 100644
 --- /dev/null
 +++ b/effects/power_transition.h
-@@ -0,0 +1,53 @@
+@@ -0,0 +1,55 @@
 +// Copyright (c) 2015, Louis Opter <kalessin@kalessin.fr>
 +//
 +// This file is part of lighstd.
@@ -1447,9 +1453,11 @@
 +
 +struct lgtd_effect_power_transition_ctx {
 +    struct lgtd_effect_power_transition_target_list targets;
++    // how many times the apply_cb will be called
++    uint32_t                                        periods;
 +    // This doesn't include the delay to restore the light color after a
 +    // power off:
-+    lgtd_time_mono_t                                end_time;
++    lgtd_time_mono_t                                ends_at;
 +};
 +
 +const struct lgtd_effect *lgtd_effect_power_transition(const struct lgtd_proto_target_list *,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ask_for_remote_dest_before_running_hg_out.patch	Sat Jul 09 19:17:07 2016 -0700
@@ -0,0 +1,23 @@
+# HG changeset patch
+# Parent  f3edec018825871eb7b80631f3c4411a5e349b7c
+Ask for the remote before checking for pending changes in release.py
+
+diff --git a/dist/release.py.in b/dist/release.py.in
+--- a/dist/release.py.in
++++ b/dist/release.py.in
+@@ -364,11 +364,11 @@
+         "commit", "-m", "Back to development, {}".format(next_version)
+     ])
+ 
+-    subprocess.check_call([HG_EXECUTABLE, "-R", LIGHTSD_SOURCE_DIR, "out"])
++    remote = click.prompt("Confirm the remote destination", default="default")
++    subprocess.check_call([
++        HG_EXECUTABLE, "-R", LIGHTSD_SOURCE_DIR, "out", remote
++    ])
+     if click.confirm("Are you ready to push those commit?"):
+-        remote = click.prompt(
+-            "Confirm the remote destination", default="default",
+-        )
+         subprocess.check_call([
+             HG_EXECUTABLE, "-R", LIGHTSD_SOURCE_DIR, "push", remote
+         ])
--- a/series	Sat Jul 09 13:23:18 2016 -0700
+++ b/series	Sat Jul 09 19:17:07 2016 -0700
@@ -1,3 +1,4 @@
+ask_for_remote_dest_before_running_hg_out.patch
 docker_images.patch
 add_power_transition.patch
 open_gateway_on_any_bulb_response.patch #+future