Skip to content

Commit

Permalink
Add NumberItem#range
Browse files Browse the repository at this point in the history
Returns a Range from and stated description, and applies units if possible

Signed-off-by: Cody Cutrer <cody@cutrer.us>
  • Loading branch information
ccutrer committed Oct 10, 2024
1 parent a329561 commit 1f5597f
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 2 deletions.
24 changes: 24 additions & 0 deletions lib/openhab/core/items/number_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,30 @@ def config_eql?(other)
super && dimension == other.dimension
end

# @!attribute [r] range
# Returns the range of values allowed for this item, as defined by its
# state description.
#
# If this item has a {#unit}, it will be applied to the result, returning
# a range of {QuantityType} instead of BigDecimal.
# @return [Range]
# @note State descriptions can be provided by bindings, defined in
# metadata, or theoretically come from other sources.
def range
return unless (sd = state_description)

# check if we have a unit, even if the item's metadata doesn't declare
# it properly
unit = self.unit || ((s = state) && s.is_a?(QuantityType) && s.unit)
min = sd.minimum&.to_d
max = sd.maximum&.to_d
return nil unless min || max

min |= unit if min && unit
max |= unit if max && unit
min..max
end

protected

# Adds the unit dimension
Expand Down
33 changes: 31 additions & 2 deletions spec/openhab/core/items/number_item_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
items.build do
group_item "Numbers" do
number_item "NumberOne", state: 0
number_item "NumberTwo", state: 70
number_item "NumberTwo", state: 70, format: "%s"
number_item "RangedNumber", range: 50..100
number_item "UnittedRangedNumber", range: 2700..6000, unit: "K"
number_item "OpenEndedNumber", range: 50.., unit: "°C"
end
number_item "NumberNull"
end
Expand All @@ -23,7 +26,12 @@

it "works with grep" do
items.build { switch_item "Switch1" }
expect(items.grep(NumberItem)).to match_array [NumberOne, NumberTwo, NumberNull]
expect(items.grep(NumberItem)).to match_array [NumberOne,
NumberTwo,
NumberNull,
RangedNumber,
UnittedRangedNumber,
OpenEndedNumber]
end

describe "#positive?" do
Expand All @@ -41,4 +49,25 @@
end
expect(Feet.state).to eq(6 | "ft")
end

describe "#range?" do
it "returns nil without a meaningful state description" do
expect(NumberOne.range).to be_nil
expect(NumberTwo.range).to be_nil
end

it "returns a value with a state description" do
expect(RangedNumber.range).to eql 50..100
end

it "returns a QuantityType as necessary" do
UnittedRangedNumber.update(3000 | "K")
expect(UnittedRangedNumber.range).to eql(2700 | "K")..(6000 | "K")
end

it "supports open ended ranges" do
OpenEndedNumber.update(75 | "°C")
expect(OpenEndedNumber.range).to eql(50 | "°C")..
end
end
end

0 comments on commit 1f5597f

Please sign in to comment.