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 +