Skip to content

Commit

Permalink
Merge pull request #47 from libremfg/fix/packml-command-module-refere…
Browse files Browse the repository at this point in the history
…nces

Fix PackML command references
  • Loading branch information
tomhollingworth authored Oct 25, 2024
2 parents 0de3085 + 2fb7811 commit d8fd030
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 57 deletions.
13 changes: 7 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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}`)
}
Expand Down
112 changes: 65 additions & 47 deletions src/packml-commands.js
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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
Expand All @@ -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])
Expand Down Expand Up @@ -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)) {
Expand All @@ -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)
Expand All @@ -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
}
9 changes: 5 additions & 4 deletions src/packml-tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: '',
Expand All @@ -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: []
}
}
Expand Down

0 comments on commit d8fd030

Please sign in to comment.