Display of the last measured values

Hello everyone,

I have a conceptual question.

Initial situation: A machine delivers several events every second according to this scheme:

eventType: string;
machineName: string;
value: number;

E.G.:
{“temperatureChanged”, “machine1”,85}
{“rotationCountChanged”, “machine1”,500}
{“IncomingVoltageChanged”, “machine1”,205}
{“temperatureChanged”, “machine1”,87}

As a result I would like to have a React Dashboard like this:

So a table with one row for each event type. For each eventType the last measured element should be displayed.

if I use the following code, of course I have 3 lines with the same value:

What would be the most elegant way to solve this?

Hi there,

And welcome to our community :wave: .

I’d suggest to do the following:

  1. Define your change event to include both the measurement type, e.g. rotationCount or temperature and the corresponding value
  2. Implement a fish to listen to these events and compute its state which would be simply a map of measurement types to the last value
  3. Use that fish in your React app (useFish()) and wire the separate map entries of the state to rows in your table.

Fish incl. event type declaration

import { FishId, Fish, Tag } from '@actyx/pond'

// (1) Measurement event type
export type Measurement = 'rotationCount' | 'temperature' | 'incomingVoltage'
export type MeasurementEvent = {
  sourceMachine: string,
  measurement: Measurement,
  value: number
}

type LastMeasurementState = {}

export const measurementTag = Tag<MeasurementEvent>('Measurement')
export const LastMeasurementsFish: Fish<LastMeasurementState, MeasurementEvent> = {
  fishId: FishId.of('ax.example.community.78', 'LastMeasurementFish', 0),
  initialState: {},
  onEvent: (state: LastMeasurementState, event: MeasurementEvent) => {
    state[event.measurement] = event.value // (2) only record the last measurement
    return state
  },
  where: measurementTag,
}

UI Component

import * as React from 'react'
import { useFish } from '@actyx-contrib/react-pond'
import { LastMeasurementsFish } from './fish/LastMeasurementsFish'

export const Foo = (): JSX.Element => {
  const measurements = useFish(LastMeasurementsFish)

  return (
      <table>
        <thead>
          <tr>
            <th>Measurement</th>
            <th>Value</th>
          </tr>
        </thead>
        <tbody>
        <!-- (3) -->
          {
            Object.keys(measurements.state).map((k) => (
              <tr key={k}>
                <td>{k}</td>
                <td>{measurements.state[k]}</td>
              </tr>
            ))
          }
        </tbody>
      </table>
  )
}

Note that this example does only record the latest measurement of each type, not the latest measurement per machine of each type. If you require this, you can simply extend onEvent to produce the desired state.

Here’s the component with additional controls to emit measurement events, in case you want to play with it in isolation.

import * as React from 'react'
import { useState } from 'react'
import { usePond, useFish } from '@actyx-contrib/react-pond'
import { LastMeasurementsFish, measurementTag } from './fish/LastMeasurementsFish'

export const Foo = (): JSX.Element => {
  const [measurement, setMeasurement] = useState('temperature')
  const [value, setValue] = useState(-1)
  const measurements = useFish(LastMeasurementsFish)

  const pond = usePond()


  return (
    <div>
      <table>
        <thead>
          <tr key={k}>
            <th>Measurement</th>
            <th>Value</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td><input onChange={({ target }) => setMeasurement(target.value)} value={measurement} /></td>
            <td><input onChange={({ target }) => setValue(target.valueAsNumber)} value={value} type='number' /></td>
          </tr>
          {
            Object.keys(measurements.state).map((k) => (
              <tr>
                <td>{k}</td>
                <td>{measurements.state[k]}</td>
              </tr>
            ))
          }
          <tr>
            <td colSpan={2}>
              <button onClick={() => {
                pond.emit(measurementTag, {
                  sourceMachine: 'M1',
                  measurement: measurement,
                  value: value
                })
              }}>measure</button>
            </td>
          </tr>
        </tbody>
      </table>


    </div>
  )
}

Does this help? Feel free to ask, if you have further questions.

2 Likes

That worked great
Thanks for the help.

1 Like