Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Unsolved
Collapse
Discussion Forum to share and further the development of home control and automation, independent of platforms.
  1. Home
  2. Software
  3. Multi-System Reactor
  4. PR #178 In-place modification of arrays in "each"
Arming Envisalink panel from MSR
T
Topic thumbnail image
Multi-System Reactor
Upgrade Issues
T
Topic thumbnail image
Multi-System Reactor
[SOLVED] Conflicting Set Reaction Groups Appear to Fire Simultaneously in Single Rule Evaluation
G
Topic thumbnail image
Multi-System Reactor
[SOLVED] Question regarding "in" vs "contains" vs contents of the string
G
Topic thumbnail image
Multi-System Reactor
Reactor (Multi-System/Multi-Hub) Announcements
toggledbitsT
Build 21228 has been released. Docker images available from DockerHub as usual, and bare-metal packages here. Home Assistant up to version 2021.8.6 supported; the online version of the manual will now state the current supported versions; Fix an error in OWMWeatherController that could cause it to stop updating; Unify the approach to entity filtering on all hub interface classes (controllers); this works for device entities only; it may be extended to other entities later; Improve error detail in messages for EzloController during auth phase; Add isRuleSet() and isRuleEnabled() functions to expressions extensions; Implement set action for lock and passage capabilities (makes them more easily scriptable in some cases); Fix a place in the UI where 24-hour time was not being displayed.
Multi-System Reactor
Logon screen timeout
G
Noticing since 170 that the lock screen doesn't switch to the logon prompt but, rather, stays on the active UI until such time as you go to click something within it. Then it jumps to the login screen. Brave browser Brave 1.92.139 (Official Build) (arm64) Chromium: 150.0.7871.114
Multi-System Reactor
[MSR] Copy&past of actions and/or drag&drop between set/reset
therealdbT
Hey @toggledbits One thing that bothers me while doing work on new systems/new features, is that I cannot copy&paste actions, and I cannot drag&drop between set and resets. #1 is for when I want to copy an action between different rules opened in two separate browser windows, while #2 is when I just need to flip a bunch of actions in the reset, or move some logic back and forth. Both will be appreciated, but I understand the technical challenges. Thanks!
Multi-System Reactor
Upgrade advice - upgrade from aarch64 to ARM64 image
T
I'm currently on version 26011. I understand that the aarch64 image is no longer supported. So, I therefore need to update to the ARM64 image. Can anyone possibly suggest how I update my docker compose.yaml file (see below). Ideally I'd like to keep my existing reactions etc. rather than start from scratch. # Multi-System Reactor template docker-compose.yml (version 22160) # # Change the lines indicated by "DO"... # services: reactor: container_name: reactor environment: # DO change the TZ: line to set your local time zone. # See valid TZ list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones TZ: GB # # DO NOT change this path. Your directory location is in "source" below. REACTOR_DATA_PREFIX: /var/reactor # DO change the image below to the one you are using (e.g. armv7l or aarch64 for RPi 4) image: toggledbits/reactor:latest-aarch64 restart: "always" expose: - 8111 ports: - 8111:8111 volumes: # DO change the /home/username/reactor below to the directory you created for # your local data; DO NOT change the /var/reactor part - /home/pi/docker/reactor:/var/reactor - /etc/localtime:/etc/localtime:ro tmpfs: /tmp
Multi-System Reactor
Alexa for MSR, any interest?
MikeReadingtonM
Topic thumbnail image
Multi-System Reactor
[RESOLVED] Telegram notification broke with latest update
3
Topic thumbnail image
Multi-System Reactor
[RESOLVED] Phantom device, “INFO” appears
wmarcolinW
Topic thumbnail image
Multi-System Reactor
[RESOLVED] Mode Status NULL
wmarcolinW
Topic thumbnail image
Multi-System Reactor
[RESOLVED] HTTP query failing after version 26177
wmarcolinW
Topic thumbnail image
Multi-System Reactor
Question about the find function
wmarcolinW
Topic thumbnail image
Multi-System Reactor
[Answered] OK to remove old json files?
3
Topic thumbnail image
Multi-System Reactor
Deprecation Announcement: 32-bit ARM *docker* images
toggledbitsT
If you are using the armv7l docker image, the OpenJS Foundation that publishes node is no longer producing 32-bit builds as of v24. That means the last supported LTS version of node for armv7l is v22, which will go End-of-Life in May 2027. Therefore, the Reactor armv7l image is now deprecated and will only be produced until node v22 goes EOL, and I will not publish armv7l images beyond that date. If you are running an RPi 3 or earlier with Reactor, you are on this image, and will need to upgrade hardware to a 64-bit model and use the arm64 image. If you need help getting it done, ask in this category.
Multi-System Reactor
[Solved] build 26150 - engine not starting
G
@toggledbits I pulled the image (well, Watchtower did) and within minutes the whole system went offline. The log looks like it ends with 26143. [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-mkahsmgf/26qq82mw-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-lqyfljfi/22f8on0t-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-lsb61rw8/24oenqi2-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-lrh58he0/rule-lrh58he0:S-1c00gfib-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-lrh58he0/1c00dylr-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-lrh58he0/1nam9w5u-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-miuh2qqi/22ls4lql-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-kwc6rmci/rule-kwc6rmci:S-1vj8sdfc-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-kwc6rmci/rule-kwc6rmci:S-1qanz01x-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-ladyja6a/24lq19p6-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-mk0o8iox/23oy468y-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-miscg2h3/rule-miscg2h3:S-22gmbq1c-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#re-kxgrfjke/238p0old-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#re-m7ccsso5/re-m7ccsso5-1r0myjxa-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-ladyja6a/19nl9wq2-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-ladyja6a/rule-ladyja6a:S-yl3xk9t-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-ladyja6a/rule-ladyja6a:S-yl3vv5m-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#re-ln7j2nqp/re-ln7j2nqp-22mx9lzd-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#re-ln7j2nqp/22mx87c8-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-licneppy/1mzwe7ht-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-ml3194ih/25jqt1j4-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#re-kxgrg7kf/227hshak-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-reactorexmachina/13ua1p95-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-reactorexmachina/13uagam7-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-grpvl9oypg/rule-grpvl9oypg:R-134x4cbv-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-grpvl9oypg/rule-grpvl9oypg:R-134x2fyl-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#re-lscjrws1/238p5c22-cons [latest-26143]2026-05-31T15:23:44.547Z <default:INFO> Closing container Container#Predicate#rule-lbwr0jvq/1xkczf03-cons [latest-26143]2026-05-31T15:23:44.547Z <Structure:NOTICE> Structure Structure#1 stopped [latest-26143]2026-05-31T15:23:44.547Z <app:NOTICE> Closing APIs... [latest-26143]2026-05-31T15:23:44.547Z <wsapi:NOTICE> wsapi: closing... [latest-26143]2026-05-31T15:23:44.547Z <wsapi:NOTICE> wsapi: disconnecting from "192.168.1.23#82" (1001 service closing) [latest-26143]2026-05-31T15:23:44.548Z <httpapi:NOTICE> HTTP API closing... [latest-26143]2026-05-31T15:23:44.549Z <wsapi:NOTICE> wsapi: server closed [latest-26143]2026-05-31T15:23:44.549Z <httpapi:INFO> HTTP server closed. [latest-26143]2026-05-31T15:23:44.549Z <app:NOTICE> Stopping timers... [latest-26143]2026-05-31T15:23:44.551Z <app:null> Shutdown complete, process ID 1 [latest-26143]2026-05-31T15:23:44.551Z <app:null> Closing logs... [latest-26143]2026-05-31T15:23:44.551Z <default:null> Closing log I can SSH to the VM. Alas, I do not have the previous image for 26143 as I'm a little too quick sometimes on housekeeping.
Multi-System Reactor
http request action & digest auth
tunnusT
I’m using the HTTP Request action in MSR and need to authenticate against an endpoint that uses HTTP Digest authentication. Now that endpoint was changed to use SHA-256 in digest auth, so I would like to know if MSR supports it, or is it limited to MD5-based digest auth?
Multi-System Reactor
Cloning actions in reactions does not work
tunnusT
With build 26140 (on Docker) I'm not able to clone any actions in reactions. Using Chrome if it has any relevance.
Multi-System Reactor
Has ping command been removed?
tunnusT
Topic thumbnail image
Multi-System Reactor

PR #178 In-place modification of arrays in "each"

Scheduled Pinned Locked Moved Multi-System Reactor
4 Posts 2 Posters 790 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • toggledbitsT Offline
    toggledbitsT Offline
    toggledbits
    wrote on last edited by toggledbits
    #1

    I'm moving the discussion on this out of the Mantis PR #178 for the benefit of all/documentation, and also because it's easier to type and format here.

    @LibraSun wrote in that PR:

    I'm 99% certain you'll explain this one away as "expected" but I naively believed it would yield different results:
    In an expression defined by:
    a=[1,2,3],
    each i in a:
    shift(a)
    // result (array) [1,2] (unexpected
    // expected [1,2,3]

    This has me thinking that 'each' is leaving items on the table, as I tried unsuccessfully pointing out above.

    The issue here is that your expression shift(a) is modifying the iteration subject array in place. Basically, here are the iteration steps that are run, starting with a=[1,2,3]

    1. First iteration: a=[1,2,3]; the local i is assigned the first array element 1, but it is not used in the expression. The expression shift(a) results in 1 and causes a to be reduced to [2,3] (the first element is shifted off and becomes the result). Since this is the last value in the expression, 1 is added to the each result array.
    2. Second iteration: a is now [2,3] because the previous iteration modified it. So i is assigned 3, because the iteration is on the second element/iteration through the array, but i is not used in the expression. The shift(a) causes a to be reduced to [3] and its return value is 2, so the value 2 is added to the iteration result array.
    3. Third iteration: a is now [3], and we are on the third iteration, but the iteration index of 3 (third iteration) is now off the end of the array (only 1 element long), so iteration stops.

    The result of this each is therefore [1,2] because those are two values that were shifted out, and a is left at [3] because there was no third run of shift() to remove it.

    As I said in the PR, modifying an array you are iterating through can be dangerous and confusing in many languages, because iterators keep state during iteration, and some operations you can do inside the iteration can and will invalidate that state in some way. In Lua on Vera, this often leads to deadlocks and crashes so bad that the box reboots, not just a Luup reload. It's a Bad Idea, and programmers who know are very wary of doing this type of thing in any language unless they are certain of the side-effects/lack of side-effects.

    Your additional example:

    a=[1,2,3], // The array 'a' is [1,2,3]
    a=unshift(a,0), // The array 'a' is [0,1,2,3]
    a=push(a,4), // The array 'a' is [0,1,2,3,4]
    each i in a: // Iterating over the 5 elements of 'a'
    shift(a) // Take the first element of 'a' and append it to result array [ ]
    // result [0,1,2] (unexpected)
    // and array 'a' is now [3,4]! (also unexpected)

    Also correct result. All of the gyrations before the each are not relevant to behavior here. At the start of the each, the array is [0,1,2,3,4] (5 elements). Iterations:

    1. a=[0,1,2,3,4], i=0, shift(a) returns 0 and modifies a to [1,2,3,4]; the each result array is now [0]
    2. a=[1,2,3,4], i=2, shift(a) returns 1 and modifies a to [2,3,4]; the each result array is now [0,1]
    3. a=[2,3,4], i=4, shift(a) returns 2 and modifies a to [3,4]; the each result array is now [0,1,2]
    4. Iteration stops because the iteration index/step is 4, but there remain only two elements in a=[3,4] (we're off the end of the array).

    So the each result is [0,1,2] and a is left with [3,4] and this is correct operation.

    Key points:

    • each keeps state during the iteration (as most iterators do) about the subject of the iteration; if the subject changes in a way that affects the state, unexpected results may occur;
    • The functions push(), pop(), shift() and unshift() modify the array in place. If you say b=shift(a) you get a value in b and a modified (shorter) a.

    Author of Multi-system Reactor and Reactor, DelayLight, Switchboard, and about a dozen other plugins that run on Vera and openLuup.

    1 Reply Last reply
    1
    • LibraSunL Offline
      LibraSunL Offline
      LibraSun
      wrote on last edited by LibraSun
      #2

      Thanks!
      I've read and re-read "Step 4" above numerous times, and it's not sinking in.
      No need to explain further, simply allow me to stew in these juices a while.
      I'll also rig this up a number of other ways (using multiple variables, for starters) to watch intended behavior in action.
      Still weirds me out. 🙂

      EDIT: I believe I understand now; the each loop is foiled mid-stream because the array a keeps shrinking with each iteration, whereas each thinks it's still holding onto a 5-element array. It's not, therefore it aborts.

      LESSON: It would make better sense to create an index array (=[0,1,2,...,N]) of the same length as a, and generate the result with:

      a=["a","b","c","d","e"], index=[0,1,2,3,4],
      each i in index: a[i]
      

      for which the trivial result would be a copy of a as I had been expecting in the original example.

      toggledbitsT 1 Reply Last reply
      0
      • LibraSunL LibraSun

        Thanks!
        I've read and re-read "Step 4" above numerous times, and it's not sinking in.
        No need to explain further, simply allow me to stew in these juices a while.
        I'll also rig this up a number of other ways (using multiple variables, for starters) to watch intended behavior in action.
        Still weirds me out. 🙂

        EDIT: I believe I understand now; the each loop is foiled mid-stream because the array a keeps shrinking with each iteration, whereas each thinks it's still holding onto a 5-element array. It's not, therefore it aborts.

        LESSON: It would make better sense to create an index array (=[0,1,2,...,N]) of the same length as a, and generate the result with:

        a=["a","b","c","d","e"], index=[0,1,2,3,4],
        each i in index: a[i]
        

        for which the trivial result would be a copy of a as I had been expecting in the original example.

        toggledbitsT Offline
        toggledbitsT Offline
        toggledbits
        wrote on last edited by toggledbits
        #3

        @librasun I'm not sure if this will help, but here's an example without arrays that demonstrates the common behavior of loop and iterator constructs often seen. Yes, there are variances across languages, but I think most programmers will agree that this is what they would expect from a new language, and then will be prepared (or surprised) by any differences from that norm:

        int n = 10;
        for ( int k = 0; k <= n; k = k + 1 ) {
            System.out.println( k );
            if ( k == 5 ) {
                n = 4;
            }
        }
        

        If you're not familiar with the for() loop construct (this is C/C++/Java-ish and a little different from Lua), the first expression is the initializer, the second is the continuation test, and the third is the post-effect. The initializer is run once before entering the loop, the continuation test is run before each iteration (and iteration stops if the test is false), and the post-effect is run at the end of each iteration. So in the absence of the if statement, this loop should output the numbers 0 through 10 inclusive.

        But what would you expect the output of this loop to be with the if statatement? I would expect:

        0
        1
        2
        3
        4
        5
        

        ...and the reason is that each trip through the loop, the test expression k < n is evaluated using the then-current values of k and n. So if n changes, as it does in this case when k reaches 5, the next eval of the loop's test expression would see the new value of n (4), and since we're now in a new iteration, k has gone to 6, which is not less than 4, so the loop exits there.

        What does not happen here is that the value of n is pre-determined at the start of the loop, and thus immune to a change within the loop. If that were the case, language consistency would demand that k also be pre-determined and not change in this expression, and this would be disastrous, because the loop could never operate properly (it would loop infinitely in most common applications of this form).

        @librasun said in PR #178 In-place modification of arrays in "each":

        LESSON: It would make better sense to create an index array (=[0,1,2,...,N]) of the same length as a, and generate the result with:

        Well, I'm not really sure what problem you're trying to solve, or if you're just doing crazy things to see what breaks (which is fine, that's a perfectly valid way to test something). Based on what you said you expected in your first example above, all you need is:

        a=[1,2,3];
        b=each i in a: i;
        

        This would produce your expected [1,2,3] in b. In other words, a copy of the array (a is unmodified here). It would thus follow:

        a=["a","b","c","d","e"],
        b=each i in a: i
        

        Would produce b=["a","b","c","d","e"] in a bit shorter way than your follow-on example.

        Author of Multi-system Reactor and Reactor, DelayLight, Switchboard, and about a dozen other plugins that run on Vera and openLuup.

        LibraSunL 1 Reply Last reply
        1
        • toggledbitsT toggledbits

          @librasun I'm not sure if this will help, but here's an example without arrays that demonstrates the common behavior of loop and iterator constructs often seen. Yes, there are variances across languages, but I think most programmers will agree that this is what they would expect from a new language, and then will be prepared (or surprised) by any differences from that norm:

          int n = 10;
          for ( int k = 0; k <= n; k = k + 1 ) {
              System.out.println( k );
              if ( k == 5 ) {
                  n = 4;
              }
          }
          

          If you're not familiar with the for() loop construct (this is C/C++/Java-ish and a little different from Lua), the first expression is the initializer, the second is the continuation test, and the third is the post-effect. The initializer is run once before entering the loop, the continuation test is run before each iteration (and iteration stops if the test is false), and the post-effect is run at the end of each iteration. So in the absence of the if statement, this loop should output the numbers 0 through 10 inclusive.

          But what would you expect the output of this loop to be with the if statatement? I would expect:

          0
          1
          2
          3
          4
          5
          

          ...and the reason is that each trip through the loop, the test expression k < n is evaluated using the then-current values of k and n. So if n changes, as it does in this case when k reaches 5, the next eval of the loop's test expression would see the new value of n (4), and since we're now in a new iteration, k has gone to 6, which is not less than 4, so the loop exits there.

          What does not happen here is that the value of n is pre-determined at the start of the loop, and thus immune to a change within the loop. If that were the case, language consistency would demand that k also be pre-determined and not change in this expression, and this would be disastrous, because the loop could never operate properly (it would loop infinitely in most common applications of this form).

          @librasun said in PR #178 In-place modification of arrays in "each":

          LESSON: It would make better sense to create an index array (=[0,1,2,...,N]) of the same length as a, and generate the result with:

          Well, I'm not really sure what problem you're trying to solve, or if you're just doing crazy things to see what breaks (which is fine, that's a perfectly valid way to test something). Based on what you said you expected in your first example above, all you need is:

          a=[1,2,3];
          b=each i in a: i;
          

          This would produce your expected [1,2,3] in b. In other words, a copy of the array (a is unmodified here). It would thus follow:

          a=["a","b","c","d","e"],
          b=each i in a: i
          

          Would produce b=["a","b","c","d","e"] in a bit shorter way than your follow-on example.

          LibraSunL Offline
          LibraSunL Offline
          LibraSun
          wrote on last edited by
          #4

          @toggledbits NOTE: Yes, it was just me trying to break stuff. I really don't have any outstanding needs at the moment in terms of my daily workflows. Thanks for the tutorial (which all makes sense)!

          1 Reply Last reply
          0
          • toggledbitsT toggledbits locked this topic on
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          Recent Topics

          • Arming Envisalink panel from MSR
            toggledbitsT
            toggledbits
            0
            5
            16

          • Upgrade Issues
            T
            tbully
            0
            9
            133

          • [SOLVED] Conflicting Set Reaction Groups Appear to Fire Simultaneously in Single Rule Evaluation
            toggledbitsT
            toggledbits
            0
            10
            113

          • [SOLVED] Question regarding "in" vs "contains" vs contents of the string
            G
            gwp1
            0
            5
            48

          • Reactor (Multi-System/Multi-Hub) Announcements
            toggledbitsT
            toggledbits
            5
            147
            127.6k

          • openLuup console disappeared - 500 - Internal Server Error
            A
            a-lurker
            0
            2
            150

          • Logon screen timeout
            G
            gwp1
            0
            5
            177

          • [MSR] Copy&past of actions and/or drag&drop between set/reset
            toggledbitsT
            toggledbits
            0
            9
            325

          • Upgrade advice - upgrade from aarch64 to ARM64 image
            toggledbitsT
            toggledbits
            0
            4
            190

          • Alexa for MSR, any interest?
            CatmanV2C
            CatmanV2
            2
            4
            323

          • Ezlo Paid Subscription for Vera Cloud Services
            therealdbT
            therealdb
            4
            2
            458
          Powered by NodeBB | Contributors
          Hosted freely by 10RUPTiV - Solutions Technologiques | Contact us
          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Unsolved