-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial ‐ Connecting Components to Adapters
To start with something simple, lets create two components that connect to a specific path within an Adapter's parameter tree.
Let's assume that this adapter is called example
has a path within its parameter tree that looks something like this:
"heater"
{
"active": false
"temperature": 15
}
active
is readable and writeable, setting it to true
activates some sort of heating element, causing the temperature to rise. temperature
is read only, and displays the current temperature of the heating element in degrees Celsius.
To get access to this part of the parameter tree, we can create an AdapterEndpoint object that points to this adapter.
const heaterEndpoint = useAdapterEndpoint("example", "http://localhost:8888", 1000);
This endpoint object will allow us to see and modify the adapter's parameter tree from within the Odin React App. The 1000
at the end tells it we want to refresh the "local view" of the parameter tree once every 1000 milliseconds, to keep the temperature reading on the GUI updating. Without this, the Endpoint object would only update when a PUT or GET request is made using it.
In order to make components that can interact with this, we need to create a component that is wrapped in the WithEndpoint Custom hook. This hook returns the component provided, but automatically handles events such as the OnClick event method for a button, in order to send information to the endpoint. Let's create an EndpointToggle
, a toggle switch that can send something to the endpoint when clicked.
const EndpointToggle = WithEndpoint(ToggleSwitch);
As this is basically declaring a custom component, it should be done just underneath any imports you need, before you declare the Functional Component that makes up the actual App.
Now, within the return method of the Functional Component, we can add the endpoint toggle switch that will change the value of active
within that endpoint's parameter tree
return (
<EndpointToggle endpoint={heaterEndpoint} event_type="click" label="Activate Heater"
fullpath="heater/active" checked={heaterEndpoint.data.heater?.active || false}/>
...
)
Note the question mark notation within the definition for checked
. This is called Optional Chaining and is a useful means of accessing properties of an object that are not guaranteed to exist. If the endpoint object is unable to populate it's data object for whatever reason then it will evaluate to undefined
and thus the component will instead use the other side of the ||
OR operator, which in this case if false
.
Because of the way the AdapterEndpoint hook is designed, the data object within it will always initiate as an empty object {}
, which will be populated once a successful GET request is finished. Because of this, the first render of a component using the AdapterEndpoint data object will not have access to that data, and so there should always be some form of check to stop the app crashing as soon as it attempts its first render.
Once we've got the toggle switch working, we can include something to display the Temperature. Because this is read only, we can simply use the data object from the Adpater Endpoint hook. Lets use a StatusBox component to do this:
...
<StatusBox label="Temperature" type={heaterEndpoint.data.heater?.active ? "success" : "danger"}>
{heaterEndpoint.data.heater?.temperature || "Unknown"}
</StatusBox>
Again, because we are using the data object from the heaterEndpoint
hook, we need to ensure there are checks in place to make sure the data exists and is accessible. As you can see in the screenshot, because this Adapter does not actually exist, the Card has been coloured Red (due to the single line IF statement in the type
definition) and it currently reads "Unknown".
These are the two main ways you might connect a component with an adapter. It demonstrates the fact that two or more components can make use of the same AdapterEndpoint hook, and you can see that changes made by one component will be reflected in all other components using that same Endpoint.