[Nut-upsdev] nutdrv_qx interface change proposal item_t::preprocess

hyouko at gmail.com
2015-05-19T00:11:46Z

mmh..

At the moment there are 3 distinct preprocess functions that operate
on 2 different types:
- info_rw_t - preprocess();
- item_t - preprocess();
- item_t - preprocess_answer().

For info_rw_t: range/enum values are preprocessed just to see if that
specific value is to be used or not depending on the conditions the
driver meets at runtime (e.g.: low voltage devices -> low voltage
ranges). So, in this case, directions don't seem to make sense to me.

For item_t:
- preprocess_answer() is always (and only) executed everytime the
driver reads a new 'answer' (be it as a consequence of a query or of
an instant command/setvar, no difference) from the device. So, in this
case, too, I can't see the ambiguity.
- preprocess(): this function is executed
  * for queries: to translate a value from device-form to NUT-form (so
direction is DEVICE -> NUT, i.e.: read from device the 'answer' to
that query);
  * for instant commands/setvars (QX_FLAG_CMD/QX_FLAG_SETVAR): to fill
the command to be sent to device with data from NUT-form to
device-form (so direction is NUT -> DEVICE, i.e.: write to device;
answer is expected to be either 'command accepted' or 'command
rejected').
  So direction already depends on item_t type (i.e. qxflags).

At the time the driver was written, that was enough to handle all situations.

Now, I know that there can be queries that need to be preprocessed
(QED<date> and the like, right?), but there's no such a thing in NUT
(i.e.: you cannot pass a value to a query directly from the command
line just like you would do with instant commands/setvars, plus the
driver preferred way of communication is through NUT variables): the
closest thing you can do is to:
1. set a var (let's say "zig.zag") to a value (so there should be
both
a bare "zig.zag" item_t with info_flags ST_FLAG_RW and a
QX_FLAG_SETVAR "zig.zag" one in nutdrv_qx) or use an internal var that
gets its value from something other;
2. use that var (either the user-provided one, "zig.zag" , or the
internal one) to fill the query (preprocess from NUT-form to
device-form and write to device) and then proceed as per other queries
(read from device the 'answer' and get the values, say
"ding.dong.1",
"ding.dong.2", ..., which may also need to be preprocessed from
device-form to NUT-form).
Thus, in the end, you may need both the NUT->device and device->NUT
preprocess functions and I don't feel enthusiastic about having big
functions that switch on direction - I already see myself lost trying
to get out of it.

What I'd do instead is to add a 3rd item_t preprocess function (be it
'preprocess_command()') that works like the preprocess_answer() one
(but in the opposite direction): this function would be called just
before the command (any command, both queries and instant
commands/setvars, no difference) would be sent to the device so that:
- queries that need to be preprocessed, can be;
- devices that require a CRC or any other weird transliteration, can
be satisfied (at this time instant commands/setvars are already filled
with user-provided data, and the same would be true for those queries
that need to be preprocessed: you'd only have to call the CRC/whatever
function before quitting the query-preprocess one).

Here's a first try at it:
https://github.com/zykh/nut/tree/nutdrv_qx_preprocess_command

Am I that far from what you want to achieve?