• Recent
    • Tags
    • Popular
    • Register
    • Login

    Please Note This forum exists for community support for the Mango product family and the Radix IoT Platform. Although Radix IoT employees participate in this forum from time to time, there is no guarantee of a response to anything posted here, nor can Radix IoT, LLC guarantee the accuracy of any information expressed or conveyed. Specific project questions from customers with active support contracts are asked to send requests to support@radixiot.com.

    Radix IoT Website Mango 3 Documentation Website Mango 4 Documentation Website Mango 5 Documentation Website

    Percent Used Bar Chart

    Dashboard Designer & Custom AngularJS Pages
    3
    14
    2.1k
    Loading More Posts
    • 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.
    • ricardoR
      ricardo
      last edited by

      We have a few MQTT occupancy sensors that have a binary data point called "occupancy" that indicates a cubicle is vacant (0) or occupied (1).

      The client would like to trend the utilization of each sensor by hour or day for a certain time range. For example, the client would like to see a bar chart of percent used of a cubicle by hour for Today So Far. Any advise on how to approach this?

      BR,
      Ricardo

      1 Reply Last reply Reply Quote 0
      • MattFoxM
        MattFox
        last edited by MattFox

        I can see two ways of doing this, maybe three but am not sure how well maStatistics will work for you.

        1. use a meta point to have start (0) and stop (finished time in minutes) then sum the results up into an hourly period with another meta point to derive hourly percentages.

        2. do the above with a dedicated component to the same thing with a single pull of all values in a given time frame and calculate it all in one go.

        3. possibly use ma statistics to derive mean and average values/times. I do not use this directive as it has no application for me at this time and is a bit resource intensive.

        Good luck

        Fox

        Do not follow where the path may lead; go instead where there is no path.
        And leave a trail - Muriel Strode

        1 Reply Last reply Reply Quote 0
        • R
          Ralf
          last edited by Ralf

          Like Fox I would use a meta data point, run it every hour. Try this code:

          return b.past(HOUR, 1).get(true).percentage;
          

          Check the docs:

          http://docs-v4.mango-os.com/about-mango-java-script

          1 Reply Last reply Reply Quote 0
          • MattFoxM
            MattFox
            last edited by

            Thanks Ralf, by the looks of your answer, you'd use percentage, not proportion as per the docs. That or just multiply your answer by 100

            Fox

            Do not follow where the path may lead; go instead where there is no path.
            And leave a trail - Muriel Strode

            1 Reply Last reply Reply Quote 0
            • R
              Ralf
              last edited by

              A person who never made a mistake never tried anything new. - A.Einstein

              Edit and thank you Fox!

              1 Reply Last reply Reply Quote 1
              • ricardoR
                ricardo
                last edited by

                Thanks for the suggestion. I have implemented a “occupiedTime” meta data point for each occupancy sensor per your suggestion but modifying it so that it captures the hourly occupied time in the hour. However, the client would like to do further analytics by binning the occupied time into 3 groups: <1 min, <10min and >10min. Would you suggest to change the meta data point from update hourly interval to possibly update by context update?

                Also any suggestions on how to create a pie chart to present the distribution of the three binned groups?

                BR,
                Ricardo

                1 Reply Last reply Reply Quote 0
                • MattFoxM
                  MattFox
                  last edited by MattFox

                  @ricardo said in Percent Used Bar Chart:

                  Would you suggest to change the meta data point from update hourly interval to possibly update by context update?

                  No because that means your code would fire and look at the previous hour every time an update came in.

                  However, the client would like to do further analytics by binning the occupied time into 3 groups: <1 min, <10min and >10min.

                  Then I advise you look at my initial suggestion as I figured this would happen. You need this to work as occupied events, not just overall statistics. These events can then be evaluated and set a value on a datapoint that represents each timeframe. I'd advise a scripting datasource in this instance as each datapoint mentioned all relates basck to the same script.

                  Also, please read the docs and give things a go. We're not here to do your job for you.

                  The StartsAndRuntimeList object is returned by Binary and Multistate points. It contains the following properties:
                  
                  periodStartTime (integer) the start time used for the calculation
                  periodEndTime (integer) the end time used for the calculation
                  --> count (integer) count of the total number of entries  
                  startValue: the value before or exactly at the period start time
                  firstValue: the first value in the period
                  firstTime: (integer) the time of the first value
                  lastValue: the last value in the period
                  lastTime: (integer) the time of the last value
                  data: (array) the list of individual StartAndRuntime objects.
                  Each StartAndRuntime object has the following properties:
                  
                  value: (boolean for Binary, integer for Multistate) the point state to which the remaining properties apply 
                  starts: (integer) the number of times the state was entered over the period
                  --> runtime: (integer) the amount of time in milliseconds the point was in the state over the period
                  proportion: (float) the proportion of the period the point was in the state (runtime / real duration)
                  

                  Fox

                  Do not follow where the path may lead; go instead where there is no path.
                  And leave a trail - Muriel Strode

                  1 Reply Last reply Reply Quote 0
                  • ricardoR
                    ricardo
                    last edited by

                    Hi Matt,

                    Thank you for your follow up. I don't understand which initial suggestion you are referring to, but I have further explored with the idea of using a meta data point for occupiedTime in sec.

                    The following is the script for the meta data point and it is executed when the occupancy binary (0) is updated (update context checked).

                    // return o.past(HOUR, 1).get(true).runtime / (60*1000)
                    
                    curState = o.value;
                    lastState = o.lastValue(false).value;
                    
                    if(curState == false) { //falling edge only
                        if(lastState != false) {
                            duration = (o.time - o.lastValue(false).time) / 1000;
                            LOG.info(o.time);
                            LOG.info(o.lastValue(false).time);
                            return duration;
                    }
                    

                    However, this implementation has a glitch that it generates "zero" when occupancy data points goes from "false" to "true" (e.g. rising edge).

                    With this occupiedTime meta data point, I can now generate bar charts showing the total occupied time by hour and possible manipulating the pointValues to generate a new series in percent. Next I will have to figure out how to do histogram (binning) the different occupied time.

                    BR,
                    Ricardo

                    1 Reply Last reply Reply Quote 0
                    • MattFoxM
                      MattFox
                      last edited by

                      Ok, I can help expand, however, is this data inserted at set intervals or only when there is a change in state?

                      Fox

                      Do not follow where the path may lead; go instead where there is no path.
                      And leave a trail - Muriel Strode

                      1 Reply Last reply Reply Quote 0
                      • ricardoR
                        ricardo
                        last edited by

                        Hi Matt,

                        The occupancy data point's logging type is set to "When point value changes".

                        BR,
                        Ricardo

                        1 Reply Last reply Reply Quote 0
                        • MattFoxM
                          MattFox
                          last edited by MattFox

                          Roger, Ill have something for you to look at later tonight. Thank you for making an effort.
                          Generally, if you log at as the data comes in, its easier to filter with a window filter for ensuring you do not have false positives. But if you are happy with the quality of the data, I shall work with that.

                          Fox

                          Do not follow where the path may lead; go instead where there is no path.
                          And leave a trail - Muriel Strode

                          1 Reply Last reply Reply Quote 0
                          • MattFoxM
                            MattFox
                            last edited by MattFox

                            Here is something I quickly threw together to illustrate my point. When doing the pie chart, just get the length of the pointValues array for each datapoint in your timeframe,
                            Each of the variables are context points in a virtual datasource.

                            var prevState = state.lastValue(1);print(prevState)
                            if(state.value && !prevState.value)
                            {
                               timeTracker.set(0);
                               LOG.info("timestracker set")
                               
                            }
                            
                            else if(prevState.value && !state.value)
                            {
                                var prevTimestamp = timeTracker.time;
                                var newTimestamp = state.time;
                                
                                var timespent = (newTimestamp - prevTimestamp)/60000.0; //In minutes
                                timeTracker.set(timespent,newTimestamp);
                               LOG.info("time spent")
                               LOG.info(timespent)
                               
                                if(timespent<1)
                                {
                                    
                                    //LOG.info("less than one")
                                    lessThanOne.set(timespent);
                                }
                                else if(timespent>=1 && timespent<10)
                                {
                                    //LOG.info("less than ten")
                                    lessThanTen.set(timespent,newTimestamp);
                                }
                                else if(timespent>=10)
                                {
                                    //LOG.info("more than ten")
                                    moreThanTen.set(timespent,newTimestamp);
                                }
                            }
                            

                            Do not follow where the path may lead; go instead where there is no path.
                            And leave a trail - Muriel Strode

                            1 Reply Last reply Reply Quote 0
                            • ricardoR
                              ricardo
                              last edited by

                              Hi Matt,

                              Do you think we can do this dynamically with AngularJS rather than with data points? One advantage doing it dynamically is we can change the bin group dynamically. What do you think?

                              BR,
                              Ricardo

                              1 Reply Last reply Reply Quote 0
                              • MattFoxM
                                MattFox
                                last edited by

                                Of course, one of my suggestions was doing the whole thing as a reusable directive. If you can think of it, the only limitations are hardware and imagination

                                Fox

                                Do not follow where the path may lead; go instead where there is no path.
                                And leave a trail - Muriel Strode

                                1 Reply Last reply Reply Quote 0
                                • First post
                                  Last post