# Map battery level to %

Most of my battery sensor uses battery level as % and this shows nicely in the sitemap, where icon shift colors depending on the level:

My items looks like this:

`Number Netatmo_Bedroom_Battery "Battery status [%d/5]" (Group_Netatmo,Group_Battery){netatmo="xxxxxxxxxxx#BatteryStatus"}`
`Number Netatmo_MasterBedroom_Battery "Battery status [%f]" (Group_Netatmo,Group_Battery){netatmo="xxxxxxxxxxx#BatteryStatus"}`

I also tried using mappings:
`Number Netatmo_MasterBedroom_Battery "Battery status [%f]" (Group_Netatmo,Group_Battery){netatmo="xxxxxxxxxxx#BatteryStatus"} mappings=[1=20,2=40,3=60,4=80,5=100]`

So how can I convert the number 5 to 100% so that icon shows correctly up in sitemap?

``````rule "Netatmo_Bedroom_Battery"
when
then
end
``````
1 Like

Or use a MAP tranformation

netatmobattery.map

``````0=0
1=20
2=40
3=60
4=80
5=100
``````
``````String Netatmo_MasterBedroom_Battery "Battery status [MAP(netatmobattery.map):%s]" (Group_Netatmo,Group_Battery){netatmo="xxxxxxxxxxx#BatteryStatus"}
``````

Didn’t check this, maybe you need a SCALE trasnformation because of the Number. But idea is similar.

Edit: Better use @hr3’s idea, because then you have your batterie leves identically scaled. Makes it easier in rules.

I didn’t think about doing mapping directly on the item and convert it to string

@hr3 Nice rule, I will modify to loop over all group items to only have 1 rule instead of 3…

`````` rule "Netatmo Battery"

when

then
val changedUnit = Group_Netatmo_Battery.members.filter[ItemChanged| ItemChanged.lastUpdate != null].sortBy[lastUpdate].last

end
``````
1 Like

No. Use triggeringItem and proxyitems!

``````Number NetatmoBattery1_proxy "Battery1 [%f]" (Group_Battery)
Number NetatmoBattery1_proxy "Battery2 [%f]" (Group_Battery)
Number NetatmoBattery1_proxy "Battery3 [%f]" (Group_Battery)
``````
``````rule "battery changed"
when
Item NetatmoBattery1 changed or
Item NetatmoBattery2 changed or
Item NetatmoBattery3 changed
then
var Number battery = Integer::parseInt(String::format("%s",triggeringItem.state.toString)) * 20
sendCommand(triggeringItem.name + "_proxy", battery.toString)
end
``````

Using sendCommand instead of postUpdate let’s you trigger on the change of the proxy.

Why can I not do like this, to avoid having proxyItems maybe @rlkoshak knows it ?

``````rule "battery changed"
when
then
var Number battery = Integer::parseInt(String::format("%s",triggeringItem.state.toString)) * 20
triggeringItem.postUpdate(battery.toString) // Post will not get the group to receive a new command..
end
``````

Sorry, you need proxy items for @hr3’s solution as well he just called it ‘Master’.

You do not want to have a rule fighting against a binding to set a value on the same item!

Sure its not a typo in @hr3 example? I have both MasterBedroom and Bedroom…

Whatever. Do whatever you like, but i do not suggest doing that without proxy items

It will get easier with the `Member of Group` Trigger

But as @job said when changing transforming the value in the rule don’t set it to the same Item.
This will probably lead to conflicts, but in your case this could be an exception.

1. The Item is only one way. Get info from node.
2. The rule is set to `received command`
3. The Item state is change by `postUpdate` which does not trigger the rule again.
4. The incomming and transformed value is a number

As there is no other interaction with this Item, this could work out without issues.

Looks like you got the answers but I’ll reiterate.

1. The rule will never trigger unless you explicitely send a command to Group_Netatmo_Battery. Commands send to members of Group_Netatmo_Battery only generate updates to Group_Netatmo_Battery.

2. Even if the trigger worked, triggeringItem would be set to Group_Netatmo_Battery, not the member of the Group that caused the Rule to trigger (see the new Member of trigger in the link from Josar below)

3. As Josar indicates, in this case you might be able to get away without using the proxy Item but it will be really easy to run into problems if you ever have any other rules that trigger on updates.

Personally, I think this is really a job for a JS transform rather than a Rule. Leave the Items as is and use

``````(function(i) {
if(isNaN(i) return "NA";
return i*20;
})(input)
``````

Then the label becomes “Battery status [JS(battery.js):%s %]” or something like that. No proxies, no rules.

1 Like

You have a small bracket error in the js above,

``````(function(i) {
if(isNaN(i)) return "NA";
return i*20;
})(input)
``````

However i can not get it to work properly, get the % sign to show up.

``````Text item=Netatmo_Outdoor_Battery label="Netatmo Bedroom Battery status [JS(netatmo_battery.js):%.0f %%]" icon="battery"
Text item=Netatmo_Bedroom_Battery label="Netatmo Bedroom Battery status [JS(netatmo_battery.js):%s]" icon="battery"
Text item=Netatmo_MasterBedroom_Battery label="Netatmo Master Bedroom Battery Battery status [JS(netatmo_battery.js):%f]" icon="battery"
``````

what am I missing to get the icon to show up correctly?

@Josar I like the member of option now, however I need to upgrade to OH2.2 then and that require some planning

Grrrr. I thought that the JavaScript would return an integer but it is returning a float.

``````return(Math.round(i*20));
``````

Then use `label="Netatmo Bedroom Battery status [JS(netatmo_battery.js):%s %%]"`

That will fix the icon problem.

Or not. The Icon is based on the actual state of the Item, not just its transformed label. You will either need to make new battery icons that go from 0 to 5 or you will need to use the Rule.

inch pincher! NA != NaN

``````(function(i) {
if( isNaN(i) ) return "NaN";
return( Math.round(i*20) );
})(input)
``````

I was hoping it was possible to do transform directly on the item…

It was on purpose. For the sitemap, I usually try to use something a little more human meaningful. Only a programmer would know that “NaN” means “Not a Number”, but “NA” is pretty universally understood (in English at least) as “Not Applicable.” I suppose for consistency I should return “-” so the Item looks like it is NULL, but that could cause other confusion.

Thanks for the clarification. As non native english speaker i just thought this must be an obvious error.

Most of the users on this forum are so proficient in English I sometimes let slip in too many idioms.

Hi, how can I leave battery voltage showing so battery icon to show correct level? Let’s say battery voltage is 56 volts and it is 100% battery icon, battery level 41 volts - 0%

So far I have used JS transformation:

(function(i) {
return (((parseFloat(i)/10) - 40)*100)/16 ;
})(input)

but I need voltage showing instead of percentage with correct battery icon showings…((

Transformation won’t help, icon selections are derived from real Item state before transformation.