RFE: Add API to set/update WANTS
Is your feature request related to a problem? Please describe. At present, a plugin has to declare its WANTs at plugin init time. The JavaScript plugin does not know what will be wanted until a script runs, so it has to WANT anything that might be needed.
return (WANTS_TOOLBAR_CALLBACK |
WANTS_CURSOR_LATLON |
WANTS_CONFIG |
WANTS_PLUGIN_MESSAGING |
WANTS_NMEA_SENTENCES |
WANTS_NMEA_EVENTS |
WANTS_AIS_SENTENCES |
WANTS_PREFERENCES
);
This results in a lot of callbacks from plugin manager being ignored.
Describe the solution you'd like
An API allowing the WANTs to be set dynamically, so that a plugin could call, say,
setWants( WANTS_PLUGIN_MESSAGING | WANTS_NMEA_SENTENCES);
Additional context
The existing declaration at init time remains, so there are no compatibility issues.
Unnecessary callbacks from plugin manager could be drastically reduced. The JavaScript plugin only needs most of these when a script is awaiting an event. It could set the WANT at that time and turn it off afterwards. Users may have the plugin installed and enabled but no script running. All those callbacks are superfluous.
As we move towards the <ObservableListener> approach, WANTS_NMEA_SENTENCES etc. becomes less used.
Other plugins may be able to increase efficiency thereby.
As we move towards the
<ObservableListener>approach, WANTS_NMEA_SENTENCES etc. becomes less used
Indeed. Since the current json message layer just is a thin adapter on top of the underlying <ObservableListener> machinery, all needs described here are already available (listening is totally dynamic). The missing piece is perhaps some documentation on how to move from the "old" system to the "new".
We should think twice before expanding the plugin API....
@antipole2 : Thinking more about this.
First: WANTS_CONFIG, WANTS_PLUGIN_MESSAGING and WANTS_TOOLBAR_CALLBACK more or less looks as no-ops -- I don't see that they are processed in any way today, just returned from the plugins.
The rest are basically callbacks, invoking the corresponding plugin methods.
Now, after #3654 we have a new kind of message PluginMsg similar to Nmea0183Msg, Nmea2000Msg, etc. That is, if the core just emitted a message when the callbacks are to be invoked, the plugin could listen to these messages instead of using the WANTS stuff. This has many advantages:
- It is, as you have explored, dynamic.
- Future updates can be done without updating the API. Listening to not emitted messages is no harm, nor is sending messages not expected by plugins.
- We avoid that the core executes code in the plugin (increased stability)
Thoughts?
WANTS_PLUGIN_MESSAGING certainly still is used in PlugInManager::SendMessageToAllPlugins and PlugInManager::GetJSONMessageTargetCount, WANTS_CONFIG and WANTS_TOOLBAR_CALLBACK related code seem to have already all been replaced and they are not needed anymore
A general thought previously touched. If we update plugins for O 5.10 to observer instead of "WANTS.... That plugin will obliviously not fit to O 5.8 and earlier. Such a plugin will not run on 5.8 due to missed API. No problem so far. But if Pluginmanager list also such a plugin for O 5.8 the user will have a problem. Could this mean we must have two versions of plugins. One for 5.10 and one for earlier? And, not less, Pluginmanager need to know O version and list only suitable plugins. Now we have different plugins for different OS but would we also need plugins for different O versions for the same OS?
If we update plugins for O 5.10 to observer instead of "WANTS.... That plugin will obliviously not fit to O 5.8 and earlier.
Such a plugin will use the latest API so yes, the plugin manager will not load it on anything but 5.10. This is nothing new, using the latest API comes with a cost.
But if Pluginmanager list also such a plugin for O 5.8 the user will have a problem.
It will not, for reasons above.
Could this mean we must have two versions of plugins. One for 5.10 and one for earlier?
Yes. Again, this is nothing new. For this reason many plugins does not use the latest API.
WANTS_PLUGIN_MESSAGING certainly still is used
Yep, sorry, missed that. Should not change anything in general.
So If a plugin developer exchange the use of WANTS_NMEA_SENTENCES by Observer it also means old the plugin version need to be left when updating Github plugins and Pluginmanager need to fetch correct version?
@Hakansv : we are a bit off from the main track here. Can we continue in zulip to not confuse @antipole2 ?
Link to zulip channel, please?
Master - 5.8.0 | plugin compatibility
In the JavaScript plugin, I provide a script API for incoming messages, thus:
OCPNonMessageName(functionName, messageName)
Behind the scenes I examine every message to check if the type matches messageName and, if so, call functionName with the message as its argument.
I see no problem changing this to use the observable listener approach, just as I do now in plugin v3 for
OCPNonNMEA0183(functionName, ident)
I have the added complication that I have to consider compatibility with users' existing scripts. Users may update the plugin version but continue to run their old scripts. Some scripts use, for example,
OCPNonNMEA0183(functionName)
which calls the function with every NMEA083 message. The user examines the message type within the function. For compatibility, we need the old WANTS_NMEA_SENTENCES to remain functional - at least for now. And it is useful for logging all NMEA0183 sentences when doing Voyage Data Recorder type logging.
The JavaScript plugin builds a record of all plugin message types seen, which can be accessed using
OCPNgetMessageNames()
This returns a list of the message names seen since the console was created. This is useful when we want to see what messages are being sent. So we want to think carefully before withdrawing WANTS_PLUGIN_MESSAGING.
Which WANTS do you envisage replacing? What about, for example, WANTS_ONPAINT_VIEWPORT ?
In any event, at least for now, we need to retain existing WANTS apart from those that do nothing. But happy to try new observable listeners and replace old code gradually.
@antipole2
In any event, at least for now, we need to retain existing WANTS apart from those that do nothing. But happy to try new observable listeners and replace old code gradually.
We should off course not remove anything of the existing messaging, why would we? The question is just if we avoid adding a new API call which makes it possible to change the WANTS settings after boot. That is, could those plugins which have this requirement use the observable approach instead?
Seen from that angle, are there any particular messages you see the need to dynamically switch on and off?
EDIT: I don't see the need to replace anything. My idea is just to send a message besides doing current callbacks. This then means that plugins could get the messages either way, using the current WANTS stuff or the new observable. However, only the observable stuff is dynamic.
I go back to the days when code optimisation was important - every cycle counted.
So, for the JavaScript plugin with, say, four inactive consoles (not unusual) for every NMEA0183 sentence it checks each console, finds it not waiting for NMEA0183 sentences and passes. Wasted cycles. That grates.
An API to set the WANTS dynamically would enable the plugin to turn them on or off as required. When a script starts listening, the plugin would do, say,
setWants(wants | WANTS_NMEA_SENTENCES)
and when it stops listening (and no other scripts are listening) it does
setWants(wants ^ WANTS_NMEA_SENTENCES)
setWants would be very simple to implement in plugin manger, I guess.
But with processors faster and faster and using less and less power, maybe this is all irrelevant. Maybe we just let it happen. If we do not add this, it saves me having to implement the optimisation (which is not trivial given the need to check no other script is wanting the sentences before turning them off) 😀
With the forthcoming coming API update and finite implementation resources, unrelated RFEs #3586 & #3166 are much more important!
An API to set the WANTS dynamically would enable the plugin to turn them on or off as required.
Yes. But using the observable stuff would also work if there was a message to listen to, right?
The observable function is fantastic. In my case it must save a "lot power" now totally wasted. The example: Plugin Ais_vd_pi reads a message from a connected AIS (class A). First at O start up and then when requested by buttons at the plugin dialog. Normally used a couple of times per day. Today with WANTS... all received NMEA0183 messages are passed to the plugin and the plugin is acting on one, rarely present, message. Here that's about 3 to 40 messages per second to check. Using observable only a couple per day is transferred. OCPN does need to do a check on every received message if any plugin or other function like to observe it but I suppose that's nothing new for the multiplexer or whom is doing that.
And I can't switch on WANTS.. when needed since there can be other O instances around me using the same plugin or other devices changing the same data any time.
So, my proposal: Instead of implementing "dynamic WANTS" we could implement new messages which makes is possible to use the observable stuff instead for cases like WANTS_ONPAINT_VIEWPORT .
OK?
So, my proposal: Instead of implementing "dynamic WANTS" we could implement new messages which makes is possible to use the observable stuff instead for cases like WANTS_ONPAINT_VIEWPORT .
OK?
I'm OK with that, thanks.
Then let's see what I can do, probably later this week.
Unsurprisingly my schedule won't work. Making a new try next week
Looking into this I realize that in order to fix it we need to generalize PliuginMsg to also carry a general shared_ptr similar to what ObservedEvtcarries. I'm on it, but with limited time.