<div dir="ltr"><div dir="auto"><div dir="auto">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).</div><div dir="auto"><div style="color:rgb(212,212,212);background-color:rgb(30,30,30);font-family:Consolas,"Courier New",monospace;line-height:19px;white-space:pre"><div style=""> <span style="color:rgb(197,134,192)">case</span> <span style="color:rgb(86,156,214)">MG_EV_WEBSOCKET_HANDSHAKE_REQUEST</span>:</div><div style=""> {</div><div style=""> <span style="color:rgb(86,156,214)">struct</span> <span style="color:rgb(78,201,176)">http_message</span> <span style="color:rgb(86,156,214)">*</span><span style="color:rgb(156,220,254)">hm</span> = (<span style="color:rgb(86,156,214)">struct</span> <span style="color:rgb(78,201,176)">http_message</span> <span style="color:rgb(86,156,214)">*</span>) <span style="color:rgb(156,220,254)">p</span>; // how to pass uri info to the event below!?</div><div style=""> }</div><div style=""> <span style="color:rgb(197,134,192)">break</span>;</div><div style=""> <span style="color:rgb(197,134,192)">case</span> <span style="color:rgb(86,156,214)">MG_EV_WEBSOCKET_HANDSHAKE_DONE</span>:<span style="color:rgb(106,153,85)"> // new websocket connection</span></div><div style=""> {</div><div style=""> <span style="color:rgb(156,220,254)">MyWebServer</span>.<span style="color:rgb(220,220,170)">CreateWebSocketHandler</span>(<span style="color:rgb(156,220,254)">nc</span>);</div><div style=""> }</div><div style=""> <span style="color:rgb(197,134,192)">break</span>;</div><br></div></div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">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.</div><div dir="auto"><br></div><div>I do like the separate units description message - though we would probably need to add the 'native' if we want to do conversions.</div><font face="monospace"><font face="monospace"><br class="gmail-Apple-interchange-newline">{ units: {<br> "v.p.speed": { </font></font><font face="monospace"><font face="monospace"><font face="monospace"><font face="monospace">code: "kmph", <b>native "kmph",</b> </font></font>label: "km/h" }, …</font></font><br><div><br></div><div>We could maintain a units collection exactly as above with some proxy arrays to get at values without exceptions. For eg: </div><div>m.label["v.p.speed"] could look up the units_ collection being maintained and return blank if the entry doesn't exist. Then</div><div>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.</div><div dir="auto"><br></div><div>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.</div><div><div dir="auto"> </div><div>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). .</div><div>--</div> <font face="monospace">var conversions = {</font></div><div><font face="monospace"> unit: function ( value) { return value }<br> km_miles: function (value) { return value * 0.6213700; }</font></div><div><font face="monospace"> }</font><div>We could perform the lookup when constructing the units and assign the touser property. (And have a 'unit' function that does no conversion).</div></div><div dir="auto"><br>//.ichael <br><br><div class="gmail_quote" dir="auto"><div dir="ltr" class="gmail_attr">On Sat, 26 Nov 2022, 10:43 pm Michael Balzer, <<a href="mailto:dexter@expeedo.de" target="_blank">dexter@expeedo.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>
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.<br>
<br>
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.<br>
<br>
My thoughts on this so far:<br>
<br>
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.<br>
<br>
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.<br>
<br>
Proposal:<br>
<br>
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'.<br>
<br>
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.<br>
<br>
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:<br>
<br>
<font face="monospace"><font face="monospace">{ units: {<br>
"v.p.speed": { </font></font><font face="monospace"><font face="monospace"><font face="monospace"><font face="monospace">code:
"kmph", </font></font>label: "km/h" }, …<br>
"</font></font><font face="monospace"><font face="monospace"><font face="monospace">units.distance": { </font></font></font><font face="monospace"><font face="monospace"><font face="monospace"><font face="monospace"><font face="monospace"><font face="monospace"><font face="monospace">code: "</font></font></font></font></font></font></font><font face="monospace"><font face="monospace"><font face="monospace"><font face="monospace"><font face="monospace"><font face="monospace"><font face="monospace"><font face="monospace">miles</font>", </font></font>label:
"M" }, …<br>
}<br>
</font></font></font><br>
</font></font>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:<br>
<font face="monospace"><font face="monospace"><br>
units["v.p.speed"] = "km/h" // consistently
accompanies metrics["v.p.speed"]<br>
</font></font><font face="monospace"><font face="monospace"><font face="monospace">unit</font></font></font><font face="monospace"><font face="monospace"><font face="monospace"><font face="monospace"><font face="monospace"><font face="monospace">codes</font></font></font>["v.p.speed"]
= "kmph"<br>
<br>
</font></font></font><font face="monospace">units["units.distance"]
= "M"</font><br>
<font face="monospace">unitcodes["units.distance"] = "miles"</font><br>
<br>
…or provide a getter that tests for the key existence and returns an
object with empty fields as necessary.<br>
<br>
With this, all metrics displays can easily be changed to display the
actual unit labels instead of using fixed strings.<br>
<br>
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…<br>
<br>
<font face="monospace">var speed_kph =
toNativeValue("v.p.speed"); // optional second arg to convert
any data<br>
</font><font face="monospace"><font face="monospace"><font face="monospace">var speed_kph =
metrics_native["v.p.speed"]; // using a getter<br>
<br>
</font></font>var trip_display = toUserValue("units.distance",
1234);<br>
<br>
</font><br>
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[]".<br>
<br>
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.<br>
<br>
Thoughts, comments?<br>
<br>
Regards,<br>
Michael<br>
<br>
<br>
<div>Am 25.11.22 um 03:13 schrieb Michael
Geddes:<br>
</div>
<blockquote type="cite">
<div dir="ltr">
<div dir="ltr">I have an idea which might reduce traffic for
maintaining the metrics[] array in the browser and cope with
the user units.</div>
<div dir="ltr">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. <br>
<div><br>
</div>
<div>Firstly:</div>
<div>* Implement the 'changed' filters as below for the
web-socket.. for both normal and 'user' values.</div>
<div>* Add a function that subscribes to a value (and returns
the current value of it)..including to 'user'
value/unitlabel.</div>
<div><br>
</div>
<div>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.</div>
<div><br>
</div>
<div>I've had a little play with the Proxy object .. so at
least I know this should work:</div>
<div><br>
</div>
<div>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 <i>metrics['prop']</i> and <i>"prop" in metrics
operations</i>).</div>
<div><br>
</div>
<div>The <i>get </i>function would return the underlying
value if it exists in the <i>metrics_ </i>array (which is
maintained through the websocket from currently subscribed
values in the current manner). </div>
<div>If the value is not in the <i>metrics_</i> array - it
would then do a subscribe+query on the websocket getting the
current value and adding it into the
<i>metrics_</i> container. If it was unavailable then it
would put <i>undefined</i> into the array.<br>
</div>
<div>The 'has' would do the get() and return true if the value
was not == <i>undefined</i>. </div>
<div><br>
<div>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.</div>
<div><br>
</div>
<div>Any immediate thoughts? Dangers?</div>
<div><br>
</div>
<div>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.</div>
<div><br>
</div>
<div>//.ichael</div>
<div><br>
</div>
</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Thu, 17 Nov 2022 at
07:52, Michael Geddes <<a href="mailto:frog@bunyip.wheelycreek.net" rel="noreferrer" target="_blank">frog@bunyip.wheelycreek.net</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="ltr">
<div dir="ltr">Yeah, ok.<br>
</div>
<div dir="ltr"><br>
</div>
<div>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).</div>
<div><br>
</div>
<div>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.</div>
<div>We could have:</div>
<div>* Web socket command to filter units (flag on
websocket to say 'filtered' + flag bitset on each
metric similar to 'dirty')<br>
</div>
<div>Then either:</div>
<div>* Web socket command to turn on user units (single
flag on that websocket)</div>
<div>or </div>
<div>* Web socket command to turn on user units for
specific metrics (flag bitset on each metric)</div>
<div><br>
</div>
<div>A parameter to the URI for the websocket could start
the socket in 'filtered' mode to avoid the initial rush
of metrics.</div>
<div><br>
</div>
<div>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.</div>
<div><br>
</div>
<div>//.ichael</div>
<div><br>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Thu, 17 Nov 2022 at
00:35, Michael Balzer <<a href="mailto:dexter@expeedo.de" rel="noreferrer" target="_blank">dexter@expeedo.de</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div> Michael,<br>
<br>
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.<br>
<br>
My impression is the new scheme, while only slightly
raising the client requirements, adds substantially
to the network requirements.<br>
<br>
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.<br>
<br>
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.<br>
<br>
Regards,<br>
Michael<br>
<br>
<br>
<div>Am 15.11.22 um 01:26 schrieb Michael Geddes:<br>
</div>
<blockquote type="cite">
<div dir="ltr">
<div dir="ltr">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</div>
<div dir="ltr">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.</div>
<div dir="ltr"><br>
</div>
<div>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. </div>
<div>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
'.' )</div>
<br>
v.p.odometer#unit: "M"<br>
v.p.odometer#user: 6754.91<br>
v.p.satcount: 13<br>
v.p.speed: 0<br>
v.p.speed#unit: "km/h"<br>
v.p.speed#user: null<br>
<b>v.p.trip: 28</b><br>
<b>v.p.trip#unit: "M"<br>
v.p.trip#user: 17.3984</b>
<div><br>
</div>
<div>Then we can use this in the dials to
populate the values and captions! (not that I
like Miles).</div>
<div>I</div>
<div>
<div><br>
</div>
<div><img src="cid:part1.hUY88jFA.gq5PxptW@expeedo.de" alt="image.png" width="217" height="136"><br>
</div>
<div><br>
</div>
<div>The other (similar) way was to have
something like the following:</div>
<div>"v.p.trip#user" : { "value": 17.3984,
"unit": "M" }</div>
<div>It wouldn't make the total message any
shorter.. soo.. dunno.</div>
<div><br>
</div>
<div>There's also some complications with
setting up the dials (for min/max values) -
like for the speed.</div>
<div><br>
</div>
<div>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.</div>
<div><br>
</div>
<div>//.ichael</div>
<div><br>
</div>
<div>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Sun,
13 Nov 2022 at 21:06, Michael Balzer
<<a href="mailto:dexter@expeedo.de" rel="noreferrer" target="_blank">dexter@expeedo.de</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div> Michael,<br>
<br>
looks good.<br>
<br>
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 ;-))<br>
<br>
@Patrick, I think that also answers
your implicit question:<br>
<blockquote type="cite">
<pre>The default button makes it unclear what the actual setting is.
</pre>
</blockquote>
<br>
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.<br>
<br>
Regards,<br>
Michael<br>
<br>
<br>
<div>Am 13.11.22 um 08:42 schrieb
Michael Geddes:<br>
</div>
<blockquote type="cite">
<div dir="ltr">Greetings,<br>
<div>so this is my idea of being
able to select which units
various groups use (in addition
to Distance).</div>
<div>This can be then accessed by
the special 'user' unit code.
(or 'metrics list -u ' )</div>
<div>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.</div>
<div><br>
</div>
<div><br>
</div>
<img src="cid:part2.FrNjkKn2.Bls3txd0@expeedo.de" alt="image.png" width="472" height="395"><br>
<div><br>
</div>
<div>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).</div>
<div><br>
</div>
<div>Thoughts / comments?</div>
<div><br>
</div>
<div>//.ichael </div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On
Sat, 12 Nov 2022 at 17:35,
Michael Geddes <<a href="mailto:frog@bunyip.wheelycreek.net" rel="noreferrer" target="_blank">frog@bunyip.wheelycreek.net</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="ltr">
<div dir="ltr"><a href="https://github.com/openvehicles/Open-Vehicle-Monitoring-System-3/pull/771" rel="noreferrer" target="_blank">https://github.com/openvehicles/Open-Vehicle-Monitoring-System-3/pull/771</a><br>
<div><br>
</div>
<div>I'm hoping this P/R is
ok in this form (made of 5
separate commits).</div>
<div><br>
</div>
<div>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.</div>
<div><br>
</div>
<div>The 'power consumption'
is one where it's not just
a check-box.. there're 5
possible choice!</div>
<div><br>
</div>
<div>I should also add 'bar'
for pressure given that
for some reason that's
still a thing people want.</div>
<div><br>
</div>
<div>//.ichael</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Sat,
12 Nov 2022 at 16:24,
Michael Balzer <<a href="mailto:dexter@expeedo.de" rel="noreferrer" target="_blank">dexter@expeedo.de</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div> I think this is
pretty decent &
complete now.<br>
<br>
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.<br>
<br>
Regards,<br>
Michael<br>
<br>
<br>
<div>Am 11.11.22 um
09:54 schrieb Michael
Geddes:<br>
</div>
<blockquote type="cite">
<div dir="ltr">Ok - so
here's what I have
implemented for
Duktape and Metrics.
(I added IsDefined()
as well).
<div>Any thoughts on
this?<br>
<div><br>
<div>Noting</div>
<div>
OvmsMetrics.Float(
{metric} )
-> Outputs
metric as
float (same)</div>
<div>
OvmsMetrics.Float(
{metric},
{unit}) ->
Outputs metric
as float
converted to
given unit
(new)</div>
<div>
OvmsMetrics.Value(
{metric} )
-> Outputs
Metric in
native value
(same)</div>
<div>
OvmsMetrics.Value(
{metric} ,
false) ->
Outputs Metric
as string and
no units
(same) </div>
OvmsMetrics.Value(
{metric} ,
{unit}) ->
Outputs Metric
converted to
given unit as
native value.
(new)
<div>
OvmsMetrics.Value(
{metric} ,
{unit}, false
) ->
Outputs Metric
converted to
given unit as
string
including any
unit
specifier.
(new)
<div>also
OvmsMetric.GetValues(
{metric}
[,{unit}] [,
{converted} ]
) Adds
similar
behaviour to
Value() above.</div>
<div>also the
special units
'<b>imperial</b>'
and '<b>metric</b>'
will convert
to the
associated
imperial /
metric version
of the units
as
appropriate.</div>
<div><br>
<div><font face="monospace">(function()
{<br>
dump =
function
(metric) {
print( metric+
" ["+(typeof
metric)+"]\n"
); }<br>
dump_obj =
function (obj
) {<br>
print('---
Object
----\n')<br>
for (var
k in obj) {<br>
xk =
obj[k];<br>
print(
k+':'+ xk + '
['+typeof xk+
"]\n");<br>
}<br>
}<br>
dump(OvmsMetrics.Value("xiq.v.trip.consumption"));<br>
dump(OvmsMetrics.Value("xiq.v.trip.consumption",
false));<br>
dump(OvmsMetrics.Value("xiq.v.trip.consumption","kmpkwh"));<br>
dump(OvmsMetrics.Value("xiq.v.trip.consumption",
"mipkwh",
false));<br>
dump(OvmsMetrics.AsFloat("xiq.v.trip.consumption"));<br>
dump(OvmsMetrics.AsFloat("xiq.v.trip.consumption","kmpkwh"));<br>
dump(OvmsMetrics.Value("xiq.v.trip.consumption","imperial"))<br>
dump(OvmsMetrics.Value("xiq.v.trip.consumption","imperial",
false))<br>
dump_obj(OvmsMetrics.GetValues("trip",
"metric"))<br>
dump_obj(OvmsMetrics.GetValues("trip",
"imperial",
false))<br>
})();<br>
</font></div>
<div><br>
</div>
<div>With this
output:</div>
<div>
<div>
<pre id="m_-3595551468962657953m_-358274377416053507m_-7644593744426345619m_-5441616086226233372m_8405494616978842232m_-5904723395924573806m_1733173679174480992m_-138117451584655546m_5484224439251412587gmail-output" style="box-sizing:border-box;overflow:auto;font-family:ui-monospace,"Cascadia Mono","Segoe UI Mono",Hack,"Source Code Pro","Roboto Mono",Menlo,Monaco,Consolas,monospace;font-size:13px;padding:9.5px;margin-top:0px;margin-bottom:10px;line-height:1.42857;color:rgb(0,34,0);word-break:break-all;background-color:rgb(245,245,245);border:1px solid rgb(204,204,204);border-radius:4px;height:406px;white-space:pre-wrap">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]</pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On
Wed, 9 Nov 2022 at
05:47, Michael
Geddes <<a href="mailto:frog@bunyip.wheelycreek.net" rel="noreferrer" target="_blank">frog@bunyip.wheelycreek.net</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="ltr">Yeah
- I like
HasValue. I
implemented
IsDefined() but
I will rename
it.. that's a
much clearer
name.
<div><br>
</div>
<div>Another
thought. How
about if we
did this (but
also with
GetValues() as
well - see the
special values
below) </div>
<div><br>
<div>OvmsMetrics.Value("xiq.v.trip.consumption",
true) -> <span style="background-color:rgb(245,245,245);color:rgb(0,34,0);font-family:ui-monospace,"Cascadia Mono","Segoe UI Mono",Hack,"Source Code Pro","Roboto Mono",Menlo,Monaco,Consolas,monospace;font-size:13px;white-space:pre-wrap">17.0582</span><span style="background-color:rgb(245,245,245);color:rgb(0,34,0);font-family:ui-monospace,"Cascadia Mono","Segoe UI Mono",Hack,"Source Code Pro","Roboto Mono",Menlo,Monaco,Consolas,monospace;font-size:13px;white-space:pre-wrap"> (Number)</span><br>
</div>
<div>
<div>OvmsMetrics.Value("xiq.v.trip.consumption",
false)
-> <span style="background-color:rgb(245,245,245);color:rgb(0,34,0);font-family:ui-monospace,"Cascadia Mono","Segoe UI Mono",Hack,"Source Code Pro","Roboto Mono",Menlo,Monaco,Consolas,monospace;font-size:13px;white-space:pre-wrap">17.0582</span><span style="background-color:rgb(245,245,245);color:rgb(0,34,0);font-family:ui-monospace,"Cascadia Mono","Segoe UI Mono",Hack,"Source Code Pro","Roboto Mono",Menlo,Monaco,Consolas,monospace;font-size:13px;white-space:pre-wrap"> (String)</span></div>
</div>
</div>
<div>OvmsMetrics.Value("xiq.v.trip.consumption",
"mipkwh",
true) -> <span style="background-color:rgb(245,245,245);color:rgb(0,34,0);font-family:ui-monospace,"Cascadia Mono","Segoe UI Mono",Hack,"Source Code Pro","Roboto Mono",Menlo,Monaco,Consolas,monospace;font-size:13px;white-space:pre-wrap">3.64264</span><span style="background-color:rgb(245,245,245);color:rgb(0,34,0);font-family:ui-monospace,"Cascadia Mono","Segoe UI Mono",Hack,"Source Code Pro","Roboto Mono",Menlo,Monaco,Consolas,monospace;font-size:13px;white-space:pre-wrap"> (Number)</span><br>
</div>
<div>OvmsMetrics.Value("xiq.v.trip.consumption",
"mipkwh",
false) -> <span style="background-color:rgb(245,245,245);color:rgb(0,34,0);font-family:ui-monospace,"Cascadia Mono","Segoe UI Mono",Hack,"Source Code Pro","Roboto Mono",Menlo,Monaco,Consolas,monospace;font-size:13px;white-space:pre-wrap">3.64264Mi/kWh</span><span style="background-color:rgb(245,245,245);color:rgb(0,34,0);font-family:ui-monospace,"Cascadia Mono","Segoe UI Mono",Hack,"Source Code Pro","Roboto Mono",Menlo,Monaco,Consolas,monospace;font-size:13px;white-space:pre-wrap"> (String)</span><br>
</div>
<div> OvmsMetrics.Value("xiq.v.trip.consumption",
"native",
false) -> <span style="font-size:13px;background-color:rgb(245,245,245);color:rgb(0,34,0);font-family:ui-monospace,"Cascadia Mono","Segoe UI Mono",Hack,"Source Code Pro","Roboto Mono",Menlo,Monaco,Consolas,monospace;white-space:pre-wrap">17.0582km/kWh</span><span style="font-size:13px;background-color:rgb(245,245,245);color:rgb(0,34,0);font-family:ui-monospace,"Cascadia Mono","Segoe UI Mono",Hack,"Source Code Pro","Roboto Mono",Menlo,Monaco,Consolas,monospace;white-space:pre-wrap"> (String)</span> </div>
<div><br>
</div>
<div>and</div>
<div>
<div>OvmsMetrics.Value("xiq.v.trip.consumption",
"imperial",
false) -> <span style="background-color:rgb(245,245,245);color:rgb(0,34,0);font-family:ui-monospace,"Cascadia Mono","Segoe UI Mono",Hack,"Source Code Pro","Roboto Mono",Menlo,Monaco,Consolas,monospace;font-size:13px;white-space:pre-wrap">3.64264Mi/kWh</span><span style="background-color:rgb(245,245,245);color:rgb(0,34,0);font-family:ui-monospace,"Cascadia Mono","Segoe UI Mono",Hack,"Source Code Pro","Roboto Mono",Menlo,Monaco,Consolas,monospace;font-size:13px;white-space:pre-wrap"> (String)</span><br>
</div>
</div>
<div><br>
</div>
<div>I have
already
implemented
the special
values
'native'
(existing),
'imperial' and
'metric'. </div>
<div><br>
</div>
<div>I was also
thinking that
in the future
you could have
'user'. Where
for each group
of values:</div>
<div>'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).</div>
<div><br>
</div>
<div><br>
</div>
<div><br>
</div>
<div>//.ichael</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On
Tue, 8 Nov
2022 at 21:57,
Mark
Webb-Johnson
<<a href="mailto:mark@webb-johnson.net" rel="noreferrer" target="_blank">mark@webb-johnson.net</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<div dir="ltr" style="color:rgb(0,0,0)">Or perhaps something more specific?</div>
<div dir="ltr" style="color:rgb(0,0,0)"><br>
</div>
<div dir="ltr" style="color:rgb(0,0,0)"> HasValue()</div>
<div dir="ltr" style="color:rgb(0,0,0)"><br>
</div>
<div dir="ltr" style="color:rgb(0,0,0)">Mark</div>
<div><br>
<blockquote type="cite">
<div>On 8 Nov
2022, at 9:01
PM, Michael
Balzer <<a href="mailto:dexter@expeedo.de" rel="noreferrer" target="_blank">dexter@expeedo.de</a>>
wrote:</div>
<br>
<div>
<div>
<div>
<div>Signed
PGP part</div>
<div>
<div> 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".<br>
<br>
An undefined
metric
currently can
be derived
from
'Values()'
returning
undefined, but
that's more an
undocumented
side effect
than intended.<br>
<br>
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.<br>
<br>
Regards,<br>
Michael<br>
<br>
<br>
<div>Am
08.11.22 um
13:46 schrieb
Michael
Geddes:<br>
</div>
<blockquote type="cite">
<div dir="ltr">
<div>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).</div>
<div><br>
</div>
<div>//.</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Tue, 8 Nov 2022 at 20:35, Michael Balzer <<a href="mailto:dexter@expeedo.de" rel="noreferrer" target="_blank">dexter@expeedo.de</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div> Michael,<br>
<br>
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() (<a href="https://docs.openvehicles.com/en/latest/userguide/scripting.html#ovmsmetrics" rel="noreferrer" target="_blank">https://docs.openvehicles.com/en/latest/userguide/scripting.html#ovmsmetrics</a>).<br>
<br>
Don't forget
to test
arrays, e.g.
"v.t.pressure"
&
"v.t.temp".<br>
<br>
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.<br>
<br>
Regards,<br>
Michael<br>
<br>
<br>
<div>Am
07.11.22 um
15:00 schrieb
Michael
Geddes:<br>
</div>
<blockquote type="cite">
<div dir="ltr">
<div dir="ltr">I
have figured
out a bunch of
stuff and have
implemented
the following:
(having done
away with
needing
AsFloatUnit)
<div><br>
</div>
<div>OvmsMetrics.Value(
{metric} [,
{decode}])</div>
<div>OvmsMetrics.Value(
{metric},
{unit}
[,{decode}])</div>
<div><br>
</div>
<div>It turns
out that the
[decode] flag
wasn't working
anyway (since
the function
was being
registered as
only having 1
param)...</div>
<div>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. </div>
<div><br>
</div>
<div>OvmsMetrics.AsFloat(
{metric}
[,{unit}] )</div>
<div><br>
</div>
<div>and add
the function</div>
<div><br>
</div>
<div>Ovms.Metrics.ValueUnit(
{metric}
[,{unit}]) </div>
<div>This
prints the
value and the
unit.</div>
<div><br>
</div>
<div>Here's a
sample
function and
the output!
This also
shows the
types of the
output.</div>
<div><br>
</div>
<div><font face="monospace">(function()
{<br>
x =
OvmsMetrics.Value("xiq.v.trip.consumption");<br>
print(
(typeof x) +
": "+ x+"\n"
);<br>
x =
OvmsMetrics.Value("xiq.v.trip.consumption",
false);<br>
print(
(typeof x) +
": "+ x +"\n"
);<br>
x =
OvmsMetrics.Value("xiq.v.trip.consumption","kmpkwh")<br>
print(
(typeof x) +
": "+ x
+"\n");<br>
x =
OvmsMetrics.Value("xiq.v.trip.consumption",
"mipkwh",
false) <br>
print(
(typeof x) +
": "+ x
+"\n");<br>
x =
OvmsMetrics.ValueUnit("xiq.v.trip.consumption")<br>
print(
(typeof x) +
": "+ x
+"\n");<br>
x =
OvmsMetrics.ValueUnit("xiq.v.trip.consumption","mipkwh")<br>
print(
(typeof x) +
": "+ x
+"\n");<br>
x =
OvmsMetrics.AsFloat("xiq.v.trip.consumption")<br>
print(
(typeof x) +
": "+ x
+"\n");<br>
x =
OvmsMetrics.AsFloat("xiq.v.trip.consumption","kmpkwh")<br>
print(
(typeof x) +
": "+ x
+"\n");<br>
})();</font><br>
</div>
<div><br>
</div>
<div>
<pre id="m_-3595551468962657953m_-358274377416053507m_-7644593744426345619m_-5441616086226233372m_8405494616978842232m_-5904723395924573806m_1733173679174480992m_-138117451584655546m_5484224439251412587m_-6783916119872647666m_7514939671383041717m_-2249740601380801512gmail-output" style="box-sizing:border-box;overflow:auto;font-family:ui-monospace,"Cascadia Mono","Segoe UI Mono",Hack,"Source Code Pro","Roboto Mono",Menlo,Monaco,Consolas,monospace;font-size:13px;padding:9.5px;margin-top:0px;margin-bottom:10px;line-height:1.42857;color:rgb(0,34,0);word-break:break-all;background-color:rgb(245,245,245);border:1px solid rgb(204,204,204);border-radius:4px;height:165px;white-space:pre-wrap">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</pre>
</div>
<div><br>
</div>
<div><br>
</div>
<div>It still
might be an
idea to use
'null' as a
return value
if the metrics
is<font face="monospace">
!IsDefined() </font><font face="arial,
sans-serif">but
that would be
changing the
existing
behaviour
slightly.</font></div>
<div><font face="arial,
sans-serif"><br>
</font></div>
<div><font face="arial,
sans-serif">//.ichael</font></div>
<div><br>
</div>
</div>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Mon, 7 Nov 2022 at 08:12, Michael Geddes <<a href="mailto:frog@bunyip.wheelycreek.net" rel="noreferrer" target="_blank">frog@bunyip.wheelycreek.net</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="ltr">I've
worked out
what the
decode flag is
for and how it
works, and I
think how
optional
params work. <br>
<div>I'm
pretty sure I
won't need
the
'AsFloatUnit'
function; the
unit would be
an option to
AsFloat();
I'll know that
soon.</div>
<div><br>
</div>
<div>The
'Value'
function is
more
complicated
because of the
optional
decode bool. I
guess I could
add the Unit
to the end of
that.</div>
<div><br>
</div>
<div>ValueUnit
could be still
useful then to
provide a
'Value +
Unit'.</div>
<div><br>
</div>
<div>Question:
Is there a
reason we
shouldn't be
returning
with <span style="color:rgb(220,220,170);background-color:rgb(30,30,30);font-family:Consolas,"Courier New",monospace;font-size:14px;white-space:pre-wrap">duk_push_null</span>
if the
metric
!IsDefined()
in both
AsFloat() and
Value(metric,true) cases?</div>
<div><br>
</div>
<div>//.ichael</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Sun, 6 Nov 2022 at 11:22, Michael Geddes <<a href="mailto:frog@bunyip.wheelycreek.net" rel="noreferrer" target="_blank">frog@bunyip.wheelycreek.net</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="ltr">
<div>Right, so
I've
implemented
some stuff
that seems to
work quite
well. <br>
</div>
<div><br>
</div>
<div><a href="https://github.com/openvehicles/Open-Vehicle-Monitoring-System-3/pull/764" rel="noreferrer" target="_blank">https://github.com/openvehicles/Open-Vehicle-Monitoring-System-3/pull/764</a>
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).</div>
<div><br>
</div>
<div>The
commit that
will follow on
from that it
implements the
new Units:
kWh/100km,
km/kWh and
mi/kWh.</div>
<div><br>
</div>
<div>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:</div>
<div> *
Should some of
the longer
unit codes be
shortened (eg
mi, mins, m,
ft, deg, perc)</div>
<div> * The
unit codes
could be much
more re<font face="arial,
sans-serif">gular
and separated
by dots eg: </font></div>
<div><font face="arial,
sans-serif">
watthours
-> w.h</font></div>
<div><font face="arial,
sans-serif">
kwhp100km
->
kw.h_100km or
kw.h/100km</font></div>
<div><font face="arial,
sans-serif">
miph
-> mi_h or
mi/h (or
should it be
mph).</font></div>
<div><font face="arial,
sans-serif">
psi
-> <a href="http://p_in.in/" rel="noreferrer" target="_blank">p_in.in</a> or p/<a href="http://in.in/" rel="noreferrer" target="_blank">in.in</a> or <a href="http://lb_in.in/" rel="noreferrer" target="_blank">lb_in.in</a> (yes, slightly
weird, but
predictable)</font></div>
<div><font face="arial,
sans-serif"> </font><br>
</div>
<b style="font-family:monospace">OVMS#
metric units</b><br>
<font face="monospace">
km :
km</font><br>
<font face="monospace">
miles : M</font><br>
<font face="monospace">
meters : m</font><br>
<font face="monospace">
feet :
ft</font><br>
<font face="monospace">
celcius :
°C</font><br>
<font face="monospace">
fahrenheit :
°F</font><br>
<font face="monospace">
kpa :
kPa</font><br>
<font face="monospace">
pa :
Pa</font><br>
<font face="monospace">
psi :
psi</font><br>
<font face="monospace">
volts : V</font><br>
<font face="monospace">
amps : A</font><br>
<font face="monospace">
</font>amphours<font face="monospace"> : Ah</font><br>
<font face="monospace">
kw :
kW</font><br>
<font face="monospace">
kwh :
kWh</font><br>
<font face="monospace">
watts : W</font><br>
<font face="monospace">
</font>watthours<font face="monospace"> : Wh</font><br>
<font face="monospace">
seconds :
Sec</font><br>
<font face="monospace">
minutes :
Min </font><br>
<font face="monospace">
hours :
Hour</font><br>
<font face="monospace">
utc :
UTC</font><br>
<font face="monospace">
degrees : °</font><br>
<font face="monospace">
kmph :
km/h</font><br>
<font face="monospace">
</font>miph<font face="monospace"> : Mph</font><br>
<font face="monospace">
</font>kmphps<font face="monospace"> : km/h/s</font><br>
<font face="monospace">
</font>miphps<font face="monospace"> : Mph/s</font><br>
<font face="monospace">
mpss :
m/s²</font><br>
<font face="monospace">
dbm :
dBm</font><br>
<font face="monospace">
sq :
sq</font><br>
<font face="monospace">
percent : %</font><br>
<font face="monospace">
whpkm :
Wh/km</font><br>
<font face="monospace">
</font>whpmi<font face="monospace"> : Wh/mi</font><br>
<font face="monospace">
kwhp100km :
kWh/100km</font><br>
<font face="monospace">
</font>kmpkwh<font face="monospace"> : km/kWh</font><br>
<font face="monospace">
</font>mipkwh<font face="monospace"> : mi/kWh</font><br>
<font face="monospace">
nm :
Nm</font><br>
<font face="monospace"><br>
<b>OVMS#
metric unit mi</b><br>
miles :
M<br>
</font></div></blockquote></div></blockquote></div></div></blockquote></div></blockquote></div></div></blockquote></div></div></div></div></div></blockquote></div></div></blockquote></div></blockquote></div></blockquote></div></blockquote></div></div></blockquote></div></blockquote></div></blockquote></div></div></div></div></blockquote></div></blockquote></div></div></blockquote></div></div></blockquote></div></blockquote></div></div></div>
</div>