Jump to content

Variables, Parameters, and Timers


Algorithm

Recommended Posts

With firmware version 2.7 approaching, perhaps it is time to give some consideration to the next release. This post will discuss one of the most often requested features, variables, and how they might be implemented. Like most other things, it is likely that they will not simply spring up full-grown in a single release, but will emerge and grow over a series of updates. Therefore we will examine some of the considerations with a view to an initial release, and subsequent enhancements.

 

Scope

In the initial release, all variables may well be global in scope (even if it causes the programmers among you to shudder). Future releases may provide for private variables within programs, folders, or on a per-device basis, for example.

 

Namespace

As with scope, the initial namespace for variables is likely to be global, which makes sense in the context of globally scoped variables. This would require that there never be two items with identical names (which is always my preference). Thus devices, scenes, programs, variables, etc. may be given an identification scheme such as 'dHall Light', 'sHall Light', 'pHall Light', 'vHall Light' and so forth. When private variables make an appearance, private namespaces should follow in kind. The initial default variables may be named simply v0, v1, v2..., with allowance for the user to rename each variable.

 

Type, Size and Range

The first release may implement only a single, simple variable type, such as Integer. If so, we must still answer the questions of size and range. Is sixteen bits sufficient? If so, should they be signed or unsigned? Sixteen bits may seem wasteful for a simple Boolean value, yet are insufficient, even if unsigned, to hold the time of day to a one second resolution, which might be a common use for an integer. [The number of seconds in a day is 60 secs/min X 60 mins/hr X 24 hrs = 86,400, while the maximum value of a 16-bit unsigned integer is 65,535.] Twenty-four bits, then? Still insufficient, even if unsigned, for a one-second resolution time-of-year. [86,400 secs/day X 366 days = 31,622,400, while a 24-bit unsigned integer has a maximum value of 16,777,215.] Thirty-two bits? A 32-bit unsigned integer has a range of 0 to 4,294,967,295, while a 32-bit signed integer has a range of -2,147,483,648 to 2,147,483,647, either of which is easily enough to handle the previous two examples, yet certainly common examples could be put forth which exceed even that range. Should thirty-two bits be considered a minimum, or would it simply be overkill?

 

Once a minimum size is decided, and allowing for only a single type in the first release, it must still be decided whether the variables should be signed or unsigned. Aside from the difference in range, each has advantages and disadvantages. Given sufficient programming flexibility, one can handle signed values even in the context of unsigned variables, but my feeling is that it is much more difficult to do so, than it is to handle unsigned values in the context of signed variables of sufficient size for the required range. Therefore I would prefer to see signed variables.

 

Future releases should see additional variable types, such as float and string, and possibly even boolean, arrays, structures and others. Considering the future serial expander module, it would seem that strings would be vital as soon as that module arrives, and would be very useful even now.

 

Number and Storage

How many variables are required, and how should they be accessed? Should there be a static variable space with all variables pre-defined, for example, v0 - v256 (which the user can rename)? Or should they be dynamically allocated? As soon as more than one variable type exists, such as integer and float, should there be separate static arrays such as i0 - i128 and f0 - f128, or should each variable be typed as it is dynamically allocated?

 

How much storage should variables be allowed to occupy? The current ISY-99 series can accept an SD memory card of up to 4GB. If we initially allocated only 8kB of storage (.0002% of the total) for variables, that would allow for 512 variables with an average length of 16 bytes (considering integers, floats, and strings).

 

Persistence

How long should a variable maintain its value? Should it persist through a system restart? Since the ISY's memory is non-volatile, it would seem that all values would persist by default. Certainly we would like some variables to retain values through a restart. Others we would likely prefer to have cleared at startup. Though the user could clear variables in a program that runs at startup, it would be convenient if the system automatically cleared those variables. Suppose we provided a user-settable parameter which specified a point in the variables array, above which variables would persist, and at and below which variables would be cleared?

 

Operations

What would be the most basic set of operators that must be provided initially? If the initial variable type was integer, would Read, Set, Increment, Decrement, Add, Subtract, Multiply, Divide, Modulus, Is Equal, Is Not Equal, Is Greater Than, Is Less Than, Is Greater Than or Equal, Is Less Than or Equal be sufficient? Should we include Logical And, Or, Exclusive Or, and Not? How about bit-wise operations? For floats, what additional operations? And what string operations?

 

Parameters

These could be thought of as system variables, and should likely be user configurable via the Configuration tab. They would include things already available on that tab, such as Query at Restart, Send Compact Notifications, etc. as well as others such as the persistent variable setpoint mentioned above. Should they also be available programmatically?

 

Timers

These are integer variables which can be read, set, and modified just like any other variable. However, they also automatically increment in value once per second, providing a one-second resolution timer with a range equal to the range of the variable. Rather than rolling over at the top of the range, they have a stop value, which when reached causes the timer to stop running. All timers are initialized to this stop value at system startup, so no timers begin running until specifically set by the user. The stop value would most likely be either zero, or else the maximum value in the case of an unsigned integer, or -1 in the case of a signed integer.

 

Strings

As mentioned above, string variables will be very important for use with the serial expander. They will also be very important in conjunction with some other future feature enhancements, such as user-configurable text in notifications, sending of direct http messages for control of Ethernet devices, etc.

 

Should they be ASCII strings, or Unicode strings? What should be their maximum size? For use with the above features, obviously they should support variable elements and formatting; should this by done via specifiers a la C, or some other way?

 

Conclusions

In the past I have used an automation controller with most of these features. It provided for 128 global, unsigned 16-bit integers; 64 unsigned 16-bit timers with a stop value of zero, 64 ASCII strings of 32 bytes with a single variable element and minor formatting, and all the requisite parameters. It was very usable, but could definitely be improved upon.

 

For the ISY, I would prefer to initially see at least 32-bit signed integers, 32-bit signed timers with a stop value of -1, and arbitrary length strings with full formatting and variable elements. I'm sure each of you will have his own preferences, and I would like to hear them.

Link to comment

That's way too much stuff to try and reply to, plus as a software developer by trade, I would like a real scripting language :)

 

So why not look into using a real scripting language to start with?

 

Seems to be a common theme with home automation software, start out with a simple unique language and slowly grow it until it has most of the features of a common scripting language but is hard to use because it is unique.

 

I'm sure there are a number of simple basic interpreters that are free and would provide a good starting point.

Link to comment

For the ISY, I would prefer to initially see at least 32-bit signed integers, 32-bit signed timers with a stop value of -1, and arbitrary length strings with full formatting and variable elements. I'm sure each of you will have his own preferences, and I would like to hear them.

This is a very good post, so thanks! Counters, timers and strings all make sense to me as important initial features that I could use immediately.

 

As far as supporting a real scripting language, that's a big question for UDI with very large consequences. Some HA controllers I've used, such as the Barix Barionet, offers both. It's useful out-of-the-box with minimal setup, but also supports a version of Basic for advanced users. I happen to like the direction the ISY rules logic and scheduler is heading. It's both easy to learn and to use. Regardless, I'd suggest not getting too carried away and to keep the scheduler clean and predictable. One of the difficulties I had with Homeseer as an Insteon controller was how easy it was to get into race conditions with multiple running events and interrupt conditions, such as one event depending on or needing to cancel another running event. I would often get something to work most of the time, but then every once in awhile, not work correctly. I suppose it has to do with their priority-based multi-threaded implementation. Great for performance, nasty for consistency. Since I've moved all of my lighting event logic from HS to the ISY, my lighting system is working much more predictably.

 

Back to work.

Link to comment

Archived

This topic is now archived and is closed to further replies.


  • Recently Browsing

    • No registered users viewing this page.
  • Forum Statistics

    • Total Topics
      36.9k
    • Total Posts
      370.2k
×
×
  • Create New...