Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for controlling eebus-go via JSON-RPC from another process (
#128) This PR provides an implementation of a [JSON-RPC 2](https://www.jsonrpc.org/specification) server that proxies calls into the eebus-go stack via TCP for control by other processes. The current state of this PR is a draft, all basic (and some advanced) functionality should work, but not all functions and edge cases are handled, and those that are handled may not be implemented optimally. Consider this a request for comments from the community on the current state of the PR and how it should proceed. The RPC server provides access to eebus-go methods via reflection and static/dynamic method scoping. Static method scoping is used to proxy methods for the eebus-go/service.Service struct by prefixing the method with "service/", methods assigned to the RPC server itself are scoped under "remote/", the service.LocalDevice methods are available under "localdevice/", and all registered use cases are available via the registered usecaseId (e.g. "eg-lpc/"). Dynamic method proxying is available currently for DeviceRemoteInterface and EntityRemoteInterface types by prefixing the wanted method with "Call/" and passing an AddressDeviceType or EntityAddressType as the first parameter. Use case specific notifications from the eebus-go stack are passed to the RPC client via a json-rpc notification where the method field is set to the api.EventType and the parameters is a JSON object containing the ski, the device address and the device entity. Notifications that the eebus-go stack normally provides the ServiceHandlerInterface are proxied to the RPC client with the method set the name of the called method in the ServiceHandlerInterface prefixed with the string "remote/". The parameters for these notifications are notification specific. There are still several open points that I have either not yet implemented or that I think should be discussed by the community before being addressed: - not all types returned by functions in the eebus-go stack can be easily serialized/deserialized via JSON. I have added automatic serialization/deserialization for the DeviceRemoteInterface and EntityRemoteInterface, but all other types that are Interfaces, contain Interfaces, or contain private members cannot currently be serialized or deserialized, this notably includes the DeviceLocalInterface, and the RemoteEntityScenarios struct. Options to increase the number of serializable/deserializable types include implementing the Marshaler/Unmarshaler interface for simple types (such as RemoteEntityScenarios) or adjusting method return types to make them serializable/deserializable. - it's impossible to pass a callback via JSON-RPC so all functions that can take a resultCB must currently take nil (json null) in that position. It may be nice to detect functions with such a parameter and provide a means for callers to register interest in the result of such an operation such that the RPC server creates a resultCB type that forwards the ResultDataType as a notification to the controlling client. To accomplish this, it would be necessary to adjust the type of the resultCB function to also take the MsgCounter as a second argument as the RPC server cannot create a function which knows the MsgCounter prior to the actual function in question being called. I've already received some feedback to a few points that I will collect here: - currently all functions that return (value, error) will drop the error from the response when it is nil, and return a JSON-RPC error message otherwise. This handling does not occur for all functions with more than 2 return values. It may be more consistent to adjust this, or drop custom handling of errors entirely. Errors would then be returned as the final argument in their string representation. - currently the EEBus-Service is automatically started as soon as the JSON-RPC listener starts, it might be better if the service is manually started via a JSON-RPC method call instead - the RPC server currently does not limit the number of controlling connections, nor does it bind the lifetime of the EEBus service to the lifetime of the TCP connection. We may want to limit the number of simultaneous connections to 1, as well as terminate the EEBus service on connection loss to prevent e.g. limits from staying valid even though the controlling connection died
- Loading branch information