-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathbacnet.js
105 lines (92 loc) · 3.7 KB
/
bacnet.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
const addon = require('./build/Release/binding.node')
const bacnet = Object.create(addon)
const EventEmitter = require('events').EventEmitter
const util = require('util')
function BACnetInstance (config) {
EventEmitter.call(this)
const bacnetAddon = addon.init(flattenConfig(config))
bacnetAddon.initClient(this)
if (config && config.device) bacnetAddon.initDevice()
bacnetAddon.listen()
const confirmedCallbacks = {}
setupMethods.call(this, bacnetAddon, confirmedCallbacks)
setupHandlers.call(this, confirmedCallbacks)
}
function setupMethods (bacnetAddon, confirmedCallbacks) {
function addCallback (invokeId, callback) {
if (callback && invokeId > 0) {
if (typeof callback !== 'function') throw new TypeError('non-function passed as callback argument')
confirmedCallbacks[invokeId] = callback
}
return invokeId
}
this.closeQueue = bacnetAddon.closeQueue
this.whois = bacnetAddon.whois
this.isBound = bacnetAddon.isBound
this.readProperty = function (deviceInstance, objectType, objectInstance, property, arrayIndex, callback) {
if (!objectType) throw new TypeError('Expected an object type, got : ' + objectType)
const invokeId = bacnetAddon.readProperty(deviceInstance, bacnet.objectTypeToNumber(objectType), objectInstance, bacnet.propertyKeyToNumber(property), arrayIndex)
if (invokeId === 0) throw new Error('Invoking BACnet read failed')
return addCallback(invokeId, callback)
}
this.writeProperty = function (deviceInstance, objectType, objectInstance, property, arrayIndex, value, callback) {
if (!objectType) throw new TypeError('Expected an object type, got : ' + objectType)
if (value.constructor !== bacnet.BacnetValue) {
value = new bacnet.BacnetValue(value)
}
const invokeId = bacnetAddon.writeProperty(deviceInstance, bacnet.objectTypeToNumber(objectType), objectInstance, bacnet.propertyKeyToNumber(property), arrayIndex, value)
if (invokeId === 0) throw new Error('Invoking BACnet read failed')
return addCallback(invokeId, callback)
}
}
function setupHandlers (confirmedCallbacks) {
function executeCallback () {
const invocationCallback = confirmedCallbacks[ this ]
if (invocationCallback) {
delete confirmedCallbacks[ this ]
try {
invocationCallback.apply(null, arguments)
} catch (err) {
console.log('Error in callback', err.stack)
this.emit('error', err)
}
}
}
this.on('ack', function onAck (invokeId, response) {
executeCallback.call(invokeId, null, response)
})
this.on('abort', function onAbort (invokeId, reason) {
console.log('abort', invokeId)
executeCallback.call(invokeId, new Error(reason))
})
this.on('reject', function onReject (invokeId, reason) {
console.log('abort', invokeId)
executeCallback.call(invokeId, new Error(reason))
})
this.on('error-ack', function onErrorAck (invokeId, error) {
console.log('error-ack', invokeId, error)
executeCallback.call(invokeId, new Error('Error received in acknowledgment for request #' + invokeId + ' ' + error[ 'error-class' ] + '/' + error[ 'error-code' ]))
})
}
function flattenConfig (config) {
var flatConfig = config && config.datalink || {} // I've flattened the config as I had trouble getting nested properties in the c++
flatConfig.device_instance_id = config.device_instance_id
return flatConfig
}
util.inherits(BACnetInstance, EventEmitter)
/**
* {
* datalink: {
* iface: process.env.BACNET_INTERFACE,
* ip_port: process.env.BACNET_PORT || 0xBAC0
* },
* device: false,
* device_instance_id: 12
* }
* @param config
* @returns {*|EventEmitter}
*/
bacnet.init = function init (config) {
return new BACnetInstance(config)
}
module.exports = bacnet