Home AMX User Forum AMX Technical Discussion

how to IDENTIFY WHICH STATE A MULTI-STATE BUTTON IS IN

I have a button which has 3 states it is identided as a multi state bargraph. so if u go to States in TP4 Design u will see
state 1,state2 and state 3. Now in the code how do I identify which button the state it is in?

Comments

  • so it is not a button with an ON/OFF state if it were I could just do this:
    send_string 0,"'WHAT IS STATE OF BUTTON= ',ITOA([dTP_IO[nPNL],615)";
    and it would return either 1 or 0, 1-On and 0 OFF

    This is a button that is defined as Multi-state bargraph, which means controlled by Level Events (I guess)
    so to choose one of the three states this button has I did this:

        send_level dTP_IO[nPNL], 1,1;  - this is state 1
        send_level dTP_IO[nPNL], 1,2;- this is state  2
        send_level dTP_IO[nPNL], 1,3;- this is state  3
    

    But when I do this on the screen I see the same button state I had which was state 1. So what I want to do is know what state the button is in NOW and then toggle to one of the other states - I doint knw the commands/syntax to do so

  • John NagyJohn Nagy Posts: 1,734
    edited October 2022

    Why ask the button what state it is in when it can't be in a state you didn't tell it to be in? Keep a status value in your code. Or simply tell it what you want when you want it, and who cares what it was before?

  • well if I have 3 states and lets say were in state one, I would ask what state am I in and If I am in state 1 I want the next state to be state 2, and if in state 2 - next state to be 3 and if in state 3, next state to be 2 not 1. So if I click
    the button and its state 1, then in code I would ask what state I am in and then change to state 2 as I listed above using the ^ANI command - using multi-state General type:
    SEND_COMMAND dTP_IO[nPNL], "'^ANI-', itoa(btSWMain[2]),',0,', ITOA(nCurrButtonState)";
    where nCurrButtonState is stored as a global variable. I got it to work but thought this was not a good way to track states, holding in a global variable.
    Now if I just had an ON/OFF state I would ask what state I am in by the following code:
    if([dTP_IO[nPNL],btSWMain[nIDX]] == 1)
    and this would say if in ON state is TRUE, but when u have multistates u cannot do this because there is no ON/OFF state.
    I also read people not liking the ^ANI command but using the level command within the 3 states - but I dont know how to visually show the diff states by level onto screen, any ideas using multi-state bargraphs

  • John NagyJohn Nagy Posts: 1,734

    Question: How does the button get into any particular state?
    Typically you would detect the press on a button or process, and determine the mode you want to occur, then tell the button to show that state. As long as your code executed that state, your code knows the value of the current state. So you know what you told the button already. You need not ask the button what you told it, as it should be the state you told it to show. If it isn't in the state you asked to show, it's wrong anyway. Just control the state and tell the button what you want it to show. Who is the boss?

  • THE Button nbr is the same acroos all states. for example my button is nbr 625, well it has 3 states, hence my question What state am I in? So as default the press of button 1 with show state 1. ok great now if I press same button again, nbr 615, if state 1 is on screen then I want to show state 2 and if state 2 is on screen and user pushes it, I want state 3 to show. If state 3 is on screen and user pushes it, I want to show state 2.
    so buttons are:
    state 1 - START
    state 2 - PAUSE
    state 3 - Continue

    I am building a Stop watch and a count down screen. So in above example if user clicks Start the Stop Watch starts and goes thru a timeline every 1/100 of a second. so if user decides to Pause I issue a TIMELINE_PAUSE
    and when I do that the button 615 goes to State 3 Continue, and when they click Continue then Pause shows up and when user Pauses and then clicks diff button nbr 616, Clear, this resets all the numbers and sets button nbr 615 to state 1- Start.

    Now I have all this working using the
    SEND_COMMAND dTP_IO[nPNL], "'^ANI-', itoa(btSWMain[2]),',0,', ITOA(nButtonState)";
    but the whole point of my post was how do I get different state buttons to show on screen using
    LEVEL COMMANdS, as button defne as multi-state bargraphs?
    send_level dTP_IO[nPNL],1,1;
    send_level dTP_IO[nPNL],1,2;
    send_level dTP_IO[nPNL],1,3;

  • richardhermanrichardherman Posts: 387
    edited October 2022

    I think you maybe missed the point on how to set a multi-state bargraph button? You don't control the button number (615), you set the level (1) to the value you want the button to be. In the button properties you set the level you want the button to react to (1), If you have 3 states you could set the 'range low' to 1 and 'range high' to 3. If you then send the level commands from your previous post, each state will show on the TP

  • richardhermanrichardherman Posts: 387
    edited October 2022

  • johnbonz1johnbonz1 Posts: 26
    edited October 2022

    YES - Thats how I had it set up --- u see pics below - BTW button nbr is 617

    1st pic i have the range -
    Range Low - 1
    Range High - 3
    Level Port is 1
    Level Code is 1

    so in the 2nd pic u can see the states

    if I wanted the TP to show state 2 button
    would this work:
    send_level dTP_IO[nPNL],1,2;


  • if I wanted the TP to show state 2 button
    would this work:
    send_level dTP_IO[nPNL],1,2;

    It should. Doesn't it work?

  • NO IT DOES NOT.
    Here is the exact command I issued - send_level dTP_IO[nPNL],1,2;
    and the State button on the TP screen is still showing STATE 1

  • Have you tried through Control-A-Device

    I'd also monitor Device Notifications and confirm the DPS of the level event being sent. When it changes at the device you should see the "Level Value From" update as well.

  • I did the following - nothing happens

  • do I need a Level event? I dont think I do

    LEVEL_EVENT[dTP_IO,1] //select a BUTTON STATE
    {
    stack_var integer nIDX; INTEGER nButtonState; integer nPNL
    send_string 0, "''";
    send_string 0, "'IN LEVEL_EVENT '";
    send_string 0, "' LEVEL.VALUE=',itoa(LEVEL.VALUE)";

    nPNL        = get_last(dTP_IO);
    
    nButtonState = LEVEL.VALUE;
    

    }

  • @johnbonz1 said:
    I did the following - nothing happens

    In the Control A Device dialog the port is set to 18 but in the button properties the port is set to 1 - either the port in the control needs to be 1 or the addressing of the port level needs to be set to 18.

  • And make sure to cycle the Value: through all the valid values - not going to see anything if you set a value to 3 that is already at 3.

  • Wow it works!! Thanks - u were right the Level Port shouls be same as the Address/Channel port - so I changed to 17 and it worked.
    But how do I know what Button State is on the TP at any given time. Because if the button on the screen is START or State 1 and I click it, I want to start a timeline for the Countdown. If the button is state 2, PAUSE, that means timeline is running and I want to pause. I have this working using multi-state general, but I had to store a global variable to know what sate I am in, I dont like that - so is there a command for multi-state bargraph that would be like
    send_string 0,"'BUTTON STATE = ',ITOA([dTP_IO[nPNL],617)"; now this would tell me if the button was ON/OFF but I just showed this as an example.

  • John NagyJohn Nagy Posts: 1,734
    edited October 2022

    Why do you prefer not to let your program be in charge? In essence you want to store your global status variable in the panel instead of in code. Keeping the current status in your program is easier and safer than asking what's on the panel at the moment. After all, your NetLinx is what tells the button what to show, so why ask the button? If the panel goes offline or reboots, the button will not reflect the actual state of your process, which the NetLinx is managing. You'll not get what you think you will, and will not save any coding. On a button press, note the current actual state of processing, take the actions required, and set the button to match.

  • Ok I know what your saying and I am capturing the value or the state of the button, when I issue command
    send_level dTP_IO[nPNL],5,3;

    once this is executed it goes to the Level_event and inside there I have the value from
    LEVEL.VALUE
    then I store in structure
    sStopWatchTimer[nPNL].nButtonState = LEVEL.VALUE;

    So this basically answers my question of How Do I know what my Button State is -

    also if Panel goes off line or reboots, it will go to home screen and to get to the screen in question I would have to re-executed everything and the structure will be re-populpated

    But the Key to this whole POST is really how to get multi state buttons to work and with the help of the people responding - I got it working and I see some like the LEVEL vs the ^ARI commands - which I agree with s0 I am using LEVEL to change BUTTON States

    so thanks everyone!!!:)

  • John NagyJohn Nagy Posts: 1,734

    If the panel goes offline and comes back online, that's visible to your code. When you see a panel come online, run a routine to update it to show what it should... don't wait for users to punch about until it looks ok.

  • Not a bad idea, as if it does come online I could refresh the state of the panel, where it was before it went offline as I do have that info stored.
    speaking of panels that come online and go offline

    is there a way to suppress the messages when it does go online/offline from the Diagnostics:?

    Line 224 2022-10-11 (20:57:56.497):: CIpEvent::OnLine 10012:1:1
    Line 225 2022-10-11 (20:57:56.502):: CIpEvent::OffLine 10012:1:1
    Line 226 2022-10-11 (20:57:56.503):: CIpEvent::OffLine 10012:2:1
    Line 227 2022-10-11 (20:57:56.505):: CIpEvent::OffLine 10012:3:1
    Line 228 2022-10-11 (20:57:56.506):: CIpEvent::OffLine 10012:4:1
    Line 229 2022-10-11 (20:57:56.507):: CIpEvent::OffLine 10012:5:1
    Line 230 2022-10-11 (20:57:56.509):: CIpEvent::OffLine 10012:6:1
    Line 231 2022-10-11 (20:57:56.510):: CIpEvent::OffLine 10012:7:1
    Line 232 2022-10-11 (20:57:56.511):: CIpEvent::OffLine 10012:8:1
    Line 233 2022-10-11 (20:57:56.512):: CIpEvent::OffLine 10012:9:1
    Line 234 2022-10-11 (20:57:56.514):: CIpEvent::OffLine 10012:10:1
    Line 235 2022-10-11 (20:57:56.515):: CIpEvent::OffLine 10012:11:1
    Line 236 2022-10-11 (20:57:56.517):: CIpEvent::OffLine 10012:12:1
    Line 237 2022-10-11 (20:57:56.518):: CIpEvent::OffLine 10012:13:1
    Line 238 2022-10-11 (20:57:56.519):: CIpEvent::OffLine 10012:14:1
    Line 239 2022-10-11 (20:57:56.520):: CIpEvent::OffLine 10012:15:1
    Line 240 2022-10-11 (20:57:56.522):: CIpEvent::OffLine 10012:16:1
    Line 241 2022-10-11 (20:57:56.524):: CIpEvent::OffLine 10012:17:1
    Line 242 2022-10-11 (20:57:56.527):: CIpEvent::OffLine 10012:18:1
    Line 243 2022-10-11 (20:57:56.532):: CIpEvent::OffLine 10012:19:1
    Line 244 2022-10-11 (20:57:56.537):: CIpEvent::OnLine 10012:1:1
    Line 245 2022-10-11 (20:57:56.611):: CIpEvent::OnLine 10012:2:1
    Line 246 2022-10-11 (20:57:56.617):: CIpEvent::OnLine 10012:3:1
    Line 247 2022-10-11 (20:57:56.618):: CIpEvent::OnLine 10012:4:1
    Line 248 2022-10-11 (20:57:56.619):: CIpEvent::OnLine 10012:5:1
    Line 249 2022-10-11 (20:57:56.621):: CIpEvent::OnLine 10012:6:1
    Line 250 2022-10-11 (20:57:56.622):: CIpEvent::OnLine 10012:7:1
    Line 251 2022-10-11 (20:57:56.627):: CIpEvent::OnLine 10012:8:1
    Line 252 2022-10-11 (20:57:56.633):: CIpEvent::OnLine 10012:9:1
    Line 253 2022-10-11 (20:57:56.634):: CIpEvent::OnLine 10012:10:1
    Line 254 2022-10-11 (20:57:56.636):: CIpEvent::OnLine 10012:11:1
    Line 255 2022-10-11 (20:57:56.637):: CIpEvent::OnLine 10012:12:1
    Line 256 2022-10-11 (20:57:56.638):: CIpEvent::OnLine 10012:13:1
    Line 257 2022-10-11 (20:57:56.641):: CIpEvent::OnLine 10012:14:1
    Line 258 2022-10-11 (20:57:56.641):: CIpEvent::OnLine 10012:15:1
    Line 259 2022-10-11 (20:57:56.643):: CIpEvent::OnLine 10012:16:1
    Line 260 2022-10-11 (20:57:56.644):: CIpEvent::OnLine 10012:17:1

  • John NagyJohn Nagy Posts: 1,734
    edited October 2022

    Your choice to use 17 port sets causes a lot of apparent thrash on offline/online. The entirety of what you have listed is actually just ONE off/on event.... but every set is reported in and out. For simplicity, you can simply detect and act on the first port (10012:1:1) and rest assured that all the others will follow and can be ignored. While using more ports than needed impacts memory and process speed, it doesn't hurt much.

    Note that if you decided to add a port 100 in your panel project, skipping ports 18 to 99, EVERY port from 1 to 100 would list to diagnostics and telnet each time the panel bounces. That would be a terrible clutter.

    We added offline logging and refresh management for our systems, as we have extremely intense panel traffic and potentially dozens of panels in our data-driven software design. So rather than refreshing potentially hundreds of dynamic buttons each time a panel burps (which can be frequent for wifi panels!), we take any offline event that is shorter than 10 seconds or so (tunable in data as needed by experience at the site) as a non-event. Clearly the panel didn't reboot in that time, and the dynamic content on any given page is unlikely to have changed and gotten missed in the blip, so we just resume and move on. Longer offlines trigger a wider refresh of the affected panel, and we also send the panel to the base page of what we know to be the active function for that panel/room, as we don't know what was missed or what the panel is showing as it comes alive.

    We also log each panel offline event for easy review if the system is acting up. Panels can drop offline a lot when the network isn't healthy, and the flapping can look like something in programming when it's really a network issue. We further enhanced the monitoring to count offline blips, and if more than 5 occur within 2 minutes or so (again tunable), we send that panel to a TROUBLE page and ignore it for 30 minutes, then try again. The trouble page has an online indicator and a button for the user to manually end the timeout if they wish. The page has instructions to check wifi range or other network problems if this occurs frequently, alerting the user that they have an unusual network issue to resolve, and that the system has acted to preserve usability at other panels. The logs are text files maintained within the NetLinx file system, and they are automatically trimmed to the latest 30 days.

    Your systems likely do not require this degree of self-awareness and self-healing, but it's all part of what can make a complex system more stable - and help you quickly and remotely find a bad panel or wifi area that is raising havoc with a system.

Sign In or Register to comment.