diff --git a/public/js/admin_bundle.js b/public/js/admin_bundle.js index cd1da7a..787157d 100644 --- a/public/js/admin_bundle.js +++ b/public/js/admin_bundle.js @@ -81343,6 +81343,10 @@ var _UnitIOGroup = __webpack_require__(1034); var _UnitIOGroup2 = _interopRequireDefault(_UnitIOGroup); +var _UnitModbus = __webpack_require__(1166); + +var _UnitModbus2 = _interopRequireDefault(_UnitModbus); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } @@ -81409,6 +81413,12 @@ var ActionSelect = function (_React$Component) { showDialog: showDialog, toggleLoading: toggleLoading, updateData: _this.updateData }); + case 'modbus': + return _react2.default.createElement(_UnitModbus2.default, { i18n: i18n, + data: _this.state.act, + showDialog: showDialog, + toggleLoading: toggleLoading, + updateData: _this.updateData }); default: return null; } @@ -81438,6 +81448,11 @@ var ActionSelect = function (_React$Component) { if (acts[1] < 16 || acts[1] > 30) return showDialog('冷氣溫度請介於16-30間'); } } + if (type == 'modbus') { + var _acts = act.split(','); + if (_acts.length != 3) return showDialog('請把動作資料填寫完成'); + if (_acts[0] == '' || _acts[1] == '' || _acts[2] == '') return showDialog('請把動作資料填寫完成'); + } _this.props.addNewAction({ dev: dev, devName: devName, act: act, actName: actName, type: type @@ -81487,6 +81502,11 @@ var ActionSelect = function (_React$Component) { 'option', { value: 'iogroup' }, 'IOGroup' + ), + _react2.default.createElement( + 'option', + { value: 'modbus' }, + 'Modbus' ) ) ), @@ -82207,6 +82227,10 @@ var _UnitGroups = __webpack_require__(1038); var _UnitGroups2 = _interopRequireDefault(_UnitGroups); +var _UnitModbus = __webpack_require__(1165); + +var _UnitModbus2 = _interopRequireDefault(_UnitModbus); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } @@ -82246,6 +82270,8 @@ var Unit = function (_React$Component) { return _react2.default.createElement(_UnitLeone2.default, { ops: ops, data: data.data, i18n: i18n, showDialog: showDialog, toggleLoading: toggleLoading, updateData: _this.updateData }); case 'di': return _react2.default.createElement(_UnitDigitalInput2.default, { ops: ops, data: data.data, i18n: i18n, showDialog: showDialog, toggleLoading: toggleLoading, updateData: _this.updateData }); + case 'modbus': + return _react2.default.createElement(_UnitModbus2.default, { ops: ops, data: data.data, i18n: i18n, showDialog: showDialog, toggleLoading: toggleLoading, updateData: _this.updateData }); case 'time': return _react2.default.createElement(_UnitTime2.default, { ops: ops, data: data.data, i18n: i18n, showDialog: showDialog, toggleLoading: toggleLoading, updateData: _this.updateData }); case 'unit': @@ -82254,6 +82280,7 @@ var Unit = function (_React$Component) { return null; } }, _this.updateData = function (data) { + console.log(data); _this.props.updateData(_this.props.id, data); }, _temp), _possibleConstructorReturn(_this, _ret); } @@ -82298,6 +82325,11 @@ var Unit = function (_React$Component) { { value: 'di' }, 'DigitalInput' ), + _react2.default.createElement( + 'option', + { value: 'modbus' }, + 'Modbus' + ), _react2.default.createElement( 'option', { value: 'time' }, @@ -82874,6 +82906,7 @@ var ActionLinkAdd = function (_React$Component) { return response.json(); }).then(function (json) { if (json.status != 1) return showDialog(json.message); + showDialog('新增完成'); _this.resetData(); }); }, _this.resetData = function () { @@ -95576,5 +95609,525 @@ var PageRoot = function (_React$Component) { _reactDom2.default.render(_react2.default.createElement(PageRoot, null), document.getElementById('app')); +/***/ }), +/* 1164 */, +/* 1165 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = __webpack_require__(0); + +var _react2 = _interopRequireDefault(_react); + +var _semanticUiReact = __webpack_require__(6); + +var _actions = __webpack_require__(16); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var UnitDigitalInput = function (_React$Component) { + _inherits(UnitDigitalInput, _React$Component); + + function UnitDigitalInput() { + var _ref; + + var _temp, _this, _ret; + + _classCallCheck(this, UnitDigitalInput); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = UnitDigitalInput.__proto__ || Object.getPrototypeOf(UnitDigitalInput)).call.apply(_ref, [this].concat(args))), _this), _this.state = { + list: [], + typelist: [], + portlist: [], + data: { + id: '', + op: '', + type: '', + port: '', + value: '' + } + }, _this.getDevTypes = function (id) { + if (!id) return; + var _this$props = _this.props, + i18n = _this$props.i18n, + showDialog = _this$props.showDialog; + + var typelist = i18n && i18n.getResource && i18n.language ? i18n.getResource(i18n.language + '.translation.porttype') : []; + fetch('/api/modbus/getmodbustype', (0, _actions.getRequest)({ id: id })).then(function (response) { + return response.json(); + }).then(function (json) { + if (json.status != 1) return showDialog(json.message); + var arr = json.data.record || []; + for (var i in arr) { + for (var j in typelist) { + if (arr[i].type == typelist[j].code) { + arr[i].name = typelist[j].name; + } + } + } + + _this.setState({ + typelist: arr, + portlist: [], + data: _extends({}, _this.state.data, { + type: '', + port: '' + }) + }); + }); + }, _this.getDevPorts = function (id, type) { + if (!id || !type) return; + var _this$props2 = _this.props, + i18n = _this$props2.i18n, + showDialog = _this$props2.showDialog; + + var mid = ''; + var m = id.match(/(\d+)/); + if (m != null && m.length > 1) mid = m[1]; + fetch('/api/modbus/getmodbusport', (0, _actions.getRequest)({ id: mid, type: type })).then(function (response) { + return response.json(); + }).then(function (json) { + if (json.status != 1) return showDialog(json.message); + var arr = json.data.record || []; + + _this.setState({ + portlist: arr, + data: _extends({}, _this.state.data, { + port: '' + }) + }); + }); + }, _this.changeState = function (key, value) { + var data = _extends({}, _this.state.data); + if (key == 'dev') { + data.id = value == '' ? '' : 'mb' + value; + } + if (key == 'op') { + data.op = value; + } + if (key == 'type') { + data.type = value; + } + if (key == 'port') { + data.port = value; + } + if (key == 'value') { + data.value = value; + } + + _this.setState({ + data: _extends({}, data) + }, function () { + if (key == 'dev') { + _this.getDevTypes(value); + } + if (key == 'type') { + _this.getDevPorts(_this.state.data.id, _this.state.data.type); + } + _this.sendUpdate(); + }); + }, _this.sendUpdate = function () { + var data = _extends({}, _this.state.data); + data.id = data.id + ',' + data.type + '|' + data.port; + delete data.type; + delete data.port; + delete data.dev; + _this.props.updateData(_extends({}, _this.props.data, data)); + }, _temp), _possibleConstructorReturn(_this, _ret); + } + + _createClass(UnitDigitalInput, [{ + key: 'componentDidMount', + value: function componentDidMount() { + var _this2 = this; + + var _props = this.props, + showDialog = _props.showDialog, + toggleLoading = _props.toggleLoading; + + + toggleLoading(1); + fetch('/api/system/getselectlist', (0, _actions.getRequest)({ type: 'modbus' })).then(function (response) { + return response.json(); + }).then(function (json) { + toggleLoading(0); + if (json.status != 1) return showDialog(json.message); + _this2.setState({ + list: json.data.record || [] + }); + }); + } + }, { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(np) { + var data = _extends({}, this.state.data); + // if(np.data.id != data.id) data.id = np.data.id; + if (np.data.op != data.op) data.op = np.data.op; + if (np.data.value != data.value) data.value = np.data.op; + + var id = (np.data.id || '').split(',')[0]; + var type = ((np.data.id || '').split(',')[1] || '').split('|')[0] || ''; + var port = ((np.data.id || '').split(',')[1] || '').split('|')[1] || ''; + + if (data.id != id) data.id = id; + if (data.type != type) data.type = type; + if (data.port != port) data.port = port; + + this.setState({ + data: _extends({}, data) + }); + } + }, { + key: 'render', + value: function render() { + var _this3 = this; + + var _props2 = this.props, + ops = _props2.ops, + i18n = _props2.i18n; + + var id = ''; + if (this.state.data.id != '') { + var m = this.state.data.id.match(/(\d+)/); + if (m != null && m.length > 1) { + id = m[1]; + } + } + + return _react2.default.createElement( + 'div', + null, + _react2.default.createElement( + 'select', + { value: id, onChange: function onChange(e) { + _this3.changeState('dev', e.target.value); + } }, + _react2.default.createElement( + 'option', + { value: '' }, + '\u9078\u64C7\u88DD\u7F6E' + ), + this.state.list.map(function (t, idx) { + return _react2.default.createElement( + 'option', + { key: idx, value: t.id }, + t.name + ); + }) + ), + _react2.default.createElement( + 'select', + { value: this.state.data.type, onChange: function onChange(e) { + _this3.changeState('type', e.target.value); + } }, + _react2.default.createElement( + 'option', + { value: '' }, + '\u63A5\u53E3\u985E\u578B' + ), + this.state.typelist.map(function (t, idx) { + return _react2.default.createElement( + 'option', + { key: idx, value: t.type }, + t.name + ); + }) + ), + _react2.default.createElement( + 'select', + { value: this.state.data.port, onChange: function onChange(e) { + _this3.changeState('port', e.target.value); + } }, + _react2.default.createElement( + 'option', + { value: '' }, + '\u63A5\u53E3' + ), + this.state.portlist.map(function (t, idx) { + return _react2.default.createElement( + 'option', + { key: idx, value: t.portnum }, + 'Port ' + t.portnum + ' ' + (t.name ? ' - ' + t.name : '') + ); + }) + ), + _react2.default.createElement( + 'select', + { value: this.state.data.op, onChange: function onChange(e) { + _this3.changeState('op', e.target.value); + } }, + _react2.default.createElement( + 'option', + { value: '' }, + '\u9078\u64C7\u689D\u4EF6' + ), + ops.map(function (t, idx) { + if (t.code != 8 && t.code != 9) { + return _react2.default.createElement( + 'option', + { value: t.code, key: idx }, + t.name + ); + } + }) + ), + _react2.default.createElement(_semanticUiReact.Input, { label: '\u8ACB\u8F38\u5165\u6578\u503C', value: this.state.data.value, onChange: function onChange(e, d) { + _this3.changeState('value', d.value); + } }) + ); + } + }]); + + return UnitDigitalInput; +}(_react2.default.Component); + +exports.default = UnitDigitalInput; + +/***/ }), +/* 1166 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = __webpack_require__(0); + +var _react2 = _interopRequireDefault(_react); + +var _semanticUiReact = __webpack_require__(6); + +var _actions = __webpack_require__(16); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var UnitLeone = function (_React$Component) { + _inherits(UnitLeone, _React$Component); + + function UnitLeone() { + var _ref; + + var _temp, _this, _ret; + + _classCallCheck(this, UnitLeone); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = UnitLeone.__proto__ || Object.getPrototypeOf(UnitLeone)).call.apply(_ref, [this].concat(args))), _this), _this.state = { + list: [], + data: { + dev: '', + devName: '', + func: '', + funcName: '', + addr: '', + value: '' + } + }, _this.changeState = function (tag, value) { + var data = _extends({}, _this.state.data); + + if (tag == 'func') { + data.funcName = value.name; + data.func = value.func; + } + if (tag == 'dev') { + data.dev = value.dev == '' ? '' : 'mb' + value.dev; + data.devName = value.name; + } + if (tag == 'addr') { + data.addr = value; + } + if (tag == 'value') { + data.value = value; + } + + _this.setState({ + data: _extends({}, data) + }, function () { + _this.updateData(); + }); + }, _this.updateData = function () { + var data = _extends({}, _this.state.data); + data.type = 'modbus'; + + data.act = data.func + ',' + data.addr + ',' + data.value; + data.actName = data.funcName + ' Addr:' + data.addr + ' Value:' + data.value; + + delete data.func; + delete data.funcName; + delete data.addr; + delete data.value; + + _this.props.updateData(data); + }, _this.updateAct = function (act, name) { + _this.changeState('act', { act: act, name: name }); + }, _temp), _possibleConstructorReturn(_this, _ret); + } + + _createClass(UnitLeone, [{ + key: 'componentDidMount', + value: function componentDidMount() { + var _this2 = this; + + var showDialog = this.props.showDialog; + + fetch('/api/system/getselectlist', (0, _actions.getRequest)({ type: 'modbus' })).then(function (response) { + return response.json(); + }).then(function (json) { + if (json.status != 1) return showDialog(json.message); + _this2.setState({ + list: json.data.record || [] + }); + }); + } + }, { + key: 'render', + value: function render() { + var _this3 = this; + + var i18n = this.props.i18n; + + var dev = ''; + var m = this.state.data.dev.match(/(\d+)/); + console.log(this.state); + if (m != null && m.length > 1) { + dev = m[1]; + } + return _react2.default.createElement( + 'div', + null, + _react2.default.createElement( + _semanticUiReact.Form.Field, + null, + _react2.default.createElement( + 'label', + null, + '\u9078\u64C7\u88DD\u7F6E' + ), + _react2.default.createElement( + 'select', + { value: dev, onChange: function onChange(e) { + var el = e.target; + var json = { + dev: '', + name: '' + }; + + json.dev = el.value; + json.name = el.options[el.selectedIndex].innerHTML; + + _this3.changeState('dev', json); + } }, + _react2.default.createElement( + 'option', + { value: '' }, + '\u9078\u64C7\u88DD\u7F6E' + ), + this.state.list.map(function (t, idx) { + return _react2.default.createElement( + 'option', + { key: idx, value: t.id }, + t.name + ); + }) + ) + ), + _react2.default.createElement( + _semanticUiReact.Form.Field, + null, + _react2.default.createElement( + 'label', + null, + '\u9078\u64C7\u8F38\u51FA\u985E\u578B' + ), + _react2.default.createElement( + 'select', + { value: this.state.data.func, onChange: function onChange(e) { + var el = e.target; + var json = { + func: '', + name: '' + }; + + json.func = el.value; + json.name = el.options[el.selectedIndex].innerHTML; + + _this3.changeState('func', json); + } }, + _react2.default.createElement( + 'option', + { value: '' }, + '\u8F38\u51FA\u985E\u578B' + ), + _react2.default.createElement( + 'option', + { value: '5' }, + 'DigitalOutput' + ), + _react2.default.createElement( + 'option', + { value: '6' }, + 'AnalogOutput' + ) + ) + ), + _react2.default.createElement( + _semanticUiReact.Form.Field, + null, + _react2.default.createElement(_semanticUiReact.Input, { label: '\u8F38\u5165\u4F4D\u5740', value: this.state.data.addr, onChange: function onChange(e, d) { + _this3.changeState('addr', d.value); + } }) + ), + _react2.default.createElement( + _semanticUiReact.Form.Field, + null, + _react2.default.createElement(_semanticUiReact.Input, { label: '\u8F38\u5165\u6578\u503C', value: this.state.data.value, onChange: function onChange(e, d) { + _this3.changeState('value', d.value); + } }) + ) + ); + } + }]); + + return UnitLeone; +}(_react2.default.Component); + +exports.default = UnitLeone; + /***/ }) /******/ ]); \ No newline at end of file diff --git a/route/api/modbus.js b/route/api/modbus.js index bafb8b5..3d6de7b 100644 --- a/route/api/modbus.js +++ b/route/api/modbus.js @@ -590,6 +590,98 @@ router n(); }) }) + .post('/getmodbustype', (req, res, n) => { + if (!config.permission.modbus) return n('ERR9000'); + let arr = req.body; + if (!arr.data) return n('ERR0000'); + if (!arr.data.id) return n('ERR0028'); + + let query = "select io.`type` \ + from ??.?? io \ + left join ??.?? dev \ + on dev.`uid` = io.`devuid` \ + where \ + dev.`uid` = ? \ + group by io.`type` \ + order by io.`type` "; + let param = [config.db.db5, 'iolist', config.db.db5, 'device', arr.data.id]; + + res.db.query(query, param, (err, row) => { + if (err) return rt.err(res, err, n, 'ERR8000'); + + res.api_res = { + record: tool.checkArray(row) + } + + n(); + }) + }) + .post('/getmodbusport', (req, res, n) => { + if (!config.permission.modbus) return n('ERR9000') + let arr = req.body; + if (!arr.data) return n('ERR0000'); + if (!arr.data.id) return n('ERR0028'); + if (!arr.data.type) return n('ERR0009'); + + let type = arr.data.type; + if (type == 5) type = 1; + if (type == 6) type = 3; + + if (type == 3 || type == 4) { + let query = "select a.`name`, a.`portnum` \ + from ??.?? a \ + left join ??.?? io \ + on io.`uid` = a.`iouid` \ + left join ??.?? dev \ + on dev.`uid` = io.`devuid` \ + where \ + io.`type` = ? \ + and dev.`uid` = ? "; + let param = [config.db.db5, 'aioset', config.db.db5, 'iolist', config.db.db5, 'device', type, arr.data.id]; + + res.db.query(query, param, (err, row) => { + if (err) return rt.err(res, err, n, 'ERR8000'); + + res.api_res = { + record: tool.checkArray(row) + } + + n(); + }); + return; + } + + if (type == 1 || type == 2) { + let query = "select * \ + from ??.?? io \ + left join ??.?? dev \ + on dev.`uid` = io.`devuid` \ + where \ + dev.`uid` = ? \ + and io.`type` = ?"; + let param = [config.db.db5, 'iolist', config.db.db5, 'device', arr.data.id, type]; + + res.db.query(query, param, (err, row) => { + if (err) return rt.err(res, err, n, 'ERR8000'); + let arr = []; + let num = 0; + for (let i in row) { + num += parseInt(row[i].num); + } + for (let i = 0; i < num; i++) { + arr.push({ portnum: (i + 1), name: '' }) + } + + res.api_res = { + record: arr + } + n(); + }) + return; + } + + return n('ERR0009'); + }) .all('*', rt.send); module.exports = router; \ No newline at end of file diff --git a/src/components/AdminPage/ActionLinkAddN/ActionSelect/UnitModbus.js b/src/components/AdminPage/ActionLinkAddN/ActionSelect/UnitModbus.js new file mode 100644 index 0000000..597a612 --- /dev/null +++ b/src/components/AdminPage/ActionLinkAddN/ActionSelect/UnitModbus.js @@ -0,0 +1,138 @@ +import React from 'react'; +import {Form, Input} from 'semantic-ui-react'; +import { getRequest } from '../../../../actions'; + +class UnitLeone extends React.Component { + state = { + list: [], + data: { + dev: '', + devName: '', + func: '', + funcName: '', + addr: '', + value: '' + } + } + + componentDidMount() { + let { showDialog } = this.props; + fetch('/api/system/getselectlist', getRequest({ type: 'modbus' })) + .then(response => response.json()) + .then(json => { + if (json.status != 1) return showDialog(json.message); + this.setState({ + list: json.data.record || [] + }) + }) + } + + changeState = (tag, value) =>{ + let data = {...this.state.data}; + + if(tag == 'func') { + data.funcName = value.name; + data.func = value.func; + } + if(tag == 'dev'){ + data.dev = value.dev == '' ? '' : `mb${value.dev}`; + data.devName = value.name; + } + if(tag == 'addr'){ + data.addr = value; + } + if(tag == 'value'){ + data.value = value; + } + + this.setState({ + data:{ + ...data + } + }, ()=>{ + this.updateData() + }) + } + + updateData = () => { + let data = {...this.state.data}; + data.type = 'modbus'; + + data.act = `${data.func},${data.addr},${data.value}`; + data.actName = `${data.funcName} Addr:${data.addr} Value:${data.value}`; + + delete data.func; + delete data.funcName; + delete data.addr; + delete data.value; + + this.props.updateData(data); + } + + updateAct = (act, name) => { + this.changeState('act', {act, name}); + } + + render() { + let {i18n} = this.props; + let dev = ''; + let m = this.state.data.dev.match(/(\d+)/); + console.log(this.state) + if(m!=null && m.length > 1){ + dev = m[1]; + } + return ( +