[Ovmsdev] New Metric Units

Michael Geddes frog at bunyip.wheelycreek.net
Fri Nov 11 16:54:33 HKT 2022


Ok - so here's what I have implemented for Duktape and Metrics. (I added
IsDefined() as well).
Any thoughts on this?

Noting
   OvmsMetrics.Float( {metric} ) -> Outputs metric as float (same)
   OvmsMetrics.Float( {metric}, {unit}) -> Outputs metric as float
converted to given unit  (new)
   OvmsMetrics.Value( {metric} )   -> Outputs Metric in native value (same)
   OvmsMetrics.Value( {metric} , false)   -> Outputs Metric as string and
no units (same)
   OvmsMetrics.Value( {metric} ,  {unit})  -> Outputs Metric converted to
given unit as native value. (new)
  OvmsMetrics.Value( {metric} ,  {unit}, false )  -> Outputs Metric
converted to given unit as string including any unit specifier. (new)
also  OvmsMetric.GetValues( {metric} [,{unit}] [, {converted} ] )  Adds
similar behaviour to Value() above.
also the special units '*imperial*' and '*metric*' will convert to the
associated imperial / metric version of the units as appropriate.

(function() {
   dump = function (metric) { print( metric+ " ["+(typeof metric)+"]\n"  );
}
   dump_obj = function (obj )  {
     print('--- Object ----\n')
     for (var k in obj) {
       xk = obj[k];
       print( k+':'+ xk + ' ['+typeof xk+ "]\n");
     }
   }
   dump(OvmsMetrics.Value("xiq.v.trip.consumption"));
   dump(OvmsMetrics.Value("xiq.v.trip.consumption", false));
   dump(OvmsMetrics.Value("xiq.v.trip.consumption","kmpkwh"));
   dump(OvmsMetrics.Value("xiq.v.trip.consumption", "mipkwh", false));
   dump(OvmsMetrics.AsFloat("xiq.v.trip.consumption"));
   dump(OvmsMetrics.AsFloat("xiq.v.trip.consumption","kmpkwh"));
   dump(OvmsMetrics.Value("xiq.v.trip.consumption","imperial"))
   dump(OvmsMetrics.Value("xiq.v.trip.consumption","imperial", false))
   dump_obj(OvmsMetrics.GetValues("trip", "metric"))
   dump_obj(OvmsMetrics.GetValues("trip", "imperial", false))
})();

With this output:

19.2308 [number]
19.2308 [string]
5.2 [number]
3.23112mi/kWh [string]
19.2308 [number]
5.2 [number]
309.49 [number]
309.49Wh/mi [string]
--- Object ----
v.p.trip:13 [number]
xiq.e.trip:0 [number]
xiq.e.trip.energy.recuperated:0 [number]
xiq.e.trip.energy.used:0 [number]
xiq.v.trip.consumption:19.2308 [number]
--- Object ----
v.p.trip:8.07781M [string]
xiq.e.trip:0M [string]
xiq.e.trip.energy.recuperated:0kWh [string]
xiq.e.trip.energy.used:0kWh [string]
xiq.v.trip.consumption:309.49Wh/mi [string]


On Wed, 9 Nov 2022 at 05:47, Michael Geddes <frog at bunyip.wheelycreek.net>
wrote:

> Yeah - I like HasValue.  I implemented IsDefined() but I will rename it..
> that's a much clearer name.
>
> Another thought. How about if we did this (but also with GetValues() as
> well - see the special values below)
>
> OvmsMetrics.Value("xiq.v.trip.consumption",  true)  -> 17.0582  (Number)
> OvmsMetrics.Value("xiq.v.trip.consumption",  false)  -> 17.0582  (String)
> OvmsMetrics.Value("xiq.v.trip.consumption", "mipkwh", true)  -> 3.64264
> (Number)
> OvmsMetrics.Value("xiq.v.trip.consumption", "mipkwh", false)  ->
> 3.64264Mi/kWh  (String)
>  OvmsMetrics.Value("xiq.v.trip.consumption", "native", false)  ->
> 17.0582km/kWh  (String)
>
> and
> OvmsMetrics.Value("xiq.v.trip.consumption", "imperial", false)  ->
> 3.64264Mi/kWh  (String)
>
> I have already implemented the special values 'native' (existing),
> 'imperial' and 'metric'.
>
> I was also thinking that in the future you could have 'user'. Where for
> each group of values:
> 'temperature', 'distance', 'shortdistance', 'power' etc.. you could have a
> user preference. I probably won't implement it now,.but it could be cool
> that any UI could just ask for the user defined units (rather than having a
> separate choice).
>
>
>
> //.ichael
>
> On Tue, 8 Nov 2022 at 21:57, Mark Webb-Johnson <mark at webb-johnson.net>
> wrote:
>
>> Or perhaps something more specific?
>>
>>     HasValue()
>>
>> Mark
>>
>> On 8 Nov 2022, at 9:01 PM, Michael Balzer <dexter at expeedo.de> wrote:
>>
>> Signed PGP part
>> That's basically a good approach, but be aware 'IsDefined()' has an
>> ambiguous meaning here, as with the API stem "OvmsMetrics" it would
>> naturally be expected to mean "is this metric defined", not "does this
>> metric have a defined value".
>>
>> An undefined metric currently can be derived from 'Values()' returning
>> undefined, but that's more an undocumented side effect than intended.
>>
>> Maybe 'GetDefined()' could be a better name, leveraging this behaviour,
>> i.e. returning 'undefined' for an actually undefined metric, and 'null' for
>> a defined metric without a value.
>>
>> Regards,
>> Michael
>>
>>
>> Am 08.11.22 um 13:46 schrieb Michael Geddes:
>>
>> Ah yes. Arrays - will check those.  Yeah, how about we add a 'IsDefined'
>> method to metrics instead of the null thing (it does sound like it will
>> upset too many applecarts).
>>
>> //.
>>
>> On Tue, 8 Nov 2022 at 20:35, Michael Balzer <dexter at expeedo.de> wrote:
>>
>>> Michael,
>>>
>>> looks all good to me, once again nice find with the decode argument.
>>> Adding decode to the Value() call was only for symmetry IIRC, the main use
>>> was with GetValues() (
>>> https://docs.openvehicles.com/en/latest/userguide/scripting.html#ovmsmetrics
>>> ).
>>>
>>> Don't forget to test arrays, e.g. "v.t.pressure" & "v.t.temp".
>>>
>>> Returning null for an undefined metric seems like a natural choice, but
>>> is a rather deep change, as for consistency not only the Duktape metrics
>>> API but also the Web UI metrics API would need to be changed accordingly.
>>> Unless you've got a real use case that needs that, we should be careful.
>>>
>>> Regards,
>>> Michael
>>>
>>>
>>> Am 07.11.22 um 15:00 schrieb Michael Geddes:
>>>
>>> I have figured out a bunch of stuff and have implemented the following:
>>> (having done away with needing AsFloatUnit)
>>>
>>> OvmsMetrics.Value( {metric} [, {decode}])
>>> OvmsMetrics.Value( {metric}, {unit} [,{decode}])
>>>
>>> It turns out that the [decode] flag wasn't working anyway (since the
>>> function was being registered as only having 1 param)...
>>> This way it is still really 1 function.. but I check it the second
>>> parameter is a 'boolean', and if not.. try the second form.
>>>
>>> OvmsMetrics.AsFloat( {metric} [,{unit}] )
>>>
>>> and add the function
>>>
>>> Ovms.Metrics.ValueUnit( {metric} [,{unit}])
>>> This prints the value and the unit.
>>>
>>> Here's a sample function and the output! This also shows the types of
>>> the output.
>>>
>>> (function() {
>>>    x = OvmsMetrics.Value("xiq.v.trip.consumption");
>>>    print( (typeof x) + ": "+  x+"\n"  );
>>>    x = OvmsMetrics.Value("xiq.v.trip.consumption", false);
>>>    print( (typeof x) + ": "+  x +"\n" );
>>>    x =  OvmsMetrics.Value("xiq.v.trip.consumption","kmpkwh")
>>>    print( (typeof x) + ": "+ x +"\n");
>>>    x =  OvmsMetrics.Value("xiq.v.trip.consumption", "mipkwh", false)
>>>    print( (typeof x) + ": "+ x +"\n");
>>>    x =  OvmsMetrics.ValueUnit("xiq.v.trip.consumption")
>>>    print( (typeof x) + ": "+ x +"\n");
>>>    x =  OvmsMetrics.ValueUnit("xiq.v.trip.consumption","mipkwh")
>>>    print( (typeof x) + ": "+ x +"\n");
>>>    x =  OvmsMetrics.AsFloat("xiq.v.trip.consumption")
>>>    print( (typeof x) + ": "+ x +"\n");
>>>    x =  OvmsMetrics.AsFloat("xiq.v.trip.consumption","kmpkwh")
>>>    print( (typeof x) + ": "+ x +"\n");
>>> })();
>>>
>>> number: 17.0582
>>> string: 17.0582
>>> number: 5.86227
>>> string: 3.64264
>>> string: 17.0582kWh/100km
>>> string: 3.64264mi/kWh
>>> number: 17.0582
>>> number: 5.86227
>>>
>>>
>>>
>>> It still might be an idea to use 'null' as a return value if the metrics
>>> is !IsDefined() but that would be changing the existing behaviour
>>> slightly.
>>>
>>> //.ichael
>>>
>>> On Mon, 7 Nov 2022 at 08:12, Michael Geddes <frog at bunyip.wheelycreek.net>
>>> wrote:
>>>
>>>> I've worked out what the decode flag is for and how it works, and I
>>>> think how optional params work.
>>>> I'm pretty sure I won't  need the 'AsFloatUnit' function; the unit
>>>> would be an option to AsFloat(); I'll know that soon.
>>>>
>>>> The 'Value' function is more complicated because of the optional decode
>>>> bool. I guess I could add the Unit to the end of that.
>>>>
>>>> ValueUnit could be still useful then to provide a 'Value + Unit'.
>>>>
>>>> Question:  Is there a reason we shouldn't be returning with
>>>> duk_push_null    if the metric !IsDefined()  in both AsFloat() and
>>>> Value(metric,true) cases?
>>>>
>>>> //.ichael
>>>>
>>>> On Sun, 6 Nov 2022 at 11:22, Michael Geddes <
>>>> frog at bunyip.wheelycreek.net> wrote:
>>>>
>>>>> Right, so I've implemented some stuff that seems to work quite well.
>>>>>
>>>>>
>>>>> https://github.com/openvehicles/Open-Vehicle-Monitoring-System-3/pull/764
>>>>> should be ready now after a couple of stupid mistakes slipped through.
>>>>>  This absolutely needs somebody to review it please! (There's a reason why
>>>>> I've converted some if()'s to switch() - which is that it will be used in
>>>>> the follow-up commit).
>>>>>
>>>>> The commit that will follow on from that it implements the new Units:
>>>>> kWh/100km, km/kWh  and  mi/kWh.
>>>>>
>>>>> This is a summary of what I've implemented for scripting - including
>>>>> showing the unit codes I have so far.  I've considered a few things:
>>>>>   * Should some of the longer unit codes be shortened  (eg mi, mins,
>>>>> m, ft, deg, perc)
>>>>>   * The unit codes could be much more regular and separated by dots
>>>>> eg:
>>>>>         watthours -> w.h
>>>>>         kwhp100km -> kw.h_100km or kw.h/100km
>>>>>         miph ->  mi_h or mi/h  (or should it be mph).
>>>>>         psi -> p_in.in or p/in.in or lb_in.in (yes, slightly weird,
>>>>> but predictable)
>>>>>
>>>>> *OVMS# metric units*
>>>>>           km : km
>>>>>        miles : M
>>>>>       meters : m
>>>>>         feet : ft
>>>>>      celcius : °C
>>>>>   fahrenheit : °F
>>>>>          kpa : kPa
>>>>>           pa : Pa
>>>>>          psi : psi
>>>>>        volts : V
>>>>>         amps : A
>>>>>     amphours : Ah
>>>>>           kw : kW
>>>>>          kwh : kWh
>>>>>        watts : W
>>>>>    watthours : Wh
>>>>>      seconds : Sec
>>>>>      minutes : Min
>>>>>        hours : Hour
>>>>>          utc : UTC
>>>>>      degrees : °
>>>>>         kmph : km/h
>>>>>         miph : Mph
>>>>>       kmphps : km/h/s
>>>>>       miphps : Mph/s
>>>>>         mpss : m/s²
>>>>>          dbm : dBm
>>>>>           sq : sq
>>>>>      percent : %
>>>>>        whpkm : Wh/km
>>>>>        whpmi : Wh/mi
>>>>>    kwhp100km : kWh/100km
>>>>>       kmpkwh : km/kWh
>>>>>       mipkwh : mi/kWh
>>>>>           nm : Nm
>>>>>
>>>>> *OVMS# metric unit mi*
>>>>>        miles : M
>>>>>      minutes : Min
>>>>>         miph : Mph
>>>>>       miphps : Mph/s
>>>>>        whpmi : Wh/mi
>>>>>       mipkwh : mi/kWh
>>>>>
>>>>>
>>>>> *OVMS# metric get xiq.v.trip.consumption *17.0597kWh/100km
>>>>>
>>>>> *OVMS# metric get xiq.v.trip.consumption kpkwh *5.86177km/kWh
>>>>>
>>>>> *OVMS# metric get xiq.v.trip.consumption mpkwh *3.64233mi/kWh
>>>>>
>>>>>
>>>>> *OVMS# metric set xiq.c.speed 5 miph *Metric set
>>>>>
>>>>> *OVMS# metric get xiq.c.speed *8.04673km/h
>>>>>
>>>>> *OVMS# metric get xiq.c.speed miph *5Mph
>>>>>
>>>>> And then in DukTape - there are some questions I have about the
>>>>> implementation:
>>>>> * Names of functions? Better ideas?
>>>>> * Should ValueUnit output the units?
>>>>> * In Value() there is the line    bool decode = duk_opt_boolean(ctx,
>>>>> 1, true);
>>>>>     * What does 'decode' mean here?
>>>>>     * Do I need it for ValueUnit() ?
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> * (function() {    print(
>>>>> OvmsMetrics.Value("xiq.v.trip.consumption"));    print("\n")    print(
>>>>> OvmsMetrics.ValueUnit("xiq.v.trip.consumption",""));    print("\n")
>>>>>  print( OvmsMetrics.ValueUnit("xiq.v.trip.consumption","mipkwh"));
>>>>>  print("\n")    print(
>>>>> OvmsMetrics.AsFloatUnit("xiq.v.trip.consumption","kmpkwh")); })();*
>>>>> --- Output ---
>>>>> 17.0597
>>>>> 17.0597kWh/100km
>>>>> 3.64233mi/kWh
>>>>> 5.86177
>>>>> ------
>>>>>
>>>>> The basic stuff all works - it's just quibbling over the details.. but
>>>>> let's get them right!
>>>>>
>>>>> //.ichael
>>>>>
>>>>> On Sat, 5 Nov 2022 at 20:09, Michael Geddes <
>>>>> frog at bunyip.wheelycreek.net> wrote:
>>>>>
>>>>>> Yeah - this was copied code from kia/kona and is what triggered these
>>>>>> ideas; I totally agree this shouldn't be doubled up on.
>>>>>>
>>>>>> I've got some commits centred round Metrics that I'll just check over
>>>>>> and push up ... and then I'll just have the single xiq.v.
>>>>>> trip.consumption metric (unless you have some ideas for the
>>>>>> namespace) which will be much neater.
>>>>>>
>>>>>> If it's ok with you then I might do that unit conversion proposal.
>>>>>> Would it ok if the unit specifications were the same as to the
>>>>>> programatic codes in ovms_metrics.h?
>>>>>> (kWh,   WattHours , MetersPSS )
>>>>>> I would probably add a command
>>>>>> metric units <spec>
>>>>>> to list all (matching) units and their associated Labels.
>>>>>>
>>>>>> //.ichael
>>>>>>
>>>>>> On Sat, 5 Nov 2022 at 18:48, Michael Balzer <dexter at expeedo.de>
>>>>>> wrote:
>>>>>>
>>>>>>> Michael,
>>>>>>>
>>>>>>> adding unit conversion support to the shell and Duktape commands is
>>>>>>> a good idea.
>>>>>>>
>>>>>>> Metrics are not meant to provide a user interface, they should be
>>>>>>> defined to be efficient and non-redundant.
>>>>>>>
>>>>>>> Btw, metrics names also shall not use upper case characters, and
>>>>>>> shall only use "." as a separator.
>>>>>>>
>>>>>>> Regards,
>>>>>>> Michael
>>>>>>>
>>>>>>>
>>>>>>> Am 05.11.22 um 11:22 schrieb Michael Geddes:
>>>>>>>
>>>>>>> Hi all,
>>>>>>> Some of the code I copied from Kona/Kia code had both kwh/100km and
>>>>>>> km/kwh metrics in the code as 'Other'.
>>>>>>> Adding the various power consumption Units is not particularly hard
>>>>>>> (I will have a pull-request soon) - though the conversions between them all
>>>>>>> required some thought!
>>>>>>> ... but it also made me think these two metrics that are (with the
>>>>>>> consumption units added) defined like this:
>>>>>>> m_v_trip_consumption1 =
>>>>>>> MyMetrics.InitFloat("xiq.v.trip.consumption.KWh/100km", 10, 0, kWHP100K);
>>>>>>> m_v_trip_consumption2 = MyMetrics.InitFloat("
>>>>>>> xiq.v.trip.consumption.km/kWh", 10, 0, kPkWH);
>>>>>>>
>>>>>>> These are effectively the same metric but in different units!
>>>>>>> I'm wondering if we would be better to have scripting and Duktape
>>>>>>> support for converting metrics to different unit!  This might be also quite
>>>>>>> useful for those strange countries that insist on using miles as a
>>>>>>> measurement.
>>>>>>>
>>>>>>> On top of the 'metric list' and 'metric set' we could add a 'metric
>>>>>>> get' which gets a single value.. and add unit support for get/set.
>>>>>>>
>>>>>>> I've also got a pull request that improves the precision of the
>>>>>>> km<->mi conversions and factors it out.
>>>>>>>
>>>>>>> //.ichael
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> OvmsDev mailing listOvmsDev at lists.openvehicles.comhttp://lists.openvehicles.com/mailman/listinfo/ovmsdev
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> Michael Balzer * Helkenberger Weg 9 * D-58256 Ennepetal
>>>>>>> Fon 02333 / 833 5735 * Handy 0176 / 206 989 26
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> OvmsDev mailing list
>>>>>>> OvmsDev at lists.openvehicles.com
>>>>>>> http://lists.openvehicles.com/mailman/listinfo/ovmsdev
>>>>>>>
>>>>>>
>>> _______________________________________________
>>> OvmsDev mailing listOvmsDev at lists.openvehicles.comhttp://lists.openvehicles.com/mailman/listinfo/ovmsdev
>>>
>>>
>>> --
>>> Michael Balzer * Helkenberger Weg 9 * D-58256 Ennepetal
>>> Fon 02333 / 833 5735 * Handy 0176 / 206 989 26
>>>
>>> _______________________________________________
>>> OvmsDev mailing list
>>> OvmsDev at lists.openvehicles.com
>>> http://lists.openvehicles.com/mailman/listinfo/ovmsdev
>>>
>>
>> _______________________________________________
>> OvmsDev mailing listOvmsDev at lists.openvehicles.comhttp://lists.openvehicles.com/mailman/listinfo/ovmsdev
>>
>>
>> --
>> Michael Balzer * Helkenberger Weg 9 * D-58256 Ennepetal
>> Fon 02333 / 833 5735 * Handy 0176 / 206 989 26
>>
>>
>>
>> _______________________________________________
>> OvmsDev mailing list
>> OvmsDev at lists.openvehicles.com
>> http://lists.openvehicles.com/mailman/listinfo/ovmsdev
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openvehicles.com/pipermail/ovmsdev/attachments/20221111/13e29e5f/attachment-0001.htm>


More information about the OvmsDev mailing list