lib/cosmos/packets/limits.rb in cosmos-3.0.1 vs lib/cosmos/packets/limits.rb in cosmos-3.1.0
- old
+ new
@@ -1,263 +1,263 @@
-# encoding: ascii-8bit
-
-# Copyright 2014 Ball Aerospace & Technologies Corp.
-# All Rights Reserved.
-#
-# This program is free software; you can modify and/or redistribute it
-# under the terms of the GNU General Public License
-# as published by the Free Software Foundation; version 3 with
-# attribution addendums as found in the LICENSE.txt
-
-require 'cosmos/packets/packet_config'
-
-module Cosmos
-
- # Limits uses PacketConfig to parse the command and telemetry
- # configuration files. It provides the API layer which other classes use to
- # access information about and manipulate limits. This includes getting,
- # setting and checking individual limit items as well as manipulating limits
- # groups.
- class Limits
- attr_reader :config
-
- LATEST_PACKET_NAME = 'LATEST'.freeze
-
- # @param config [PacketConfig] Packet configuration to use to access the
- # limits information
- def initialize(config)
- @config = config
- end
-
- # (see PacketConfig#warnings)
- def warnings
- return @config.warnings
- end
-
- # (see PacketConfig#limits_sets)
- def sets
- return @config.limits_sets
- end
-
- # @param config [PacketConfig] Set the packet configuration to a new
- # configuration. This will change everything this class returns!
- def config=(config)
- @config = config
- end
-
- # (see Cosmos::Packet#out_of_limits)
- def out_of_limits
- items = []
- @config.telemetry.each do |target_name, target_packets|
- target_packets.each do |packet_name, packet|
- new_items = packet.out_of_limits
- items.concat(new_items)
- end
- end
- return items
- end
-
- # @ignored_items [Array of Arrays] Items to ignore from the consideration
- # @return [Symbol] The overall limits state for the system
- def overall_limits_state(ignored_items = nil)
- overall = :GREEN
- limits_packet_stale = false
- items_out_of_limits = []
- # Note: If anything with limits is stale then overall limits state cannot be green or blue
- @config.telemetry.each do |target_name, target_packets|
- target_packets.each do |packet_name, packet|
- if packet.stale && !packet.limits_items.empty?
- if ignored_items
- all_ignored = true
- packet.limits_items.each do |item|
- all_ignored = false unless includes_item?(ignored_items, target_name, packet_name, item.name)
- end
- else
- all_ignored = false
- end
- limits_packet_stale = true unless all_ignored
- end
- items_out_of_limits.concat(packet.out_of_limits)
- end
- end
- items_out_of_limits.each do |target_name, packet_name, item_name, limits_state|
- next if ignored_items && includes_item?(ignored_items, target_name, packet_name, item_name)
- case overall
- # If our overall state is currently blue or green we can go to any state
- when :BLUE, :GREEN, :GREEN_HIGH, :GREEN_LOW
- overall = limits_state
- # If our overal state is yellow we can only go higher to red
- when :YELLOW, :YELLOW_HIGH, :YELLOW_LOW
- if limits_state == :RED || limits_state == :RED_HIGH || limits_state == :RED_LOW
- overall = limits_state
- break # Red is as high as we go so no need to look for more
- end
- end
- end
- overall = :GREEN if overall == :GREEN_HIGH || overall == :GREEN_LOW || overall == :BLUE
- overall = :YELLOW if overall == :YELLOW_HIGH || overall == :YELLOW_LOW
- overall = :RED if overall == :RED_HIGH || overall == :RED_LOW
- overall = :STALE if (overall == :GREEN || overall == :BLUE) && limits_packet_stale
- return overall
- end
-
- # @return [Hash(String, Array)] The defined limits groups
- def groups
- return @config.limits_groups
- end
-
- # Enables limit checking for all the items in the given group.
- #
- # @param group_name [String] Name of the group to enable
- def enable_group(group_name)
- group_upcase = group_name.to_s.upcase
- limits_group = @config.limits_groups[group_upcase]
- if limits_group
- limits_group.each do |target_name, packet_name, item_name|
- enable(target_name, packet_name, item_name)
- end
- else
- raise "LIMITS_GROUP #{group_upcase} undefined. Ensure your telemetry definition contains the line: LIMITS_GROUP #{group_upcase}"
- end
- end
-
- # Disables limit checking for all the items in the given group.
- #
- # @param group_name [String] Name of the group to disable
- def disable_group(group_name)
- group_upcase = group_name.to_s.upcase
- limits_group = @config.limits_groups[group_upcase]
- if limits_group
- limits_group.each do |target_name, packet_name, item_name|
- disable(target_name, packet_name, item_name)
- end
- else
- raise "LIMITS_GROUP #{group_upcase} undefined. Ensure your telemetry definition contains the line: LIMITS_GROUP #{group_upcase}"
- end
- end
-
- # Checks whether the limits are enabled for the specified item
- #
- # @param target_name [String] The target name
- # @param packet_name [String] The packet name. Must be a defined packet name and not 'LATEST'.
- # @param item_name [String] The item name
- def enabled?(target_name, packet_name, item_name)
- get_packet(target_name, packet_name).get_item(item_name).limits.enabled
- end
-
- # Enables limit checking for the specified item
- #
- # @param (see #enabled?)
- def enable(target_name, packet_name, item_name)
- get_packet(target_name, packet_name).enable_limits(item_name)
- end
-
- # Disables limit checking for the specified item
- #
- # @param (see #enabled?)
- def disable(target_name, packet_name, item_name)
- get_packet(target_name, packet_name).disable_limits(item_name)
- end
-
- # Get the limits for a telemetry item
- #
- # @param target_name [String] Target Name
- # @param packet_name [String] Packet Name
- # @param item_name [String] Item Name
- # @param limits_set [String or Symbol or nil] Desired Limits set. nil = current limits set
- # @return [Array<limits_set, persistence, enabled, red_low, yellow_low, red_high, yellow_high, green_low (optional), green_high (optional)] Limits information
- def get(target_name, packet_name, item_name, limits_set = nil)
- limits = get_packet(target_name, packet_name).get_item(item_name).limits
- if limits.values
- if limits_set
- limits_set = limits_set.to_s.upcase.intern
- else
- limits_set = System.limits_set
- end
- limits_for_set = limits.values[limits_set]
- if limits_for_set
- return [limits_set, limits.persistence_setting, limits.enabled, limits_for_set[0], limits_for_set[1], limits_for_set[2], limits_for_set[3], limits_for_set[4], limits_for_set[5]]
- else
- return [nil, nil, nil, nil, nil, nil, nil, nil, nil]
- end
- else
- return [nil, nil, nil, nil, nil, nil, nil, nil, nil]
- end
- end
-
- # Set the limits for a telemetry item
- #
- # @param target_name [String] Target Name
- # @param packet_name [String] Packet Name
- # @param item_name [String] Item Name
- # @param red_low [Float] Red Low Limit
- # @param yellow_low [Float] Yellow Low Limit
- # @param yellow_high [Float] Yellow High Limit
- # @param red_high [Float] Red High Limit
- # @param green_low [Float] Green Low Limit
- # @param green_high [Float] Green High Limit
- # @param limits_set [String or Symbol or nil] Desired Limits set. nil = current limits set, recommend using :CUSTOM
- # @param persistence [Integer] The number of samples the value must be out of limits before detecting a limits change. nil = Leave unchanged
- # @param enabled [Boolean] If limits monitoring is enabled for this item
- # @return [Array<limits_set, persistence, enabled, red_low, yellow_low, red_high, yellow_high, green_low (optional), green_high (optional)] Limits information
- def set(target_name, packet_name, item_name, red_low, yellow_low, yellow_high, red_high, green_low = nil, green_high = nil, limits_set = :CUSTOM, persistence = nil, enabled = true)
- packet = get_packet(target_name, packet_name)
- limits = packet.get_item(item_name).limits
- if limits_set
- limits_set = limits_set.to_s.upcase.intern
- else
- limits_set = System.limits_set
- end
- if !limits.values
- if limits_set == :DEFAULT
- limits.values = {:DEFAULT => []}
- else
- raise "DEFAULT limits must be defined for #{target_name} #{packet_name} #{item_name} before setting limits set #{limits_set}"
- end
- end
- limits_for_set = limits.values[limits_set]
- unless limits_for_set
- limits.values[limits_set] = []
- limits_for_set = limits.values[limits_set]
- end
- limits_for_set[0] = red_low.to_f
- limits_for_set[1] = yellow_low.to_f
- limits_for_set[2] = yellow_high.to_f
- limits_for_set[3] = red_high.to_f
- limits_for_set.delete_at(5) if limits_for_set[5]
- limits_for_set.delete_at(4) if limits_for_set[4]
- if green_low && green_high
- limits_for_set[4] = green_low.to_f
- limits_for_set[5] = green_high.to_f
- end
- limits.enabled = enabled
- limits.persistence_setting = Integer(persistence) if persistence
- packet.update_limits_items_cache
- @config.limits_sets << limits_set
- @config.limits_sets.uniq!
- return [limits_set, limits.persistence_setting, limits.enabled, limits_for_set[0], limits_for_set[1], limits_for_set[2], limits_for_set[3], limits_for_set[4], limits_for_set[5]]
- end
-
- protected
-
- def get_packet(target_name, packet_name)
- raise "LATEST packet not valid" if packet_name.upcase == LATEST_PACKET_NAME
- packets = @config.telemetry[target_name.to_s.upcase]
- raise "Telemetry target '#{target_name.to_s.upcase}' does not exist" unless packets
- packet = packets[packet_name.to_s.upcase]
- raise "Telemetry packet '#{target_name.to_s.upcase} #{packet_name.to_s.upcase}' does not exist" unless packet
- return packet
- end
-
- def includes_item?(array, target_name, packet_name, item_name)
- array.each do |array_target_name, array_packet_name, array_item_name|
- if ((array_target_name == target_name) && (array_packet_name == packet_name) && (array_item_name == item_name))
- return true
- end
- end
- return false
- end
-
- end # class Limits
-
-end
-
+# encoding: ascii-8bit
+
+# Copyright 2014 Ball Aerospace & Technologies Corp.
+# All Rights Reserved.
+#
+# This program is free software; you can modify and/or redistribute it
+# under the terms of the GNU General Public License
+# as published by the Free Software Foundation; version 3 with
+# attribution addendums as found in the LICENSE.txt
+
+require 'cosmos/packets/packet_config'
+
+module Cosmos
+
+ # Limits uses PacketConfig to parse the command and telemetry
+ # configuration files. It provides the API layer which other classes use to
+ # access information about and manipulate limits. This includes getting,
+ # setting and checking individual limit items as well as manipulating limits
+ # groups.
+ class Limits
+ attr_reader :config
+
+ LATEST_PACKET_NAME = 'LATEST'.freeze
+
+ # @param config [PacketConfig] Packet configuration to use to access the
+ # limits information
+ def initialize(config)
+ @config = config
+ end
+
+ # (see PacketConfig#warnings)
+ def warnings
+ return @config.warnings
+ end
+
+ # (see PacketConfig#limits_sets)
+ def sets
+ return @config.limits_sets
+ end
+
+ # @param config [PacketConfig] Set the packet configuration to a new
+ # configuration. This will change everything this class returns!
+ def config=(config)
+ @config = config
+ end
+
+ # (see Cosmos::Packet#out_of_limits)
+ def out_of_limits
+ items = []
+ @config.telemetry.each do |target_name, target_packets|
+ target_packets.each do |packet_name, packet|
+ new_items = packet.out_of_limits
+ items.concat(new_items)
+ end
+ end
+ return items
+ end
+
+ # @ignored_items [Array of Arrays] Items to ignore from the consideration
+ # @return [Symbol] The overall limits state for the system
+ def overall_limits_state(ignored_items = nil)
+ overall = :GREEN
+ limits_packet_stale = false
+ items_out_of_limits = []
+ # Note: If anything with limits is stale then overall limits state cannot be green or blue
+ @config.telemetry.each do |target_name, target_packets|
+ target_packets.each do |packet_name, packet|
+ if packet.stale && !packet.limits_items.empty?
+ if ignored_items
+ all_ignored = true
+ packet.limits_items.each do |item|
+ all_ignored = false unless includes_item?(ignored_items, target_name, packet_name, item.name)
+ end
+ else
+ all_ignored = false
+ end
+ limits_packet_stale = true unless all_ignored
+ end
+ items_out_of_limits.concat(packet.out_of_limits)
+ end
+ end
+ items_out_of_limits.each do |target_name, packet_name, item_name, limits_state|
+ next if ignored_items && includes_item?(ignored_items, target_name, packet_name, item_name)
+ case overall
+ # If our overall state is currently blue or green we can go to any state
+ when :BLUE, :GREEN, :GREEN_HIGH, :GREEN_LOW
+ overall = limits_state
+ # If our overal state is yellow we can only go higher to red
+ when :YELLOW, :YELLOW_HIGH, :YELLOW_LOW
+ if limits_state == :RED || limits_state == :RED_HIGH || limits_state == :RED_LOW
+ overall = limits_state
+ break # Red is as high as we go so no need to look for more
+ end
+ end
+ end
+ overall = :GREEN if overall == :GREEN_HIGH || overall == :GREEN_LOW || overall == :BLUE
+ overall = :YELLOW if overall == :YELLOW_HIGH || overall == :YELLOW_LOW
+ overall = :RED if overall == :RED_HIGH || overall == :RED_LOW
+ overall = :STALE if (overall == :GREEN || overall == :BLUE) && limits_packet_stale
+ return overall
+ end
+
+ # @return [Hash(String, Array)] The defined limits groups
+ def groups
+ return @config.limits_groups
+ end
+
+ # Enables limit checking for all the items in the given group.
+ #
+ # @param group_name [String] Name of the group to enable
+ def enable_group(group_name)
+ group_upcase = group_name.to_s.upcase
+ limits_group = @config.limits_groups[group_upcase]
+ if limits_group
+ limits_group.each do |target_name, packet_name, item_name|
+ enable(target_name, packet_name, item_name)
+ end
+ else
+ raise "LIMITS_GROUP #{group_upcase} undefined. Ensure your telemetry definition contains the line: LIMITS_GROUP #{group_upcase}"
+ end
+ end
+
+ # Disables limit checking for all the items in the given group.
+ #
+ # @param group_name [String] Name of the group to disable
+ def disable_group(group_name)
+ group_upcase = group_name.to_s.upcase
+ limits_group = @config.limits_groups[group_upcase]
+ if limits_group
+ limits_group.each do |target_name, packet_name, item_name|
+ disable(target_name, packet_name, item_name)
+ end
+ else
+ raise "LIMITS_GROUP #{group_upcase} undefined. Ensure your telemetry definition contains the line: LIMITS_GROUP #{group_upcase}"
+ end
+ end
+
+ # Checks whether the limits are enabled for the specified item
+ #
+ # @param target_name [String] The target name
+ # @param packet_name [String] The packet name. Must be a defined packet name and not 'LATEST'.
+ # @param item_name [String] The item name
+ def enabled?(target_name, packet_name, item_name)
+ get_packet(target_name, packet_name).get_item(item_name).limits.enabled
+ end
+
+ # Enables limit checking for the specified item
+ #
+ # @param (see #enabled?)
+ def enable(target_name, packet_name, item_name)
+ get_packet(target_name, packet_name).enable_limits(item_name)
+ end
+
+ # Disables limit checking for the specified item
+ #
+ # @param (see #enabled?)
+ def disable(target_name, packet_name, item_name)
+ get_packet(target_name, packet_name).disable_limits(item_name)
+ end
+
+ # Get the limits for a telemetry item
+ #
+ # @param target_name [String] Target Name
+ # @param packet_name [String] Packet Name
+ # @param item_name [String] Item Name
+ # @param limits_set [String or Symbol or nil] Desired Limits set. nil = current limits set
+ # @return [Array<limits_set, persistence, enabled, red_low, yellow_low, red_high, yellow_high, green_low (optional), green_high (optional)] Limits information
+ def get(target_name, packet_name, item_name, limits_set = nil)
+ limits = get_packet(target_name, packet_name).get_item(item_name).limits
+ if limits.values
+ if limits_set
+ limits_set = limits_set.to_s.upcase.intern
+ else
+ limits_set = System.limits_set
+ end
+ limits_for_set = limits.values[limits_set]
+ if limits_for_set
+ return [limits_set, limits.persistence_setting, limits.enabled, limits_for_set[0], limits_for_set[1], limits_for_set[2], limits_for_set[3], limits_for_set[4], limits_for_set[5]]
+ else
+ return [nil, nil, nil, nil, nil, nil, nil, nil, nil]
+ end
+ else
+ return [nil, nil, nil, nil, nil, nil, nil, nil, nil]
+ end
+ end
+
+ # Set the limits for a telemetry item
+ #
+ # @param target_name [String] Target Name
+ # @param packet_name [String] Packet Name
+ # @param item_name [String] Item Name
+ # @param red_low [Float] Red Low Limit
+ # @param yellow_low [Float] Yellow Low Limit
+ # @param yellow_high [Float] Yellow High Limit
+ # @param red_high [Float] Red High Limit
+ # @param green_low [Float] Green Low Limit
+ # @param green_high [Float] Green High Limit
+ # @param limits_set [String or Symbol or nil] Desired Limits set. nil = current limits set, recommend using :CUSTOM
+ # @param persistence [Integer] The number of samples the value must be out of limits before detecting a limits change. nil = Leave unchanged
+ # @param enabled [Boolean] If limits monitoring is enabled for this item
+ # @return [Array<limits_set, persistence, enabled, red_low, yellow_low, red_high, yellow_high, green_low (optional), green_high (optional)] Limits information
+ def set(target_name, packet_name, item_name, red_low, yellow_low, yellow_high, red_high, green_low = nil, green_high = nil, limits_set = :CUSTOM, persistence = nil, enabled = true)
+ packet = get_packet(target_name, packet_name)
+ limits = packet.get_item(item_name).limits
+ if limits_set
+ limits_set = limits_set.to_s.upcase.intern
+ else
+ limits_set = System.limits_set
+ end
+ if !limits.values
+ if limits_set == :DEFAULT
+ limits.values = {:DEFAULT => []}
+ else
+ raise "DEFAULT limits must be defined for #{target_name} #{packet_name} #{item_name} before setting limits set #{limits_set}"
+ end
+ end
+ limits_for_set = limits.values[limits_set]
+ unless limits_for_set
+ limits.values[limits_set] = []
+ limits_for_set = limits.values[limits_set]
+ end
+ limits_for_set[0] = red_low.to_f
+ limits_for_set[1] = yellow_low.to_f
+ limits_for_set[2] = yellow_high.to_f
+ limits_for_set[3] = red_high.to_f
+ limits_for_set.delete_at(5) if limits_for_set[5]
+ limits_for_set.delete_at(4) if limits_for_set[4]
+ if green_low && green_high
+ limits_for_set[4] = green_low.to_f
+ limits_for_set[5] = green_high.to_f
+ end
+ limits.enabled = enabled
+ limits.persistence_setting = Integer(persistence) if persistence
+ packet.update_limits_items_cache
+ @config.limits_sets << limits_set
+ @config.limits_sets.uniq!
+ return [limits_set, limits.persistence_setting, limits.enabled, limits_for_set[0], limits_for_set[1], limits_for_set[2], limits_for_set[3], limits_for_set[4], limits_for_set[5]]
+ end
+
+ protected
+
+ def get_packet(target_name, packet_name)
+ raise "LATEST packet not valid" if packet_name.upcase == LATEST_PACKET_NAME
+ packets = @config.telemetry[target_name.to_s.upcase]
+ raise "Telemetry target '#{target_name.to_s.upcase}' does not exist" unless packets
+ packet = packets[packet_name.to_s.upcase]
+ raise "Telemetry packet '#{target_name.to_s.upcase} #{packet_name.to_s.upcase}' does not exist" unless packet
+ return packet
+ end
+
+ def includes_item?(array, target_name, packet_name, item_name)
+ array.each do |array_target_name, array_packet_name, array_item_name|
+ if ((array_target_name == target_name) && (array_packet_name == packet_name) && (array_item_name == item_name))
+ return true
+ end
+ end
+ return false
+ end
+
+ end # class Limits
+
+end
+