[Ovmsdev] New Metric Units

Michael Balzer dexter at expeedo.de
Sat Nov 12 16:23:35 HKT 2022


I think this is pretty decent & complete now.

I also like the approach of the 'user' unit code. Moving all user unit 
prefs into the module configuration is an old todo. Currently only the 
distance unit is defined at the module side, temperature and pressure 
are App prefs.

Regards,
Michael


Am 11.11.22 um 09:54 schrieb Michael Geddes:
> 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 <http://p_in.in/> or
>>>>                     p/in.in <http://in.in/> or lb_in.in
>>>>                     <http://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
>>>>>                             <http://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 list
>>>>>                             OvmsDev at lists.openvehicles.com
>>>>>                             http://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 list
>>>>             OvmsDev at lists.openvehicles.com
>>>>             http://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 list
>>>         OvmsDev at lists.openvehicles.com
>>>         http://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 list
> OvmsDev at lists.openvehicles.com
> http://lists.openvehicles.com/mailman/listinfo/ovmsdev

-- 
Michael Balzer * Helkenberger Weg 9 * D-58256 Ennepetal
Fon 02333 / 833 5735 * Handy 0176 / 206 989 26

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openvehicles.com/pipermail/ovmsdev/attachments/20221112/824c2c3b/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 203 bytes
Desc: OpenPGP digital signature
URL: <http://lists.openvehicles.com/pipermail/ovmsdev/attachments/20221112/824c2c3b/attachment-0001.sig>


More information about the OvmsDev mailing list