@wethecurious/iotes-curios
v0.1.33
Published
Curios middleware for iotes
Downloads
25
Readme
iotes-curios
This collection of middlewares is designed to provide a redux friendly connection to We The Curious's Curios services for exhibit's implementing the redux pattern. The middleware handles connection to and data retrival from:
- mqtt iot devices
- phidget physical input devices
- exhibit analytics service
Example
There is a basic example here of the usage of this package avaliable on We The Curious bitbucket https://bitbucket.org/wethecurious/playground-usecurios-example/src/master/
Usage
The createCuriosMiddleware export both a middleware and wrapped version of the redux combineReducer function which provides the '@@Curios' reducer to track connection state in the redux store
This is a significant rewrite of the previous brightsign-middleware package. In the long tun it will make it easer to intgrate new devices
Config example
const phidgetTopologoy: TopologyMap<PhidgetStrategyConfig, PhidgetDeviceTypes > = {
hosts: [{ name: 'testapp/0', host: 'localhost', port: '8888' }],
devices: [
{
hostName: 'testapp/0', //host name of device matches the device with required host
type: 'RFID_READER',
name: 'READ/1', // Note that the names must be unique globally across all strategies at this stage
channel: 1,
},
{
hostName: 'testapp/0',
type: 'ROTARY_ENCODER',
name: 'ENCOD/1',
channel: 2,
},
],
}
const messageTopologoy: TopologyMap<MqttStrategyConfig, MqttDeviceTypes> = {
hosts: [{ name: 'testapp/0', host: 'localhost', port: '8888' }],
devices: [
{
hostName: 'testapp/0',
type: 'APP_CHANNEL',
name: 'READER/1',
channel: 1,
},
{
hostName: 'testapp/0',
type: 'EXTERNAL_CHANNEL',
name: 'ENCODER/1',
channel: 2,
},
],
}
const config: CuriosConfig = {
app: 'app',
appInstance: 0,
service: 'service',
serviceInstance: 0,
phidget: phidgetTopologoy,
message: messageTopologoy
}
Usage example
On Initialisation
const { useCurios, middleware, combineReducers }: CuriosIntegration = createCuriosMiddleware(config)
const reduxStore = createStore(combineReducers({...otherReducers}), applyMiddleware(...middleware))
Within a component
const Component = () => {
const [ deviceVal, setDeviceVal ] = useCurios()
return (
<>
<p>{deviceVal}</p>
<button onClick={() => {
setDeviceVal(
'ENCODER/1', // Device name to update
'UPDATE', // type of update (may not be used by the strategy, depending on the purpose and docs)
{ message: 'test' }, // Payload to send to device
)
}}
/>
</>
)
}
Adding Devices
Adding Strategies to handle new device types
This is packages is built on iotes, which is a more generalised packages for communication between state management libraries.
Iotes works by routing requests to strategies which hendle device communication. The strategy for phidget22 for example for be found here
https://www.npmjs.com/package/iotes-strategy-phidget22,
support for more more devices can be added by modifying the strategy source or writing a new strategy
The general form of a strategy is as follows
const strategy = iotesFunctions => hostFactory => DeviceFactory => DeviceFunction
For example
const phidgetStrategy = (
hostDispatch,
deviceDispatch,
hostSubscribe,
hostDispatch
): HostFactory => async (
hostConfig: HostConfig<StrategyConfig>,
): Promise<DeviceFactory> => (
deviceFactory
) => DeviceFunctions
The function of each of the stages is:
- iotesFunction: is where the iotes commuication channel are injected and should remain as the four fuctions as demonstrated.
- hostFactory: is where the host connections from the tolopology map are created. This is where you make the connection to the service you are trying to use. This returns a device factory.
- deviceFactory: This returns a object of functions. Each function create connections to the devices described in the topology map.
- deviceFunctions: This is the function which creates the connection to the actual device.
The completed strategy should then be able to be passed into the createIotes function and be initialised according to the topology map
Adding strategies to Curios reducer
The reducer connection to iotes is initialised by creating muliple instances of the IotesReactReduxHooks
plugin.
const [ usePhidget, phidgetMiddleware ]: IotesReactReduxHook = createIotesReactReduxHook(
{...phidget, client: { name: names.complete }},
phidgetStrategy, '@@CURIOS', '@@CURIOS_PHIDGET'
)
const [ useMessage, messageMiddleware ]: IotesReactReduxHook = createIotesReactReduxHook(
{ ...message, client: { name: names.complete } },
mqttStrategy, '@@CURIOS', '@@CURIOS_MESSAGE'
)
const [ useAnalytics, analyticsMiddleware ]: IotesReactReduxHook = createIotesReactReduxHook(
{...analytics, client: { name: names.complete }},
mqttStrategy, '@@CURIOS', '@@CURIOS_ANALYTICS'
)
//Add a new connection here
const middlewares = [phidgetMiddleware, messageMiddleware, analyticsMiddleware, /*Add new middleware here*/]
return ({
useCurios: createUseCurios(usePhidget, useMessage, useAnalytics, /*add new hooks here*/),
middleware: middlewares,
combineReducers
})
In the actual custom hook you need to manually add the hook handlng at this stage (I couldn't work out how to reliably put it in a loop without violating the rules of hooks)
const createUseCurios = (usePhidget: any, useMessage: any, useAnalytics: any):() => [{}, any] => {
return () => {
const [ input, setInput ] = useState({})
const [ phidget, setPhidget ] = usePhidget()
const [ message, setMessage ] = useMessage()
const [ analytics, setAnalytics ] = useAnalytics()
// Destructure new hooks here
const [ output, setOutput ] = useState<DeviceDispatchable<any>>({})
const setDeviceVal = (
name: string,
type: any,
payload: {[key:string] : unknown},
meta?: {[key:string] : unknown},
source? :string,
error?: ErrorDispatchable
) => {
setOutput({...output, ... createDeviceDispatchable(name, type, payload, meta, source, error)})
}
useEffect(() => {
setInput(phidget)
}, [phidget])
useEffect(() => {
setInput(message)
}, [message])
useEffect(() => {
setInput(analytics)
}, [analytics])
// Add input method here
useEffect(() => {
setMessage(output)
setPhidget(output)
// add set hook here
},[output])
return [ input, setDeviceVal ]
}
}
TODO
- Support for more phidget devices
- Strategy to talk to mqtt dmx