[Ovmsdev] New Metric Units

Michael Balzer dexter at expeedo.de
Sun Dec 11 19:53:42 HKT 2022


Michael,

yes, while async getters seem to be possible by some JS voodoo, they 
probably won't work without changes to the applications.

I also don't think they would form an application code pattern we should 
encourage, as they would try to hide asynchronous operations and would 
lead to each individual metric needing to be requested (at least 
initially) by a separate async call.

Instead, please reconsider:

> Btw, in case you didn't see this already: I implemented an auto 
> subscription scheme for the 'stream' notifications -- these are by 
> default very transmission intense and can cause substantial load on 
> the module side as well. These subscriptions are managed automatically 
> for all components and plugins by the framework (which btw also takes 
> care of initializing all fragments added in the '#' container).

I designed this subscription scheme to follow the MQTT topic 
subscription scheme and be usable for any kind of subscription. 
Different data sources can be identified by the root topic. For 
notifications, it's `notify/`, for metrics, we can naturally assign 
`metrics/`. A subscription pattern `metrics/v/p/#` would for example 
subscribe to all `v.p.*` metrics.

Auto subscribing & unsubscribing is managed by the framework via the 
`data-subscriptions` attribute of a `.receiver`.

Examples:

  * https://docs.openvehicles.com/en/latest/components/ovms_webserver/docs/notifications.html
  * https://github.com/openvehicles/Open-Vehicle-Monitoring-System-3/tree/master/plugins/retools


Btw, if (!) we keep the units dictionary subscription necessity, that 
could be a subscription to `units/#`.

Regards,
Michael


Am 08.12.22 um 04:29 schrieb Michael Geddes:
> I've implemented a way of having user units of metrics come through  
> (I have metrics_user[] metrics_label[] and metrics_all[] implemented)..
> *however as far as dynamic subscription to metrics goes, I now believe 
> I can't do what I want in a backwards compatible way.*
>
> This is where I'm at:
>
> I haven't used Promises before or async/wait etc, so in my naivity, I 
> had (mistakenly it seems) thought I could define a function taking a 
> /metric code/ that
> * Sends a command to the websocket  eg /metric fetchsub 1234 v.p.trip/
> * Waits for the result coming in over the web-socket or times out
> * Returns the result to the user *directly*
> so /metric['/ /v.p.trip//'] /  (or whatever) could have an 
> accessor function that (for unsubscribed metrics) silently fetched and 
> subscribed to the metric over the websocket and returned the value.
>
> I have actually implemented the fetching bit mostly .. (a Promise 
> resolve call-back is put in a collection against a random id and when 
> the event comes back it uses the id to grab the promise function and 
> resolve with the result - and yes it has a timeout) ... except that in 
> the end, the javascript still requires a Promise to be created that 
> needs to execute its result as a call-back. I also believe I now 
> understand why that is not possible, and that fundamentally the only 
> way of doing async stuff at all ends up in some kind of call back (via 
> a Promise directly or an async function Promise)... and that the only 
> exceptions to this are within an async function (which in the end 
> still returns a Promise).
>
> This makes blocking on a metric['v.p.trip']  proxy get; function not 
> possible afaict.  Unless somebody knows a mechansim that I could use? 
> (outside of an async function, of course)
>
> I have implement the subscription model for metrics[] (which supports, 
> for example, v.p.* ) .. but without the auto-subscription it is going 
> to be less useful for plugins as far as backwards compatibility goes!
>
> you could have a call like this:
>    applyMetric('v.p.trip', (value) => {  ... put the value somewhere } )
>
>
>
> //.ichael
>
>
> On Sat, 3 Dec 2022 at 02:29, Michael Balzer <dexter at expeedo.de> wrote:
>
>     Michael,
>
>     the unit conversion JS code scheme is fine. Btw, you can optimize
>     convert to…
>
>       convert = function (from, to, value) {
>         return (unit_conversions[from + ">" + to] ||
>     unit_conversions.native)(value);
>       }
>
> Yeah - I'm assuming that the gain from not looking up unnecessarily is 
> lost from all the checking. Got it.
>
>
>>     I knew we had to keep the default webstream as it was.  I was
>>     thinking of having a different websocket Uri to trigger filtered
>>     mode (starting without sending all units).
>>     Especially, I was also considering the plugins that run from the
>>     '#' container that may not know the container had switched to
>>     user units! (so I'm not sure about option a.), so from what I can
>>     tell, the base metrics[] needs to maintain native units imho.
>>     This is also why I was looking at the 'auto-subscribe' idea since
>>     the outside container doesn't know which metrics a plugin might
>>     use, and a plugin wouldn't know to subscribe to the messages.
>
>     I think plugins will need to be updated anyway, as will all our
>     standard pages & components, as up to now all units have been
>     fixed in the UI.
>
>     In both approaches, all metrics displays (simple markup, tables,
>     charts) will need to be reworked to use the user units. Only the
>     basic markup type displays could partially be modified
>     automatically (by walking through their '.unit' elements), but any
>     extended use, even the range & energy displays in the dashboard's
>     speed gauge, will need a config-aware approach.
>
>     Charts will need to fully reconfigure, as unit labels are used
>     within different chart features, and axis limits & plotbands will
>     need to be adjusted. For this, scripts can subscribe to a new
>     'msg:units' event sent when a (re-)configuration of units is received.
>
> Yeah - I've got some classes so that different cars can specify all 
> the ranges in native units and it will generate code for the current 
> user units. I've already put this into use for all vehicle classes 
> that return a custom guage configuration.
>
>   At the moment it is still static code and we'll need to sink on a 
> (not yet implmeneted) untits changed event to reload it.. but it would 
> be simple enough to change the code generated to be dynamic 
> (especially that we now have that conversion function). Even just 
> having the user refresh the page is better than nothing at the moment 
> (it's not like the user is going to be changing the units all the time).
>
>
>     Btw, in case you didn't see this already: I implemented an auto
>     subscription scheme for the 'stream' notifications -- these are by
>     default very transmission intense and can cause substantial load
>     on the module side as well. These subscriptions are managed
>     automatically for all components and plugins by the framework
>     (which btw also takes care of initializing all fragments added in
>     the '#' container).
>
>>     We could maintain a units collection exactly as above with some
>>     proxy arrays to get at values without exceptions.  For eg:
>>     m.label["v.p.speed"]  could look up the units_ collection being
>>     maintained and return blank if the entry doesn't exist. Then
>>     m.value["v.p.speed"] would give the user unit and
>>     m.nativevalue["v.p.speed"] the native value. The latter two would
>>     use the metrics[] array or whatever mechanism we had. We could
>>     add m.text["v.p.speed"] that would give a text version with the
>>     value and unit if it had one.
>
>     That leads us to another option: we could keep the metrics
>     transmission in native values, add the units dictionary and
>     provide all conversions in Javascript using this proxy getter scheme.
>
>
> Yep - already decided to do that. It makes more sense. At the moment 
> I'm also implementing a way of starting off with no metrics supplied 
> and then adding in which ones we need.  Probably the JS is the bit I 
> need to work out on that.
>
>
>     That would keep the current metrics[] access scheme intact and
>     unchanged, so all current frontend code & plugins would continue
>     to work, using the native values as before.
>
>     The new proxy getters then can be used as the new way to access
>     metrics by anyone interested in using user units, and we can go
>     ahead by applying this to the standard pages and components.
>
>     This in combination with the 'msg:units' event to signal
>     reconfiguration should provide all we need.
>
>     We can even easily combine this with providing a command or socket
>     URL / parameter to switch the metrics into user mode. The standard
>     web frontend won't need this then, but it would make using user
>     units easy for devices without Javascript support.
>
>     Regards,
>     Michael
>
>
>     Am 28.11.22 um 00:36 schrieb Michael Geddes:
>>     Solved a couple of things.
>>     I have a 'unit conversion' code - which I current have put into a
>>     separate cpp file along with the two other C++ conversion functions.
>>     I wanted to do it this way so they are all in there together.
>>     (Does this make sense to do?).
>>
>>     mi_to_km = function(mi) { return mi * 1.609347; }
>>       km_to_mi = function(km) { return km * 0.6213700; }
>>       pkm_to_pmi = function(pkm) { return pkm * 1.609347; }
>>       pmi_to_pkm  = function(pmi) { return pmi * 0.6213700; }
>>       const feet_per_mile = 5280;
>>       var unit_conversions = {
>>             "native":             function (value) { return value;},
>>             "km>miles":           km_to_mi,
>>             "km>meters":          function (value) { return
>>     value*1000; },
>>             "km>feet":            function (value) { return
>>     km_to_mi(value) * feet_per_mile; },
>>     ......
>>             "percent>permille":   function (value) { return
>>     value*10.0; },
>>             "percent>percent":    function (value) { return value*0.10; }
>>       }
>>       convert_function = function (from, to) {
>>         var fn = undefined;
>>         if (from !== to && to !== "")
>>           fn = unit_conversions[from + ">" + to];
>>         if (fn == undefined)
>>           fn = unit_conversions.native;
>>         return fn;
>>       }
>>       convert = function (from, to, value) {
>>         var fn = convert_function(from, to);
>>         return fn(value);
>>       }
>>
>>     The other problem of looking at the uri of the websocket I have
>>     solved by creating a 'SocketCreator'  MgHandler class in
>>     the MG_EV_WEBSOCKET_HANDSHAKE_REQUEST event (and looks at the
>>     uri)... that waits for the
>>     MG_EV_WEBSOCKET_HANDSHAKE_DONE  and deletes itself.
>>
>>     int OvmsSocketCreator::HandleEvent(int ev, void *p)
>>     {
>>       if ( ev != MG_EV_WEBSOCKET_HANDSHAKE_DONE)
>>         return ev;
>>       // new websocket connection
>>       MyWebServer.CreateWebSocketHandler(m_nc, m_socket_type );
>>       m_nc = NULL;
>>       delete this;
>>       return 0;
>>     }
>>
>>     Thoughts?
>>
>>     //.ichael
>>
>>     On Sun, 27 Nov 2022 at 07:18, Michael Geddes
>>     <frog at bunyip.wheelycreek.net> wrote:
>>
>>         I knew we had to keep the default webstream as it was.  I was
>>         thinking of having a different websocket Uri to trigger
>>         filtered mode (starting without sending all units).. Though I
>>         am struggling with how to get and then pass the Uri
>>         information into the web socket constructor! The event that
>>         currently creates it doesn't seem to have access to the Uri.
>>         (see below - p is NULL for HANDSHAKE_DONE).
>>         case MG_EV_WEBSOCKET_HANDSHAKE_REQUEST:
>>               {
>>         struct http_message *hm = (struct http_message *) p; // how
>>         to pass uri info to the event below!?
>>               }
>>         break;
>>         case MG_EV_WEBSOCKET_HANDSHAKE_DONE:   // new websocket
>>         connection
>>               {
>>         MyWebServer.CreateWebSocketHandler(nc);
>>               }
>>         break;
>>
>>
>>         Especially, I was also considering the plugins that run from
>>         the '#' container that may not know the container had
>>         switched to user units! (so I'm not sure about option a.), so
>>         from what I can tell, the base metrics[] needs to maintain
>>         native units imho. This is also why I was looking at the
>>         'auto-subscribe' idea since the outside container doesn't
>>         know which metrics a plugin might use, and a plugin wouldn't
>>         know to subscribe to the messages.
>>
>>         I do like the separate units description message - though we
>>         would probably need to add the 'native' if we want to do
>>         conversions.
>>
>>         { units: {
>>           "v.p.speed": { code: "kmph", *native "kmph",* label: "km/h"
>>         }, …
>>
>>         We could maintain a units collection exactly as above with
>>         some proxy arrays to get at values without exceptions.  For eg:
>>         m.label["v.p.speed"]  could look up the units_ collection
>>         being maintained and return blank if the entry doesn't exist.
>>         Then
>>         m.value["v.p.speed"] would give the user unit and
>>         m.nativevalue["v.p.speed"] the native value. The latter two
>>         would use the metrics[] array or whatever mechanism we had.
>>         We could add m.text["v.p.speed"] that would give a text
>>         version with the value and unit if it had one.
>>
>>         I had contemplated the idea of providing a JavaScript unit
>>         conversion and was working around it. Downside is it's a
>>         third set of conversion functions to maintain... On the other
>>         hand using that we could just keep the metrics being sent as
>>         it is now, have the groups sent as you proposed (along with
>>         the native unit code) , and have the above m.value[] proxy
>>         collection use a 'touser' function assigned to the units_
>>         collection above that provided native to user conversion.
>>         We could send a javascript library constructed with just the
>>         necessary functions for the required conversions of native to
>>         user (or the whole lot.. whichever). .
>>         --
>>         var conversions = {
>>             unit: function ( value) { return value }
>>             km_miles: function (value) { return value * 0.6213700; }
>>           }
>>         We could perform the lookup when constructing the units and
>>         assign the touser property. (And have a 'unit' function that
>>         does no conversion).
>>
>>         //.ichael
>>
>>         On Sat, 26 Nov 2022, 10:43 pm Michael Balzer,
>>         <dexter at expeedo.de> wrote:
>>
>>             The metrics subscription scheme is an option, and the
>>             auto-subscribe feature via a getter is a nice idea. But I
>>             wouldn't apply that to metrics value conversions and units.
>>
>>             Also we would still need the current set of metrics to be
>>             subscribed by default, as there are also non Javascript
>>             devices (e.g. smart buttons, Wifi displays) reading the
>>             WebSocket stream.
>>
>>             My thoughts on this so far:
>>
>>             Basically the web UI, as any frontend, should adapt to
>>             unit configurations seamlessly. The web UI includes many
>>             command outputs, which already automatically switch units
>>             as configured.
>>
>>             For all practical purposes, the web UI needs to interact
>>             with users in their preferred units. Only some plugins
>>             and functions will need certain values in metric (native)
>>             units for calculations, and these will also need a simple
>>             way to convert calculation results back to user units for
>>             displaying. So I think we need to provide the unit
>>             configuration and value conversion tools in the web
>>             framework as well.
>>
>>             Proposal:
>>
>>             a) We provide a config option and a WebSocket command to
>>             switch the WebSocket metrics transmission mode to user /
>>             native units. To keep plugin compatibility, the default
>>             is 'native'.
>>
>>             b) We introduce a separate units dictionary object
>>             containing the user units for both metrics and the unit
>>             groups in their code & label representation. The units
>>             dictionary only needs to be sent initially, when new
>>             metrics are registered, when the metrics mode is changed
>>             for the current connection, and when some user unit
>>             configuration is changed, keeping the bandwidth and
>>             processing requirements low.
>>
>>             The units dictionary can combine both metrics and group
>>             units, as the unit group names are fully distinct from
>>             the metrics namespace. The transport scheme could be:
>>
>>             { units: {
>>               "v.p.speed": { code: "kmph", label: "km/h" }, …
>>               "units.distance": { code: "miles", label: "M" }, …
>>             }
>>
>>             c) In the web framework, accessing units should be as
>>             simple as possible and avoid throwing exceptions for
>>             undefined entries, so we could e.g. split these into
>>             separate code & label objects:
>>
>>             units["v.p.speed"]          = "km/h"    // consistently
>>             accompanies metrics["v.p.speed"]
>>             unitcodes["v.p.speed"]     = "kmph"
>>
>>             units["units.distance"] = "M"
>>             unitcodes["units.distance"] = "miles"
>>
>>             …or provide a getter that tests for the key existence and
>>             returns an object with empty fields as necessary.
>>
>>             With this, all metrics displays can easily be changed to
>>             display the actual unit labels instead of using fixed
>>             strings.
>>
>>             d) To provide value conversion we implement UnitConvert()
>>             in Javascript plus some wrappers that automatically look
>>             up the unit for a given metrics/group name and do the
>>             conversion to/from native units, something like…
>>
>>             var speed_kph = toNativeValue("v.p.speed");   // optional
>>             second arg to convert any data
>>             var speed_kph = metrics_native["v.p.speed"];  // using a
>>             getter
>>
>>             var trip_display = toUserValue("units.distance", 1234);
>>
>>
>>             Plugins for scientific/technical applications that depend
>>             on native (metric) units can use the new metrics
>>             transmission mode control command to force native mode.
>>             Or they can choose to migrate from "metrics[]" to
>>             "metrics_native[]".
>>
>>             The metrics mode config option can come with a note
>>             informing users that there may be some old plugins not
>>             compatible with non-native units. They can then check
>>             their plugins for this and make an informed decision on
>>             wether to enable user units and/or wether to install a
>>             specific plugin.
>>
>>             Thoughts, comments?
>>
>>             Regards,
>>             Michael
>>
>>
>>             Am 25.11.22 um 03:13 schrieb Michael Geddes:
>>>             I have an idea which might reduce traffic for
>>>             maintaining the metrics[] array in the browser and cope
>>>             with the user units.
>>>             I'll start by saying I'm not a JS developer per se.. so
>>>             a newb in JS really. Still, it's mainly just another
>>>             language so .. we'll give it a go.
>>>
>>>             Firstly:
>>>             * Implement the 'changed' filters as below for the
>>>             web-socket.. for both normal and 'user' values.
>>>             * Add a function that subscribes to a value (and returns
>>>             the current value of it)..including to 'user'
>>>             value/unitlabel.
>>>
>>>             Subscribing the normal way to the metrics over the
>>>             websocket would have the normal effect.. but we would
>>>             have a new way that would subscribe in a filtered way.
>>>
>>>             I've had a little play with the Proxy object .. so at
>>>             least I know this should work:
>>>
>>>             Have a metrics_ array that is the real associative array
>>>             for metrics[] and then define a Proxy that has (at the
>>>             least) 'get' and 'has' defined (giving us the ability to
>>>             overload /metrics['prop']/ and /"prop" in metrics
>>>             operations/).
>>>
>>>             The /get /function would return the underlying value if
>>>             it exists in the /metrics_ /array (which  is maintained
>>>             through the websocket from currently subscribed values
>>>             in the current manner).
>>>             If the value is not in the /metrics_/ array - it would
>>>             then do a subscribe+query on the websocket getting the
>>>             current value and adding it into the
>>>             /metrics_/  container. If it was unavailable then it
>>>             would put /undefined/ into the array.
>>>             The 'has' would do the get() and return true if the
>>>             value was not == /undefined/.
>>>
>>>             For the 'query the websocket' bit, I'm assuming I would
>>>             be working with promises or futures or some such: I'll
>>>             do the research and do it properly unless somebody can
>>>             help me out with it. That's the bit I was going to work
>>>             on next for the proof-of-concept.
>>>
>>>             Any immediate thoughts? Dangers?
>>>
>>>             I also noticed there was a bit that went through html
>>>             element properties and looked for metrics .. this could
>>>             be used to bulk subscribe to any metric values required
>>>             there.
>>>
>>>             //.ichael
>>>
>>>
>>>             On Thu, 17 Nov 2022 at 07:52, Michael Geddes
>>>             <frog at bunyip.wheelycreek.net> wrote:
>>>
>>>                 Yeah, ok.
>>>
>>>                 I will get all the other 'user unit' stuff done as a
>>>                 line in the sand, and then move to working out the
>>>                 web stuff.  I'm still finding my way though all the
>>>                 client side javascript, which looks very cool.. but
>>>                 I've not really done jQuery before (just enough to
>>>                 recognise it).
>>>
>>>                 Subscribing to metrics with/without user units makes
>>>                 a lot of sense. Obviously the default needs to be
>>>                 'Subscribe to all metrics but not user units' to
>>>                 maintain compatibility... but I was also thinking it
>>>                 might be nice if we could filter down even the
>>>                 normal subscribed events.
>>>                 We could have:
>>>                 * Web socket command to filter units (flag on
>>>                 websocket to say 'filtered' + flag bitset on each
>>>                 metric  similar to 'dirty')
>>>                 Then either:
>>>                 * Web socket command to turn on user units (single
>>>                 flag on that websocket)
>>>                 or
>>>                 * Web socket command to turn on user units for
>>>                 specific metrics (flag bitset on each metric)
>>>
>>>                 A parameter to the URI for the websocket could start
>>>                 the socket in 'filtered' mode to avoid the initial
>>>                 rush of metrics.
>>>
>>>                 This could drastically reduce traffic and time for
>>>                 the metrics command to execute.  It would be
>>>                 possible to also check (on a 'filtered' websocket)
>>>                 for any changes to metrics for that websocket slot
>>>                 before queueing the 'metric update' socket command.
>>>
>>>                 //.ichael
>>>
>>>
>>>                 On Thu, 17 Nov 2022 at 00:35, Michael Balzer
>>>                 <dexter at expeedo.de> wrote:
>>>
>>>                     Michael,
>>>
>>>                     I don't have much spare time currently, just
>>>                     some quick first comments: it's important to
>>>                     implement this as lightweight as possible, both
>>>                     in terms of network load and client CPU & memory
>>>                     requirements. Some devices already have issues,
>>>                     which can be seen by the "websocket overflow"
>>>                     messages. The web UI also should stay usable via
>>>                     cellular.
>>>
>>>                     My impression is the new scheme, while only
>>>                     slightly raising the client requirements, adds
>>>                     substantially to the network requirements.
>>>
>>>                     An option could be to separate the units -- or
>>>                     more, back when implementing this I thought
>>>                     about separating the names later on. Another
>>>                     question is if we normally generally need both
>>>                     the native and the converted values in the web
>>>                     UI. We maybe could provide an option to switch
>>>                     to converted values, or add an option to
>>>                     retreive or subscribe to a set of converted
>>>                     metrics on demand.
>>>
>>>                     Standard plugins like ABRP and PwrMon rely on
>>>                     getting metric (native) units, and there
>>>                     probably are non-public plugins, e.g. for
>>>                     engineering & scientific projects, that depend
>>>                     on metric units to do their calculations and
>>>                     don't need anything else. We shouldn't make life
>>>                     harder for these applications without good reason.
>>>
>>>                     Regards,
>>>                     Michael
>>>
>>>
>>>                     Am 15.11.22 um 01:26 schrieb Michael Geddes:
>>>>                     If you're ok with the [default] option I'll
>>>>                     stick with that. I mean in some ways it would
>>>>                     be nice to have a button choice
>>>>                     metric | usa | europe | asia | custom  etc and
>>>>                     I kind of considered something like that but
>>>>                     figured it's only a handful of choices.. and
>>>>                     it's an embedded device.. so simpler is better.
>>>>
>>>>                     On a related note - I was thinking how it would
>>>>                     be nice if the dashboard (etc) had access to
>>>>                     the 'user' units, so went hunting down that
>>>>                     little rabbit hole. Quite a nice mechanism with
>>>>                     the web socket updating the "metrics" object in
>>>>                     the UI.
>>>>                     This is a snippet of one idea, which is that
>>>>                     for any metric that has the possibility of a
>>>>                     user unit, we set the extra values of the
>>>>                     metric with '#unit' and '#user' appended - see
>>>>                     below. (I've chosen '#' arbitrarily.. but it
>>>>                     could be '/' or ':' or '>'  but maybe not '.' )
>>>>
>>>>                     v.p.odometer#unit: "M"
>>>>                     v.p.odometer#user: 6754.91
>>>>                     v.p.satcount: 13
>>>>                     v.p.speed: 0
>>>>                     v.p.speed#unit: "km/h"
>>>>                     v.p.speed#user: null
>>>>                     *v.p.trip: 28*
>>>>                     *v.p.trip#unit: "M"
>>>>                     v.p.trip#user: 17.3984*
>>>>
>>>>                     Then we can use this in the dials to populate
>>>>                     the values and captions! (not that I like Miles).
>>>>                     I
>>>>
>>>>                     image.png
>>>>
>>>>                     The other (similar) way was to have something
>>>>                     like the following:
>>>>                     "v.p.trip#user" : { "value": 17.3984, "unit": "M" }
>>>>                     It wouldn't make the total message any
>>>>                     shorter.. soo.. dunno.
>>>>
>>>>                     There's also some complications with setting up
>>>>                     the dials (for min/max values) - like for the
>>>>                     speed.
>>>>
>>>>                     Notice also that I'm returning null for
>>>>                     undefined values. It's nice - but I'm not sure
>>>>                     how javascript handles null when used / printed
>>>>                     etc.
>>>>
>>>>                     //.ichael
>>>>
>>>>                     On Sun, 13 Nov 2022 at 21:06, Michael Balzer
>>>>                     <dexter at expeedo.de> wrote:
>>>>
>>>>                         Michael,
>>>>
>>>>                         looks good.
>>>>
>>>>                         I think having an explicit 'default' option
>>>>                         is better than taking the 'Metric'
>>>>                         equivalent for that, as in your example you
>>>>                         already show unit alternatives within the
>>>>                         metric system to support different scalings
>>>>                         (kW / W, kWh / Wh). (Btw… waiting for
>>>>                         someone to miss Horsepower & BTU here ;-))
>>>>
>>>>                         @Patrick, I think that also answers your
>>>>                         implicit question:
>>>>>                         The default button makes it unclear what the actual setting is.
>>>>
>>>>                         The default (native unit) is always metric,
>>>>                         but you may have a mix of scalings, as we
>>>>                         try to find the one that fits best for the
>>>>                         given application when defining a metric.
>>>>                         For example the current driving energy
>>>>                         consumption is stored natively in Wh/km,
>>>>                         while the energy used or regenerated is in
>>>>                         kWh, and the odometer & trip counters are
>>>>                         in km, while the altitude ist in m.
>>>>
>>>>                         Regards,
>>>>                         Michael
>>>>
>>>>
>>>>                         Am 13.11.22 um 08:42 schrieb Michael Geddes:
>>>>>                         Greetings,
>>>>>                         so this is my idea of being able to select
>>>>>                         which units various groups use (in
>>>>>                         addition to Distance).
>>>>>                         This can be then accessed by the special
>>>>>                         'user' unit code.  (or 'metrics list -u ' )
>>>>>                         The idea of [Default] selection below 
>>>>>                         simply means storing the value to blank -
>>>>>                         meaning use whatever unit the particular
>>>>>                         metric uses. The other idea I had was to
>>>>>                         actually default it to the equivalent of
>>>>>                         'Metric' special unit code and not have
>>>>>                         the [Default] button.
>>>>>
>>>>>
>>>>>                         image.png
>>>>>
>>>>>                         Currently I've made it so that if there
>>>>>                         are more than 3 choices other than
>>>>>                         [default] that it uses the choice/combo
>>>>>                         box rather than the Radio buttons. (ie
>>>>>                         this list is auto-generated from the
>>>>>                         Metric Units table and the Metric Groups
>>>>>                         table).
>>>>>
>>>>>                         Thoughts / comments?
>>>>>
>>>>>                         //.ichael
>>>>>
>>>>>                         On Sat, 12 Nov 2022 at 17:35, Michael
>>>>>                         Geddes <frog at bunyip.wheelycreek.net> wrote:
>>>>>
>>>>>                             https://github.com/openvehicles/Open-Vehicle-Monitoring-System-3/pull/771
>>>>>
>>>>>                             I'm hoping this P/R is ok in this form
>>>>>                             (made of 5 separate commits).
>>>>>
>>>>>                             I will have a look at implementing the
>>>>>                             "user" unit code. The base for how it
>>>>>                             would work is already a part of the
>>>>>                             above pull request. I'll just look at
>>>>>                             the module configuration for distance.
>>>>>
>>>>>                             The 'power consumption' is one where
>>>>>                             it's not just a check-box.. there're 5
>>>>>                             possible choice!
>>>>>
>>>>>                             I should also add 'bar' for pressure
>>>>>                             given that for some reason that's
>>>>>                             still a thing people want.
>>>>>
>>>>>                             //.ichael
>>>>>
>>>>>                             On Sat, 12 Nov 2022 at 16:24, Michael
>>>>>                             Balzer <dexter at expeedo.de> wrote:
>>>>>
>>>>>                                 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
>>>>>>>>>
>>
>>     _______________________________________________
>>     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/20221211/304092d1/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/20221211/304092d1/attachment-0001.sig>


More information about the OvmsDev mailing list