CQC 1.4 is released

Just a little teaser....

WebSrvPreview2.jpg


Our next CQC release will have a built in web server so that you can do web-based access to CQC. This will be early days so it won't be the all seeing/all dancing web server but it'll be pretty nice. We'll probably consider the version of it coming out in the 1.5 release to be a beta so it won't be licensed or anything in that release so that everyone can play around with it.

It basically will allow you to access htm/html, jpeg, and txt files on disk, and to invoke macros (in our CML language) that can spit out dynamic pages so that you can provide device status-based image display and such. I'm calling it CML-Bin, since it's a lot like GCI-Bin. The disk based files can have replacement tokens that refer to CQC device fields, which is how the pages above were done. The tokens are just replaced with the actual values of the fields as the page is loaded. Buttons can just invoke macros via a POST that sends the data the macro should process.

Since it's our own web server, there's no complicated configuration. You'll just pick a port, and set a couple of security settings, and that's it.
 
Move over HomeSeer... That looks great. How dare you keep a secret that good from us :)

Wow!. I am impressed.
 
Well, I ran the first event driven actions tonight, so all the basic stuff is in place now for CQC to handle the 'do X if Y happens' type automation logic. This is the biggie for 1.5, so we are finally over the hump and now will be in the 'tightening up' phase and moving towards a 1.5 beta before too long here.

The event filtering system is based on the same expression syntax as used in our PDL driver language, so you can do quite complex filtering, i.e. 'if it's 10am, and I'm drunk, and my wife is really pissed, lock the doors', that kind of thing. What used to be the 'sheduled events' server is now just the 'events server' and handles both scheduled events and triggered events. The interface viewer will also be able to listen for events, though the things it will do in response will be a fairly simple in the 1.5 release. It's mainly for things like popping up a translucent window when a given event comes in, for things like announcing incoming calls or the front door bell or whatever.

The syntax for the events is xAP, so though we won't do it in 1.5, by 1.6 we'll have a 'xAP Gateway' server that can be used as an interface between CQC and the outside xAP world. CQC's events are encrypted, but the xAP Gateway will be able to bring them in or allow them to pass out. So you'll be able to have CQC react to xAP events, or for xAP programs to react to CQC events.

1.5 will also include a web browser widget for the interface system, so that you can embed web pages in your interfaces, and will include the web server mentioned above for web-based access to CQC. So, though as always I claimed it was going to be an extremely focused release, it's managed to accumulate unplanned features along the way.
 
And here are some simple examples of dynamic page content through our web server. They look a little rough due to high compression, but good enough for the purpose.

These are done via the CMLBin scheme mentioned above, where you can invoke a special type of URL and that will cause a CML macro to be run to generate the page. This provides a very high degree of flexibility, and access to all the CQC information and control you need.

These are also accessing images directly from CQC's image repository, so they aren't on-disk images as normally would be the case with a web server. There is also a special form of URL that allows CQC images to be embedded into web pages.

So if you are using an image set for your CQC interfaces, you don't have to have separate copies of the images and keep them in sync in order to use a simple look in your web pages. In the case of the weather page, that image is from the weather channel image set. There are quite a few images in there and it would be a pain to have to keep two separate copies.

WebSrvPreview3.jpg




WebSrvPreview4.jpg
 
Incredible work! This is exactly what I'm looking for. I will be building a demo home in the next year or so, and from what I've seen I'd like to use your software exclusively for the higher level front end. I'll be contacting you for more information in the next few weeks through your website.
 
1/10th score and a few hours ago, a much thinner, somewhat saner me brought forth unto this continent a new product, conceived in my bedroom, and dedicated to the proposition that I should be able to own a Ferrari. Now we are engaged in a great coding effort, testing whether that product, or any product so conceived and so dedicated, can long endure. We are met on a great online forum of that war.

Well, it's been two years exactly since CQC 1.0 was released. I noticed this a little while back when I was searching for something and just happened on the 1.0 announcement post. It's come a long way in that time.

A screen cap of CQC circa 2 years ago at the 1.0 release
Showoff.jpg


It's hard to even remember that version of it. There was no administrative tools per se, the client side driver interfaces were just separate programs. The earliest version of the user interface system had just arrived (the window that says "A/V System", but it just used standard windows widgets so it wasn't too sexy looking. There was just a very simple interpreted macro language and a very simple serial driver language, and no actual tools for editing them, no centralized storage of data and other servers, no event system, no XML Gateway, etc...

There have been a lot of brain cells under the bridge since then, and I'll never get them back.
 
I'm working towards a 1.5 beta this week sometime, and I just wanted to post a little info about the new event system, since it's something that many folks who are hard into the pure automation thing have been wanting in CQC before they'd be interested. So I figured I'd give you some info on what's coming so that you can comment now if you think something is missing.

Basically it's in parts. There are 'event triggers', where you indicate that you want a particular device field to cause a field change event to occur. In CQC all devices are composed of a set of 'fields' that are named entities that usually represent some readable or writeable value in the device. So you can mark the fields that you are interested in being notified of change for, and only those will send events (which will significantly reduce the level of event activity over just sending them for any change.)

You can indicate that you want it to send an event for any change in the field, or if it the value changes to or away from some value, is greater than or less than some value, is non-zero, and so forth. There are a standard set of such 'expressions' in CQC that are used in a few places, and those standard expressions are used in these event triggers.

On the receiving end, you define an 'event filters', where you define some action that you want to occur, and then you create a filter that decides if an incoming event meets the criteria for triggering that action. These filters are done using a simple expression language, which is actually a subset of the expression language used in our PDL (protocol description language) system used for writing drivers for simpler types of devices.

It's a very straightforward, purely declarative, language that is very fast to parse and create an expression tree from, but quite flexible at the same time. So, a very common filter would look like this:

Code:
IfAll 
( 
    IsFldChangeFor("DevSim.Power") 
    , FldValIs(True) 
)

Basically there must be one top level expression that resolves to true or false, i.e. an expression that has a boolean result. If it resolve to true, then the action is taken, else it is not.

In the example above, IfAll() is the top level expression. It takes an arbitrary number of child expressions and if they are all true, then it's result is true (i.e. it's an AND expression basically.) The two child expressions in the example above check for, respectively, a field change event for the Power field of the device called DevSim and, if it is, then it checks that the new value is True. I.e. it filtering for the DevSim device to be powered on.

The CQC events are effectively xAP messages, and a field change event would look something like this:

Code:
xap-header 
{ 
    v=12 
    hop=1 
    uid=FF000000 
    class=cqsl.fldchange 
    source=cqsl.field:DevSim.Power 
} 
cqsl.fldval 
{ 
    val=True 
}

This event would pass the filter above, since the event class is a field change, and the source is a field named DevSim.Power, and the value reported is True. You can actually access any arbitrary event fields using lower level expressions than the ones used above. The equivalent of the first example up there would be this:

Code:
IfAll 
( 
    EventFldIs("/xap-header/class", "cqsl.fldchange") 
    , EventFldIs("/xap-header/source", "cqsl.field:DevSim.Power") 
    , EventFldIs("/cqsl.fldval/val", "True") 
)

The values of the event are represented via a path type syntax that should be pretty obvious if you look at the example event above. So the first example up there just used some special case expressions that are designed to make the most common scenarios easy, but you can always drill down and get to specific bits of the event data.

You can also do wildcarding, so something like this:

Code:
IfAll 
( 
    EventFldIs("/xap-header/class", "cqsl.fldchange") 
    , EventFldIsLike("/xap-header/source", "cqsl.field:DevSim.*") 
)

Would trigger the action on any field change from the DevSim device.

There are expressions to check for is it daylight, is it nighttime, for doing addition, subtractions, multiplication, and division, for returning one of two expression values based on the true/false state of a third expression, testing for equality and inequality, testing for greater and less than, and so on. And in addition to the IfAll() used in these examples there is IfAny, basically an OR, and IfOne, basically a XOR. Others can be added fairly easily and will be as we move forward and needs arise for them.

You can also get live device status info so that you can react both to the event contents and to the existing status of the system. So, we could extend the initial example to only trigger if it's not been supressed by the SupressEvent field of the driver named Variables being set.

Code:
IfAll 
( 
    IsFldChangeFor("DevSim.Power") 
    , FldValIs("True") 
    , IsEqual(GetField("Variables.SupressEvent", False))
)

So in this case GetField gets the value of the field, and Equals() compares it to False and returns true if it is equal. So now we'll trigger if it's a field change event for DevSim.Power, the new value is true, and Variables. SuppressEvent is false. So we can now stop this event from happening by setting the SupressEvent field to True.


So that's basically the deal. It's something that can be easily used for simple stuff by non-programmers since simple events will mostly be like the first example. But it can be taken quite far for fancier filtering.

Keep in mind also that an 'action' in CQC is just a sequences of commands, one type of which can be a CML macro invocation. So you can do even more filtering in such macros if you want. So even if the action gets invoked, if that action just basically invokes a macro, the macro can still decide to effectivley do nothing if the situation is not auspicious. But, for the most part, the filtering language will be sufficient to do any filtering you'll need to do, or if something is missing it can probably easily be added via new expressions once it becomes known to us.

So here's one last one, to show an example of something more complex.

Code:
IfAll
(
    IfAny
    (
        IfAll
        (
           IfAll(IsFldChangeFor(L"Motion.Bedroom"), FldValIs(True)),
           IsEqual(GetField("Lights.Bedroom"), FldValIs(False))
        ),
        IfAll
        (
           IfAll(IsFldChangeFor(L"Motion.LivingRoom"), FldValIs(True)),
           IsEqual(GetField("Lights.LivingRoom"), FldValIs(False))
        )
    ),
    IsNight()
)

So this one says that if either motion ws detected in the bedroom and the bedroom lights are off, or if motion was detected in the living room and the livingroom lights are off, and it's night time, then run the action, which will probably turn on the light in the area where the motion was detected.

I'll probably add some more helpers before 1.5, such as DevFieldIs() which would combing the GetField and the FldValIs, since those are going to be done so much, and DevFieldIsLike for regular expression type checks of device fields. With that, the above would get simpler:

Code:
IfAll
(
    IfAny
    (
        IfAll
        (
           IfAll(IsFldChangeFor(L"Motion.Bedroom"), FldValIs(True)),
           DevFldIs("Lights.Bedroom", False)
        ),
        IfAll
        (
           IfAll(IsFldChangeFor(L"Motion.LivingRoom"), FldValIs(True)),
           DevFldIs("Lights.LivingRoom", False)
        )
    ),
    IsNight()
)

So, there'tis. Does anyone have any major complaints about this scheme? It should be plenty powerful enough for the hard stuff and simple enough for the easy stuff.
 
My only complaint is that you seem to always use shortened identifiers such as DevFldIs(). I really think it would make using the language easier if you just wrote out the entire words instead. Reading your examples is very cryptic to most people.
 
Ehhh, it's one of those never ending questions. No matter what you call them, no one is just going to guess what they are, they'll always have to look them up until they have memorized them. So, given that, there's at least a reasonable argument for having less verbiage to type. But, if there's a general consensus that arises, I'm perfectly happy to flesh the names back out.
 
Would picking one or the other break existing code? Thats why I was asking about using both. Perhaps provide examples in longer code format and using short form for personal use.

OR

Simply add more comments explaining in detail what each method and property is being called for. Add the comments actually in the examples.

OR

Provide a language which is already well known across the universe such as VBscript and/or JavaScript and possibly attract the many potential customers that are turned off by your example scripts.
 
All the expressions will be fully documented, as is everything. There will be a new technical document for the event system and the online tutorial will be updated to actually do some event stuff.

On the language thing, it wouldn't really make much difference wrt to the naming of the expresions really, since they'd still have to have names in any language, and no matter what we call them someone will think they should be something else, I'm sure.

The bulk of people using the product will probably not have any significant experience with any particular language we would happen to choose, many of them with none at all. So, in the end, we'd pay a huge price for supporting non-specialized languages, while the benefits wouldn't be that great unless you just happen to be familiar with the particular language we chose.
 
Back
Top