diff --git a/src/index.js b/src/index.js index cf6d6c7..17f143f 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,7 @@ const logging = require('./logging') const packmlModel = require('./packml-model') const packmlTags = require('./packml-tags') +const packmlCommands = require('./packml-commands') const simulation = require('./simulation') const helper = require('./helper') const mqtt = require('./clients/mqtt'); @@ -46,7 +47,7 @@ const stateCommandTopic = new RegExp(String.raw`^${global.config.topicPrefix}\/C const modeCommandTopic = new RegExp(String.raw`^${global.config.topicPrefix}\/Command\/(UnitMode)$`) const machineSpeedCommandTopic = new RegExp(String.raw`^${global.config.topicPrefix}\/Command\/MachSpeed$`) const packmlParameters = new RegExp(String.raw`^${global.config.topicPrefix}\/Command\/Parameter\/(\d*)\/(ID|Name|Unit|Value)$`) -const packmlProducts = new RegExp(String.raw`^${global.config.topicPrefix}\/Command\/Product\/(\d*)\/(ProductID|ProcessParameter\/(\d*)\/(ID|Name|Unit|Value)|Ingredient\/(\d*)\/(IngredientID|Parameter\/(\d*)\/(ID|Name|Unit|Value)))$`) +const packmlProducts = new RegExp(String.raw`^${global.config.topicPrefix}\/Command\/Product\/(\d*)\/(ID|ProcessParameter\/(\d*)\/(ID|Name|Unit|Value)|Ingredient\/(\d*)\/(ID|Parameter\/(\d*)\/(ID|Name|Unit|Value)))$`) // PackML State Model let state = new packmlModel.StateMachine() @@ -145,15 +146,15 @@ client.on('close', () => { // Handle PackML Commands client.on('message', (topic, message) => { if (topic.match(stateCommandTopic)) { - stateCommand(topic, message, state) + packmlCommands.stateCommand(logger, topic, message, state, stateCommandTopic) } else if (topic.match(modeCommandTopic)) { - modeCommand(topic, message, mode) + packmlCommands.modeCommand(logger, message, mode) } else if (topic.match(machineSpeedCommandTopic)) { - machineSpeedCommand(topic, message, tags) + packmlCommands.machineSpeedCommand(logger, topic, message, tags) } else if (topic.match(packmlParameters)) { - parameterCommand(topic, message, tags) + packmlCommands.parameterCommand(logger, topic, message, tags, packmlParameters, changed) } else if (topic.match(packmlProducts)) { - productCommand(topic, message, tags) + packmlCommands.productCommand(logger, topic, message, tags, packmlProducts, changed) } else { logger.debug(`No handle defined for ${topic}`) } diff --git a/src/packml-commands.js b/src/packml-commands.js index a793cff..c605d45 100644 --- a/src/packml-commands.js +++ b/src/packml-commands.js @@ -1,8 +1,13 @@ #!/usr/bin/env node 'use strict' +// Imports +const packmlModel = require('./packml-model') +const packmlTags = require('./packml-tags') +const helper = require('./helper') + // handle state commands -function stateCommand(topic, message, state) { +exports.stateCommand = (logger, topic, message, state, stateCommandTopic) => { // State Commands const command = topic.match(stateCommandTopic)[1] try { @@ -18,21 +23,21 @@ function stateCommand(topic, message, state) { } // handle mode commands -function modeCommand(message, mode) { +exports.modeCommand = (logger, message, mode) => { if (isNaN(message)) { - message = message.toLowerCase() + message = message.toString().toLowerCase() } else { message = packmlModel.getModeTextByModeInt(message).toLowerCase() } if (packmlModel.isUnitMode(message)) { mode.goto(message) } else { - logger.error('Cannot change to unknown UnitMode') + logger.error(`Cannot change to unknown UnitMode: ${message}`) } } // handle machine speed commands -function machineSpeedCommand(topic, message, tags) { +exports.machineSpeedCommand = (logger, topic, message, tags) => { if (Number.isNaN(message)) { logger.error(`Bad request: ${topic} Must be an number`) return @@ -46,7 +51,7 @@ function machineSpeedCommand(topic, message, tags) { } // handle parameter commands -function parameterCommand(topic, message, tags) { +exports.parameterCommand = (logger, topic, message, tags, packmlParameters, changed) => { // Parameters const bits = topic.match(packmlParameters) const index = parseInt(bits[1]) @@ -81,53 +86,61 @@ function parameterCommand(topic, message, tags) { } // handle product commands -function productCommand(topic, message, tags) { +exports.productCommand = (logger, topic, message, tags, packmlProducts, changed) => { // Products const bits = topic.match(packmlProducts).filter(match => match !== undefined) const index = parseInt(bits[1]) - if (bits.length === 3) { - productCommandForProduct(index, topic, message, tags) - } else if (bits.length === 5) { - const nextIndex = bits[3] - if (bits[0].indexOf('Ingredient')) { - productCommandForIngredient(nextIndex, message, tags) - } else { - productCommandForProductParameter(nextIndex, bits, topic, message, tags) - } - } else if (bits.length === 7) { - productCommandForIngredientParameter(bits, topic, message, tags) - } -} -function productCommandForProduct(index, topic, message, tags) { + // Add in empty product if it doesn't exist while (tags.status.product.length <= index) { tags.status.product.push(new Proxy(new packmlTags.Product(tags.status.product.length), { set (target, prop, value) { target[prop] = value - changed('Status/Product/' + target._productIndex + '/' + prop, value) + changed('Status/Product/' + target._index + '/', prop, value) return true } })) } + if (bits.length === 3) { + productCommandForProduct(logger, index, topic, message, tags) + } else if (bits.length === 5) { + const nextIndex = bits[3] + const isIngredient = bits[0].indexOf('Ingredient') !== -1 + if (isIngredient) { + productCommandForIngredient(index, nextIndex, bits, message, tags, changed) + } else { + productCommandForProductParameter(logger, index, nextIndex, bits, topic, message, tags, changed) + } + } else if (bits.length === 7) { + productCommandForIngredientParameter(logger, index, bits, topic, message, tags, changed) + } +} + +function productCommandForProduct(logger, index, topic, message, tags) { message = parseInt(message) if (isNaN(message)) { logger.error(`Bad request: ${topic} Must be an number`) return } - tags.status.product[index].productId = message + tags.status.product[index].id = message } -function productCommandForIngredient(nextIndex, message, tags) { - while (tags.status.product.length <= index) { - tags.status.product.push(new packmlTags.Product()) - } +function productCommandForIngredient(index, nextIndex, bits, message, tags, changed) { while (tags.status.product[index].ingredient.length <= nextIndex) { - tags.status.product[index].ingredient.push(new packmlTags.Ingredient()) + tags.status.product[index].ingredient.push(new Proxy( + new packmlTags.Ingredient(tags.status.product[index].ingredient.length), + { + set (target, prop, value) { + changed('Status/Product/' + index + '/Ingredient/' + target._index + '/', prop, value) + return Reflect.set(...arguments) + } + } + )) } tags.status.product[index].ingredient[nextIndex][helper.camelCase(bits[4])] = parseInt(message) } -function productCommandForProductParameter(nextIndex, bits, topic, message, tags) { +function productCommandForProductParameter(logger, index, nextIndex, bits, topic, message, tags, changed) { if (bits[4] === 'ID') { message = parseInt(message) if (isNaN(message)) { @@ -141,22 +154,20 @@ function productCommandForProductParameter(nextIndex, bits, topic, message, tags return } } - while (tags.status.product.length <= index) { - tags.status.product.push(new packmlTags.Product()) - } while (tags.status.product[index].processParameter.length <= nextIndex) { - tags.status.product[index].processParameter.push(new packmlTags.Parameter(tags.status.product[index].processParameter.length), { + tags.status.product[index].processParameter.push(new Proxy( + new packmlTags.Parameter(tags.status.product[index].processParameter.length, index), { set (target, prop, value) { - changed('Status/Product/' + index + '/ProcessParameter/' + tags.status.product[index].processParameter.length + '/', prop, value) + changed('Status/Product/' + index + '/ProcessParameter/' + target._index + '/', prop, value) return Reflect.set(...arguments) } - }) + })) } tags.status.product[index].processParameter[nextIndex][helper.camelCase(bits[4])] = message } -function productCommandForIngredientParameter(bits, topic, message, tags) { - const ingredientIndex = parseInt(bits[2]) +function productCommandForIngredientParameter(logger, index, bits, topic, message, tags, changed) { + const ingredientIndex = parseInt(bits[3]) const parameterIndex = parseInt(bits[5]) if (bits[6] === 'ID') { message = parseInt(message) @@ -171,19 +182,26 @@ function productCommandForIngredientParameter(bits, topic, message, tags) { return } } - while (tags.status.product.length <= index) { - tags.status.product.push(new packmlTags.Product()) - } while (tags.status.product[index].ingredient.length <= ingredientIndex) { - tags.status.product[index].ingredient.push(new packmlTags.Parameter(), { - set (target, prop, value) { - changed('Status/Product/' + index + '/Ingredient/' + tags.status.product[index].ingredient.length - 1 + '/', prop, value) - return Reflect.set(...arguments) + tags.status.product[index].ingredient.push(new Proxy( + new packmlTags.Ingredient(tags.status.product[index].ingredient.length), { + set (target, prop, value) { + changed('Status/Product/' + index + '/Ingredient/' + target._index + '/', prop, value) + return Reflect.set(...arguments) + } } - }) + )) } - while (tags.status.product[index].ingredient[ingredientIndex].parameter <= parameterIndex) { - tags.status.product[index].ingredient[ingredientIndex].parameter.push(new packmlTags.Parameter()) + + while (tags.status.product[index].ingredient[ingredientIndex].parameter.length <= parameterIndex) { + tags.status.product[index].ingredient[ingredientIndex].parameter.push(new Proxy( + new packmlTags.Parameter(tags.status.product[index].ingredient[ingredientIndex].parameter.length, index, ingredientIndex), { + set(target, prop, value) { + changed('Status/Product/' + index + '/Ingredient/' + ingredientIndex + '/Parameter/' + target._index + '/', prop, value) + return Reflect.set(...arguments) + } + } + )) } tags.status.product[index].ingredient[ingredientIndex].parameter[parameterIndex][helper.camelCase(bits[6])] = message } \ No newline at end of file diff --git a/src/packml-tags.js b/src/packml-tags.js index 6d2b287..48ba83d 100644 --- a/src/packml-tags.js +++ b/src/packml-tags.js @@ -35,13 +35,14 @@ function EquipmentInterlock() { } } -function Parameter(index ,productIndex) { +function Parameter(index, productIndex, ingredientIndex) { if (index === undefined || index === null) { throw TypeError('Must construct a Parameter with an index') } return { _index: index, _productIndex: productIndex !== undefined && productIndex !== null ? productIndex : null, + _ingredientIndex: ingredientIndex !== undefined && ingredientIndex !== null ? ingredientIndex : null, id: 0, name: '', unit: '', @@ -63,12 +64,12 @@ function Ingredient(index, productIndex) { function Product(index) { if (index === undefined || index === null) { - throw TypeError('Must construct a Prodct with an index') + throw TypeError('Must construct a Product with an index') } return { _index: index, - productId: 0, - parameter: [], + id: 0, + processParameter: [], ingredient: [] } }