Skip to content

Commit

Permalink
feat: parse value functions #739 (#741)
Browse files Browse the repository at this point in the history
  • Loading branch information
robertsLando authored Sep 25, 2020
1 parent b7dc921 commit c356a5b
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 10 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ The Gateway values table can be used with all gateway types to customize specifi
- **Post operation**: If you want to convert your value (eg. '/10' '/100' '*10' '*100')
- **Poll**: Enable this to set the value `enablePoll` flag
- **Verify Changes**: Used to verify changes of this values
- **Parse Send**: Enable this to allow users to specify a custom `function(value)` to parse the value sent to MQTT. The function must be sync
- **Parse receive**: Enable this to allow users to specify a custom `function(value)` to parse the value received via MQTT. The function must be sync
## :file_folder: Nodes Management
Expand Down
64 changes: 54 additions & 10 deletions lib/Gateway.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,17 @@ function onValueChanged (valueId, node, changed) {
// Parse valueId value and create the payload
var tmpVal = valueId.value

if (valueConf && isValidOperation(valueConf.postOperation)) {
tmpVal = eval(valueId.value + valueConf.postOperation)
if (valueConf) {
if (isValidOperation(valueConf.postOperation)) {
tmpVal = eval(valueId.value + valueConf.postOperation)
}

if (valueConf.parseSend) {
var parsedVal = evalFunction(valueConf.sendFunction, valueId, tmpVal)
if (parsedVal != null) {
tmpVal = parsedVal
}
}
}

// Check if I need to update discovery topics of this device
Expand Down Expand Up @@ -430,6 +439,28 @@ function isValidOperation (op) {
return op && !/[^0-9.()\-+*/,]/g.test(op)
}

/**
* Evaluate the return value of a custom parse Function
*
* @param {String} code The function code
* @param {Object} valueId The valueId object
* @param {*} value The actual value to parse
* @returns
*/
function evalFunction (code, valueId, value) {
var result = null

try {
/* eslint-disable no-new-func */
var parseFunc = new Function('value', code)
result = parseFunc(value)
} catch (error) {
debug('Error eval function of value ', valueId.value_id, error.message)
}

return result
}

/**
* Converts an integer to 2 digits hex number
*
Expand Down Expand Up @@ -633,16 +664,29 @@ Gateway.prototype.parsePayload = function (payload, valueId, valueConf) {
}
}

if (valueConf && isValidOperation(valueConf.postOperation)) {
let op = valueConf.postOperation
if (valueConf) {
if (isValidOperation(valueConf.postOperation)) {
let op = valueConf.postOperation

// revert operation to write
if (op.includes('/')) op = op.replace(/\//, '*')
else if (op.includes('*')) op = op.replace(/\*/g, '/')
else if (op.includes('+')) op = op.replace(/\+/, '-')
else if (op.includes('-')) op = op.replace(/-/, '+')

// revert operation to write
if (op.includes('/')) op = op.replace(/\//, '*')
else if (op.includes('*')) op = op.replace(/\*/g, '/')
else if (op.includes('+')) op = op.replace(/\+/, '-')
else if (op.includes('-')) op = op.replace(/-/, '+')
payload = eval(payload + op)
}

payload = eval(payload + op)
if (valueConf.parseReceive) {
var parsedVal = evalFunction(
valueConf.receiveFunction,
valueId,
payload
)
if (parsedVal != null) {
payload = parsedVal
}
}
}
} catch (error) {
debug('Error while parsing payload', payload, 'for valueID', valueId)
Expand Down
51 changes: 51 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
"native-url": "^0.3.4",
"nedb": "^1.8.0",
"openzwave-shared": "^1.7.1",
"prismjs": "^1.21.0",
"serialport": "^9.0.1",
"serve-favicon": "^2.5.0",
"socket.io": "^2.3.0",
Expand All @@ -116,6 +117,7 @@
"uniqid": "^5.2.0",
"vue": "^2.6.12",
"vue-d3-network": "^0.1.28",
"vue-prism-editor": "^1.2.2",
"vue-router": "^3.4.3",
"vuetify": "^2.3.10",
"vuex": "^3.5.1"
Expand Down
67 changes: 67 additions & 0 deletions src/components/dialogs/DialogGatewayValue.vue
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,50 @@
v-model="editedValue.verifyChanges"
></v-switch>
</v-flex>

<v-flex xs6>
<v-switch
label="Parse send"
hint="Create a function that parse the value sent via MQTT"
persistent-hint
v-model="editedValue.parseSend"
></v-switch>
</v-flex>

<v-container v-if="editedValue.parseSend">
<p>
Write the function here. Args are <code>value</code>. The
function is sync and must return the parsed <code>value</code>
</p>
<prism-editor
lineNumbers
v-model="editedValue.sendFunction"
language="js"
:highlight="highlighter"
></prism-editor>
</v-container>

<v-flex xs6>
<v-switch
label="Parse receive"
hint="Create a function that parse the received value from MQTT"
persistent-hint
v-model="editedValue.parseReceive"
></v-switch>
</v-flex>

<v-container v-if="editedValue.parseReceive">
<p>
Write the function here. Args are <code>value</code>. The
function is sync and must return the parsed <code>value</code>
</p>
<prism-editor
lineNumbers
v-model="editedValue.receiveFunction"
language="js"
:highlight="highlighter"
></prism-editor>
</v-container>
</v-layout>
</v-form>
</v-container>
Expand All @@ -134,7 +178,20 @@
</template>

<script>
// import Prism Editor
import { PrismEditor } from 'vue-prism-editor'
import 'vue-prism-editor/dist/prismeditor.min.css' // import the styles somewhere
// import highlighting library (you can use any library you want just return html string)
import { highlight, languages } from 'prismjs/components/prism-core'
import 'prismjs/components/prism-clike'
import 'prismjs/components/prism-javascript'
import 'prismjs/themes/prism-tomorrow.css' // import syntax highlighting styles
export default {
components: {
PrismEditor
},
props: {
value: Boolean,
gw_type: Number,
Expand Down Expand Up @@ -220,9 +277,19 @@ export default {
}
},
methods: {
highlighter (code) {
return highlight(code, languages.js) // returns html
},
isSensor (v) {
return v && (v.class_id === 0x31 || v.class_id === 0x32)
}
}
}
</script>

<style>
/* optional class for removing the outline */
.prism-editor__textarea:focus {
outline: none;
}
</style>

0 comments on commit c356a5b

Please sign in to comment.