CBus Tags as constant initialisation

Discussion in 'C-Touch/HomeGate/SchedulePlus/PICED Software' started by djaggar, Feb 22, 2013.

  1. djaggar

    djaggar

    Joined:
    Jul 18, 2009
    Messages:
    66
    Likes Received:
    0
    Location:
    New Zealand
    Just a suggestion, but it would be really nice if the Logic engine allowed constants to be set to the value of a tag, but when I try I get an error C261 Tag Error.

    e.g.

    DefaultApplication = "Lighting";

    would do the same as

    DefaultApplication = 56;

    Seems strange that it doesn't work ...
     
    djaggar, Feb 22, 2013
    #1
  2. djaggar

    Goran C Forum Member

    Joined:
    Jun 7, 2012
    Messages:
    28
    Likes Received:
    0
    Location:
    Adelaide
    Tags are customisable and can be readily change this would cause the logic code to frequently break and cause confusion as to why the logic is no longer working or working abnormally.

    For example if you had C-Bus Group 1 attached to the light in Bedroom 1
    and you had logic grab a value from a light sensor and turned on the Group 1 to ON if the light level was below a certain level.

    If your logic referred to the Group 1 Tag "JamesRoom" and later down track you changed that tag to refer to "BobsRoom" then that logic would no longer work as it would be looking for JamesRoom which no longer exists however Group 1 is still associated with Bedroom 1.
     
    Goran C, Feb 22, 2013
    #2
  3. djaggar

    djaggar

    Joined:
    Jul 18, 2009
    Messages:
    66
    Likes Received:
    0
    Location:
    New Zealand
    Huh? Doesn't that happen anyway? If I write this
    Code:
    SetLightingState("BobsRoom", false) 
    and then I change the value of BobsRoom I have to recompile the logic code to get the new value of BobsRoom. If that weren't true the Tag database would have to exist in every logic engine, which it doesn't ...

    My problem is this, I have a 50 or so references to a stack of groups. For some installs, they won't all fit in the lighting app. So I want to write

    Code:
    const
       DefaultNetwork = "Local Network";
       DefaultApplication = "Lighting";
    and then throughout the code write things like

    Code:
       SetCBusState(DefaultNetwork,DefaultApplication,"AGroupName");
    
    but I can't define my constants that way.
     
    djaggar, Feb 22, 2013
    #3
  4. djaggar

    Darren Senior Member

    Joined:
    Jul 29, 2004
    Messages:
    2,361
    Likes Received:
    0
    Location:
    Adelaide, South Australia
    The constant DefaultApplication will be an integer value and the compiler needs to work out what value you want. The reason your code doesn't work is that there is no way for the compiler to understand from the context that "Lighting" is an application tag.

    There is a solution though.

    Define DefaultApplication as an integer variable.

    In your logic initialisation code, you use:

    DefaultApplication := GetCBusApplicationAddress("Lighting");

    See the logic help file topic "GetCBusApplicationAddress Function" for details.
     
    Darren, Feb 23, 2013
    #4
  5. djaggar

    djaggar

    Joined:
    Jul 18, 2009
    Messages:
    66
    Likes Received:
    0
    Location:
    New Zealand
    Thanks for your suggestion, it's helpful but not what I'm getting at. You say reason my code doesn't work is that the constant value will be an integer value, but it doesn't have to be, the point is it could be a tag, that is, its type is tag, not integer, in the same way that the type of a constant can be string or float. So the compiler then knows the context of the tag, it is the context in which it is used. Its seems to me that constants have to be typed anyway, so it's not as if most of that mechanism isn't already there in your compiler.

    What of course I'm trying to achieve is to hoist all the configuration into the constant section so there is one place to go to efficiently alter the code to suit each install. I understand I can add another global variable (for every network, application, and group) and take a small runtime hit to access the value of all three for every call to a Get/Set CBus function, but that's a shame when these things really are constants known are compile time. But thanks again for your suggestion.

    On a related note, if you really want to make my day, give me #define and #ifdef #else #endif i.e. preprocess the source :) Along those lines, here is a wee trick I've been using for a while to switch between two alternate bits of code (i.e. a poor man's ifdef)

    Code:
      // { Remove the // at the start of this line to enable the B Side and disable the A Side
      //  // A Side code goes here
      
      (*} // B Side code goes here
    
      //*) // End of optional code
    Also, while I think of it, is there dead code elimination in the compiler e.g. does

    Code:
    const
      debug = 0;
    
    if (debug) then LogMessage('Debugging enabled');
    result in any code being generated?

    Thanks,
    Dave

     
    djaggar, Feb 23, 2013
    #5
  6. djaggar

    ashleigh Moderator

    Joined:
    Aug 4, 2004
    Messages:
    2,397
    Likes Received:
    26
    Location:
    Adelaide, South Australia
    In the pascal language on which the scripting engine is based, constants are... well... constant.

    That is, they are a named number, like

    const pi = 3.1415926535;

    tags are not constants, they are variables looked up at run time.

    So what you are asking for is a change to the semantic behaviour of the underlying scripting language. Thats not a bolt on, thats a major change to be considered very carefully in case of unforeseen problems.

    Read that answer as: big ask, not very likely.
     
    ashleigh, Feb 23, 2013
    #6
  7. djaggar

    djaggar

    Joined:
    Jul 18, 2009
    Messages:
    66
    Likes Received:
    0
    Location:
    New Zealand
    The thing that is confusing to me is the bit that tags are variables looked up at run time. If I read, for example, the definition of GetCBusApplicationAddress from the Piced manual it says

    "If the Name parameter is an Application Tag, then the name is looked up in the C-Bus Tag Database at compile time only. This is not at all demanding on processor time."

    So the manual says tags are looked up at compile time (at least sometimes) which is what I always thought, but you guys all seem to be saying run time. Sorry, but which is correct?

    And by the way, the first few words of my original post was "Just a suggestion", I'm not trying to give you a headache, if its hard, so be it. But there is a conflict (in my head at least) as to when the value of a tag is evaluated, run time or compile time.

    Cheers,
    Dave
     
    djaggar, Feb 24, 2013
    #7
  8. djaggar

    Darren Senior Member

    Joined:
    Jul 29, 2004
    Messages:
    2,361
    Likes Received:
    0
    Location:
    Adelaide, South Australia
    I suspected you would say that :)

    The problem is that there is no tag type. There are only integer, boolean, char (including string) and real types. Tags are a short cut for an integer value and they can only be determined by context (in most cases). It is a convenient "hack" to the Pascal compiler to provide convenience for the users.

    The compiler could, in principle, be extended to handle tags as constants, but it is not a trivial task.

    A better way might be to handle "define" type instructions, but that is a major change, as it will probably need to compiler to change from a one-pass, one symbol look-ahead compiler to a multi-pass compiler. This is not a trivial change either.

    It is on the (long) list of things to do.


    Very neat.

    There is no dead-code elimination in the compiler.
     
    Darren, Feb 24, 2013
    #8
  9. djaggar

    Darren Senior Member

    Joined:
    Jul 29, 2004
    Messages:
    2,361
    Likes Received:
    0
    Location:
    Adelaide, South Australia
    Sorry about the confusion. This is one of the very, very rare occasions where Ashleigh was wrong about something (although a very minor point). I will have to remember this occasion so I can gloat about it sometime ;-)

    It is correct that tags are not constants as discussed in my post above. The tags are actually looked up at compile time and turned into integer values on the fly. The integer values are then used by the compiler as if they were written in the code as integers.

    The only exception to this is when using the C-Bus tag look-up functions and passing them a string variable (not a tag). In this case the tag has to be looked up at run time because the value is not known at compile time. These functions are not normally used though.
     
    Last edited by a moderator: Feb 24, 2013
    Darren, Feb 24, 2013
    #9
  10. djaggar

    djaggar

    Joined:
    Jul 18, 2009
    Messages:
    66
    Likes Received:
    0
    Location:
    New Zealand
    I get they aren't real Pascal constants, but their values are constant. Pascal String Constants might be helpful (see below)...

    Sooo ... you've almost just implemented it :) If the string variable does happen to be known at compile time (i.e. it's a constant string, or a literal string), at compile time just look its value up in the tag database ...

    Code:
    program TongueInCheek(input {just a suggestion}, output {none expected} );
    
    const
        AStringThatsReallyATagWhoseValueIsKnownAtCompileTime = 'Lighting';
        AnIntegerConst = 56;
    var
        AString: string;
        AnInteger: integer;
    Procedure TestParser;
       AString := 'Lighting';
       AnInteger := 56;
    
       GetCBusApplicationAddress(56); // This Works
       GetCBusApplicationAddress(AIntegerConst); // And This Works
       GetCBusApplicationAddress(AnInteger); // This Also Works
       GetCBusApplicationAddress("Lighting"); // This Works Too
       GetCBusApplicationAddress(AString); // Even This Works (At Run Time)
    
       GetCBusApplicationAddress('Lighting');
             // This Works At Run Time, 
             // But it could work at Compile Time (hint hint)
             // Poor Literal Constant String left on the compile time sideline
    
       GetCBusApplicationAddress(
           AStringThatsReallyATagWhoseValueIsKnownAtCompileTime);
           // If the line above works, this should work too,
           // Because it's no less constant than the line above, just not literal
       end;
    end; {Of Program}
    All joking aside, I get you're spotting double quoted things at some high level in the parser (although it can't be that high level because you need to know what kind of tag to look up from the context) and substituting the integer value to the rest of the compiler, but you also handle variable strings at this point (for some calls), so you know at this point a) the context of the tag (network, app, group etc), the b) type of the argument (integer or string) and c) its value if its constant. So call your tag evaluation code with the value of the constant string, and presto :) Like I said, just a suggestion. Keep up the good work!

    Cheers,
    Dave
     
    djaggar, Feb 24, 2013
    #10
  11. djaggar

    jackaroos

    Joined:
    Apr 8, 2014
    Messages:
    17
    Likes Received:
    0
    Location:
    New Zealand
    I have a project with 50-odd networks and I am having the following issue:

    I have:
    Code:
    //global variables
    J1L1_PRIM: integer;
    
    //initialisation
    J1L1_PRIM := 253;
    but "J1L1_PRIM" is causing a tag error in:

    Code:
    SetCBusLevel(J1L1_PRIM, "DALI_J1_L1", "J1L1_D1-G9", 0, "60m");
    If I change out J1L1_PRIM for 253 in the above code, no tag error.

    FYI I also tried
    Code:
    J1L1_PRIM:= GetCBusApplicationAddress("DB/LP-J1/L1-PRIM");
    but it also gets a tag error.

    I have triple checked, the tags exist in S+ and I can use them on buttons but not in the logic, so what am I doing wrong please? :)
     
    jackaroos, Sep 26, 2017
    #11
  12. djaggar

    Ashley

    Joined:
    Dec 1, 2005
    Messages:
    1,548
    Likes Received:
    178
    Location:
    Adelaide, Australia
    The problem is that tags are converted to their corresponding integer at compile time. However, since your network is a variable it's value isn't known at compile time so it can't lookup the group tag because it doesn't now what network to use. I'm not really sure what you are trying to accomplish because a group belongs to a specific network, so if you know the group tag you also know the network it belongs to. Perhaps you could describe what you a re actually trying to accomplish? If you make the group a variable and load it with the correct value, it will work just fine.
     
    Ashley, Sep 26, 2017
    #12
  13. djaggar

    jackaroos

    Joined:
    Apr 8, 2014
    Messages:
    17
    Likes Received:
    0
    Location:
    New Zealand
    Hi Ashely

    What I am trying to do is reduce the likelihood of typing errors, and have just one place to correct things :)

    I understand the value of tags is determined at compile time, but if using an network number (integer) instead of the tag works, why does a variable that is an integer not work?

    IMHO this should be changed.

    thanks very much
    Jackie
     
    jackaroos, Sep 27, 2017
    #13
  14. djaggar

    Ashley

    Joined:
    Dec 1, 2005
    Messages:
    1,548
    Likes Received:
    178
    Location:
    Adelaide, Australia
    Your problem isn't with using a variable as the network number, it is using a tag name as a group while using a variable as the network number. How can the compiler convert the group tag to a number when it doesn't know which network to use? By using a variable as a network, the assumption is you are going to dynamically change the network at run-time. What are you expecting it to do with the group? Does the group tag exist in every network with the same value?

    But aren't you just replacing one potential typing error for another? Instead of typing the tag "J1L1_PRIM" you have to type the variable name J1L1_PRIM. What's the difference? Do you need to be able to change the network number? if so, why not just change the tag name in the database?

    Note that if you aren't proposing to change the network variable at run-time you can just define it as a constant and it will compile fine.

    e.g.
    CONSTANTS
    J1L1_PRIM = 254;
     
    Ashley, Sep 27, 2017
    #14
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.