diff --git a/recipes-app/iot2050-conf-webui/files/src/components/ExtendedModules/SM1231_8AI/SM1231with8AIConf.js b/recipes-app/iot2050-conf-webui/files/src/components/ExtendedModules/SM1231_8AI/SM1231with8AIConf.js new file mode 100644 index 000000000..1e909dd58 --- /dev/null +++ b/recipes-app/iot2050-conf-webui/files/src/components/ExtendedModules/SM1231_8AI/SM1231with8AIConf.js @@ -0,0 +1,315 @@ +/* eslint-disable react/prop-types */ +import * as React from 'react'; +import Stack from '@mui/material/Stack'; +import Paper from '@mui/material/Paper'; +import FormGroup from '@mui/material/FormGroup'; +import FormControl from '@mui/material/FormControl'; +import ModuleInfo from '@/components/ModuleInfo'; +import SelectionConfig from '@/components/ConfigEntry/SelectionConfig'; +import CheckConfig from '@/components/ConfigEntry/CheckConfig'; +import ConfigGroupLabel from '@/components/ConfigEntry/ConfigGroupLabel'; +import ConfTextConverter from '@/lib/smConfig/ConfTextConverter'; +import uiString from '@/lib/uiString/SM1231_8AI.json'; +import { range } from 'lodash'; + +const yamlUIMapping = [ + { + keys: [/ch[0-7]\.type/], + rules: [ + { + scenario: 'all', + mapping: [ + { ui: uiString.TYPE_1, yaml: 1 }, + { ui: uiString.TYPE_3, yaml: 3 } + ] + } + ] + }, + { + keys: [/ch[0-7]\.range/], + rules: [ + { + scenario: 'all', + mapping: [ + { ui: uiString.RANGE_2, yaml: 2 }, + { ui: uiString.RANGE_3, yaml: 3 }, + { ui: uiString.RANGE_7, yaml: 7 }, + { ui: uiString.RANGE_8, yaml: 8 }, + { ui: uiString.RANGE_9, yaml: 9 } + ] + } + ] + }, + { + keys: [/integ_time/], + rules: [ + { + scenario: 'all', + mapping: [ + { ui: uiString.INT_TIME_0, yaml: 0 }, + { ui: uiString.INT_TIME_1, yaml: 1 }, + { ui: uiString.INT_TIME_2, yaml: 2 }, + { ui: uiString.INT_TIME_3, yaml: 3 } + ] + } + ] + }, + { + keys: [/ch[0-7]\.smooth/], + rules: [ + { + scenario: 'all', + mapping: [ + { ui: uiString.SMOOTH_0, yaml: 0 }, + { ui: uiString.SMOOTH_1, yaml: 1 }, + { ui: uiString.SMOOTH_2, yaml: 2 }, + { ui: uiString.SMOOTH_3, yaml: 3 } + ] + } + ] + } +]; + +const converter = new ConfTextConverter(yamlUIMapping); + +const rangeSelectionOfCurrent = [ + uiString.RANGE_2, + uiString.RANGE_3 +]; + +const rangeSelectionOfVoltage = [ + uiString.RANGE_7, + uiString.RANGE_8, + uiString.RANGE_9 +]; + +const channelConfigDefault = { + type: { + label: uiString.LABEL_TYPE, + selection: [ + uiString.TYPE_1, + uiString.TYPE_3 + ], + value: uiString.TYPE_1 + }, + range: { + label: uiString.LABEL_RANGE_VOL, + selection: rangeSelectionOfVoltage, + value: uiString.RANGE_9 + }, + smooth: { + label: uiString.LABEL_SMOOTH, + selection: [ + uiString.SMOOTH_0, + uiString.SMOOTH_1, + uiString.SMOOTH_2, + uiString.SMOOTH_3 + ], + value: uiString.SMOOTH_1 + }, + open_wire_alarm: { + label: uiString.LABEL_OPEN_WIRE_ALARM, + value: false + }, + overflow_alarm: { + label: uiString.LABEL_OVER_FLOW_ALARM, + value: true + }, + underflow_alarm: { + label: uiString.LABEL_UNDER_FLOW_ALARM, + value: true + } +}; + +export const SM1231with8AIConfDefault = { + mlfb: '6ES7231-4HF32-0XB0', + power_alarm: { + label: uiString.LABEL_POWER_ALARM, + value: true + }, + integ_time: { + label: uiString.LABEL_INT_TIME, + selection: [ + uiString.INT_TIME_0, + uiString.INT_TIME_1, + uiString.INT_TIME_2, + uiString.INT_TIME_3 + ], + value: uiString.INT_TIME_2 + }, + channels: [ + JSON.parse(JSON.stringify(channelConfigDefault)), + JSON.parse(JSON.stringify(channelConfigDefault)), + JSON.parse(JSON.stringify(channelConfigDefault)), + JSON.parse(JSON.stringify(channelConfigDefault)), + JSON.parse(JSON.stringify(channelConfigDefault)), + JSON.parse(JSON.stringify(channelConfigDefault)), + JSON.parse(JSON.stringify(channelConfigDefault)), + JSON.parse(JSON.stringify(channelConfigDefault)) + ] +}; + +export function convertToUIFormat (config) { + const ret = JSON.parse(JSON.stringify(SM1231with8AIConfDefault)); + + ret.power_alarm.value = config.power_alarm; + ret.integ_time.value = converter.yamlToUi('integ_time', config.integ_time); + + for (let i = 0; i < 8; i++) { + ret.channels[i].type.value = converter.yamlToUi(`ch${i}.type`, config[`ch${i}`].type); + ret.channels[i].range.value = converter.yamlToUi(`ch${i}.range`, config[`ch${i}`].range); + if (ret.channels[i].type.value === uiString.TYPE_1) { + ret.channels[i].range.selection = rangeSelectionOfVoltage; + ret.channels[i].range.label = uiString.LABEL_RANGE_VOL; + } else { + ret.channels[i].range.selection = rangeSelectionOfCurrent; + ret.channels[i].range.label = uiString.LABEL_RANGE_CUR; + } + + ret.channels[i].smooth.value = converter.yamlToUi(`ch${i}.smooth`, config[`ch${i}`].smooth); + ret.channels[i].open_wire_alarm.value = config[`ch${i}`].open_wire_alarm; + ret.channels[i].overflow_alarm.value = config[`ch${i}`].overflow_alarm; + ret.channels[i].underflow_alarm.value = config[`ch${i}`].underflow_alarm; + } + return ret; +}; + +export function convertToDeviceFormat (config) { + const ret = { + description: uiString.DESC_MOD, + mlfb: config.mlfb, + power_alarm: config.power_alarm.value, + integ_time: converter.uiToYaml('integ_time', config.integ_time.value) + }; + for (let i = 0; i < 8; i++) { + ret['ch' + i] = { + type: converter.uiToYaml(`ch${i}.type`, config.channels[i].type.value), + range: converter.uiToYaml(`ch${i}.range`, config.channels[i].range.value), + smooth: converter.uiToYaml(`ch${i}.smooth`, config.channels[i].smooth.value), + open_wire_alarm: config.channels[i].open_wire_alarm.value, + overflow_alarm: config.channels[i].overflow_alarm.value, + underflow_alarm: config.channels[i].underflow_alarm.value + }; + } + return ret; +}; + +export default function SM1231with8AIConf ({ slotNum, configData, updateConfig }) { + const setChannelRange = (event) => { + const chIndex = parseInt(event.target.name.slice(-1), 10); + const newType = configData.channels[chIndex].type.value; + let newRangeSelection; + let newRangeLabel; + let newRange; + + if (newType === uiString.TYPE_1) { + newRangeSelection = rangeSelectionOfVoltage; + newRangeLabel = uiString.LABEL_RANGE_VOL; + newRange = uiString.RANGE_9; + } else { + newRangeSelection = rangeSelectionOfCurrent; + newRangeLabel = uiString.LABEL_RANGE_CUR; + newRange = uiString.RANGE_2; + } + + configData.channels[chIndex].range.selection = newRangeSelection; + configData.channels[chIndex].range.label = newRangeLabel; + configData.channels[chIndex].range.value = newRange; + /* Set the binding channel */ + configData.channels[chIndex + 1].type.value = newType; + configData.channels[chIndex + 1].range.selection = newRangeSelection; + configData.channels[chIndex + 1].range.label = newRangeLabel; + configData.channels[chIndex + 1].range.value = newRange; + }; + + const updateSlotConfig = () => { + updateConfig(slotNum, configData); + }; + + return ( + + + + + + + + {range(0, 8).map((index) => ( + + + + + + + + + + + + + + + + + + + + + + )) + } + + ); +} diff --git a/recipes-app/iot2050-conf-webui/files/src/components/SlotInfo.js b/recipes-app/iot2050-conf-webui/files/src/components/SlotInfo.js index 2300c9ff8..d369ec86e 100644 --- a/recipes-app/iot2050-conf-webui/files/src/components/SlotInfo.js +++ b/recipes-app/iot2050-conf-webui/files/src/components/SlotInfo.js @@ -8,6 +8,7 @@ import Typography from '@mui/material/Typography'; import SM1223Conf, { SM1223ConfDefault } from '@/components/ExtendedModules/SM1223/SM1223Conf'; import SM1231_4RTDConf, { SM1231_4RTDConfDefault } from '@/components/ExtendedModules/SM1231_RTD/SM1231_4RTDConf'; import SM1231_8RTDConf, { SM1231_8RTDConfDefault } from '@/components/ExtendedModules/SM1231_RTD/SM1231_8RTDConf'; +import SM1231with8AIConf, { SM1231with8AIConfDefault } from '@/components/ExtendedModules/SM1231_8AI/SM1231with8AIConf'; function Mod ({ modType, slotNum, config, updateConfig }) { switch (modType) { @@ -29,6 +30,12 @@ function Mod ({ modType, slotNum, config, updateConfig }) { configData={config} updateConfig={updateConfig} />; + case '6ES7231-4HF32-0XB0': + return ; default: return No module in this slot!!!; } @@ -46,6 +53,9 @@ export default function SlotInfo ({ slotNum, configData, updateSlot }) { case '6ES7231-5PF32-0XB0': updateSlot(slotNum, JSON.parse(JSON.stringify(SM1231_8RTDConfDefault))); break; + case '6ES7231-4HF32-0XB0': + updateSlot(slotNum, JSON.parse(JSON.stringify(SM1231with8AIConfDefault))); + break; default: updateSlot(slotNum, { mlfb: 'None' }); } @@ -56,6 +66,7 @@ export default function SlotInfo ({ slotNum, configData, updateSlot }) { '6ES7223-1QH32-0XB0', // SM1223 '6ES7231-5PD32-0XB0', // SM1231-4RTD '6ES7231-5PF32-0XB0', // SM1231-8RTD + '6ES7231-4HF32-0XB0', // SM1231-8AI ]; return ( diff --git a/recipes-app/iot2050-conf-webui/files/src/lib/smConfig/smConfig.js b/recipes-app/iot2050-conf-webui/files/src/lib/smConfig/smConfig.js index 8b18ff81e..3aa16279b 100644 --- a/recipes-app/iot2050-conf-webui/files/src/lib/smConfig/smConfig.js +++ b/recipes-app/iot2050-conf-webui/files/src/lib/smConfig/smConfig.js @@ -6,6 +6,10 @@ import { convertToDeviceFormat as convertToDeviceFmtForSM1231RTD, convertToUIFormat as convertToUIFmtForSM1231RTD } from '@/components/ExtendedModules/SM1231_RTD/SM1231_RTDConf'; +import { + convertToDeviceFormat as convertToDeviceFmtForSM1231with8AI, + convertToUIFormat as convertToUIFmtForSM1231with8AI +} from '@/components/ExtendedModules/SM1231_8AI/SM1231with8AIConf'; export function exportYamlConfig (configData) { const yamlConfig = {}; @@ -20,6 +24,9 @@ export function exportYamlConfig (configData) { case '6ES7231-5PF32-0XB0': // SM1231-8RTD yamlConfig['slot' + slotIndex] = convertToDeviceFmtForSM1231RTD(confSlot); break; + case '6ES7231-4HF32-0XB0': // SM1231-8AI + yamlConfig['slot' + slotIndex] = convertToDeviceFmtForSM1231with8AI(confSlot); + break; case 'None': default: yamlConfig['slot' + slotIndex] = { @@ -53,6 +60,9 @@ export function importYamlConfig (configData) { case '6ES7231-5PF32-0XB0': // SM1231-8RTD uiConfig.config[i - 1] = convertToUIFmtForSM1231RTD(configData['slot' + i]); break; + case '6ES7231-4HF32-0XB0': // SM1231-8AI + uiConfig.config[i - 1] = convertToUIFmtForSM1231with8AI(configData['slot' + i]); + break; case 'None': default: break; diff --git a/recipes-app/iot2050-conf-webui/files/src/lib/uiString/SM1231_8AI.json b/recipes-app/iot2050-conf-webui/files/src/lib/uiString/SM1231_8AI.json new file mode 100644 index 000000000..8827c4637 --- /dev/null +++ b/recipes-app/iot2050-conf-webui/files/src/lib/uiString/SM1231_8AI.json @@ -0,0 +1,27 @@ +{ + "DESC_MOD": "Analog input module AI8 x 13 bits", + "LABEL_POWER_ALARM": "Enable module 24V DC power supply diagnostics", + "LABEL_TYPE": "Measurement type:", + "LABEL_RANGE_VOL": "Voltage range:", + "LABEL_RANGE_CUR": "Current range:", + "LABEL_INT_TIME": "Set integration time for noise reduction:", + "LABEL_SMOOTH": "Smoothing:", + "LABEL_OPEN_WIRE_ALARM": "Enable broken wire diagnostics", + "LABEL_OVER_FLOW_ALARM": "Enable overflow diagnostics", + "LABEL_UNDER_FLOW_ALARM": "Enable underflow diagnostics", + "TYPE_1": "Voltage", + "TYPE_3": "Current", + "RANGE_2": "0..20mA", + "RANGE_3": "4..20mA", + "RANGE_7": "+/-2.5V", + "RANGE_8": "+/-5V", + "RANGE_9": "+/-10V", + "INT_TIME_0": "400 Hz (2.5ms)", + "INT_TIME_1": "60 Hz (16.6ms)", + "INT_TIME_2": "50 Hz (20ms)", + "INT_TIME_3": "10 Hz (100ms)", + "SMOOTH_0": "None (1 cycle)", + "SMOOTH_1": "Weak (4 cycles)", + "SMOOTH_2": "Medium (16 cycles)", + "SMOOTH_3": "Strong (32 cycles)" +} \ No newline at end of file