Skip to content

Commit

Permalink
Add min/max to mapping
Browse files Browse the repository at this point in the history
Belongs to #237
  • Loading branch information
ledermann committed Sep 9, 2024
1 parent 8d99aa4 commit 4e86a6f
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 14 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ MAPPING_0_TOPIC=senec/0/ENERGY/GUI_INVERTER_POWER
MAPPING_0_MEASUREMENT=PV
MAPPING_0_FIELD=inverter_power
MAPPING_0_TYPE=integer
MAPPING_0_MIN=5
MAPPING_0_MAX=15000
#
MAPPING_1_TOPIC=senec/0/ENERGY/GUI_HOUSE_POW
MAPPING_1_MEASUREMENT=PV
Expand Down
2 changes: 2 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ MAPPING_0_TOPIC=senec/0/ENERGY/GUI_INVERTER_POWER
MAPPING_0_MEASUREMENT=PV
MAPPING_0_FIELD=inverter_power
MAPPING_0_TYPE=integer
MAPPING_0_MIN=5
MAPPING_0_MAX=15000
#
MAPPING_1_TOPIC=senec/0/ENERGY/GUI_HOUSE_POW
MAPPING_1_MEASUREMENT=PV
Expand Down
5 changes: 3 additions & 2 deletions lib/loop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,14 @@ def next_message
# There is no timestamp in the MQTT message, so we use the current time
time = Time.now

records = mapper.records_for(topic, message)

# Log all the data we received
logger.info "# Message from #{time}"
logger.info " topic = #{topic}"
logger.info " message = #{message}"

# Convert the message to records
records = mapper.records_for(topic, message)

# Log all the data we are going to push to InfluxDB
records.each do |record|
logger.info " => #{record[:measurement]}:#{record[:field]} = #{record[:value]}"
Expand Down
64 changes: 53 additions & 11 deletions lib/mapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def formatted_mapping(topic)
"#{mapping[:measurement]}:#{mapping[:field]}"
end

result += " (#{mapping[:type]})"
result += " (#{"#{mapping[:min]} ≥ " if mapping[:min]}#{mapping[:type]}#{" ≤ #{mapping[:max]}" if mapping[:max]})"
result
end
.join(', ')
Expand Down Expand Up @@ -74,24 +74,50 @@ def value_from(message, mapping)
def convert_type(message, mapping)
case mapping[:type]
when 'float'
begin
convert_float(message, mapping)
when 'integer'
convert_integer(message, mapping)
when 'boolean'
convert_boolean(message, mapping)
when 'string'
convert_string(message, mapping)
end
end

def convert_float(message, mapping)
ensure_min_max(
field: mapping[:field],
value: (begin
message.to_f
rescue StandardError
config.logger.warn "Failed to convert #{message} to float"
nil
end
when 'integer'
begin
end),
min: mapping[:min]&.to_f,
max: mapping[:max]&.to_f,
)
end

def convert_integer(message, mapping)
ensure_min_max(
field: mapping[:field],
value: (begin
message.to_f.round
rescue StandardError
config.logger.warn "Failed to convert #{message} to integer"
nil
end
when 'boolean'
%w[true ok yes on 1].include?(message.to_s.downcase)
when 'string'
message.to_s
end
end),
min: mapping[:min]&.to_i,
max: mapping[:max]&.to_i,
)
end

def convert_boolean(message, _mapping)
%w[true ok yes on 1].include?(message.to_s.downcase)
end

def convert_string(message, _mapping)
message.to_s
end

def extract_from_json(message, mapping)
Expand Down Expand Up @@ -143,4 +169,20 @@ def map_default(mapping, value)
def mappings_for(topic)
config.mappings.select { |mapping| mapping[:topic] == topic }
end

def ensure_min_max(field:, value:, min:, max:)
return value unless value && (max || min)

if max && value > max
config.logger.warn " Ignoring #{field}: #{value} exceeds maximum of #{max}"
return
end

if min && value < min
config.logger.warn " Ignoring #{field}: #{value} is below minimum of #{min}"
return
end

value
end
end
22 changes: 21 additions & 1 deletion spec/lib/mapper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
'MAPPING_0_MEASUREMENT' => 'PV',
'MAPPING_0_FIELD' => 'inverter_power',
'MAPPING_0_TYPE' => 'integer',
'MAPPING_0_MIN' => '5',
'MAPPING_0_MAX' => '15000',
#
'MAPPING_1_TOPIC' => 'senec/0/ENERGY/GUI_HOUSE_POW',
'MAPPING_1_MEASUREMENT' => 'PV',
Expand Down Expand Up @@ -176,7 +178,7 @@

it 'formats mapping' do
expect(mapper.formatted_mapping('senec/0/ENERGY/GUI_INVERTER_POWER')).to eq(
'PV:inverter_power (integer)',
'PV:inverter_power (5 ≥ integer ≤ 15000)',
)

expect(
Expand Down Expand Up @@ -443,6 +445,24 @@
expect(hash).to eq([])
end

it 'handles value < minimum' do
hash = mapper.records_for('senec/0/ENERGY/GUI_INVERTER_POWER', '-10')

expect(hash).to eq(
[],
)
expect(logger.warn_messages).to include(/Ignoring inverter_power: -10 is below minimum of 5/)
end

it 'handles value > maximum' do
hash = mapper.records_for('senec/0/ENERGY/GUI_INVERTER_POWER', '16000')

expect(hash).to eq(
[],
)
expect(logger.warn_messages).to include(/Ignoring inverter_power: 16000 exceeds maximum of 15000/)
end

it 'raises on unknown topic' do
expect do
mapper.records_for('this/is/an/unknown/topic', 'foo!')
Expand Down

0 comments on commit 4e86a6f

Please sign in to comment.