forked from pimatic/pimatic-sysinfo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sysinfo.coffee
150 lines (136 loc) · 5.44 KB
/
sysinfo.coffee
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
module.exports = (env) ->
# Require the bluebird promise library
Promise = env.require 'bluebird'
# Require the [cassert library](https://github.com/rhoot/cassert).
assert = env.require 'cassert'
fs = env.require 'fs'
os = env.require 'os'
Promise.promisifyAll(fs)
ns = require('nsutil')
Promise.promisifyAll(ns)
path = require 'path'
class SysinfoPlugin extends env.plugins.Plugin
init: (app, @framework, @config) =>
deviceConfigDef = require("./device-config-schema")
@framework.deviceManager.registerDeviceClass("SystemSensor", {
configDef: deviceConfigDef.SystemSensor,
createCallback: (config) => return new SystemSensor(config, framework)
})
# ##LogWatcher Sensor
class SystemSensor extends env.devices.Sensor
constructor: (@config, framework) ->
@id = config.id
@name = config.name
@attributes = {}
# initialise all attributes
for attr, i in @config.attributes
do (attr) =>
name = attr.name
assert name in [
'cpu', 'memory', "temperature", "dbsize", "diskusage",
"memoryRss","memoryHeapUsed", "memoryHeapTotal", "uptime"
]
@attributes[name] = {
description: name
type: "number"
}
switch name
when "cpu"
lastCpuTimes = null
sum = (cput) -> cput.user + cput.nice + cput.system + cput.idle
reschredule = ( -> Promise.resolve().delay(3000).then( -> getter() ) )
lastValue = null
lastTime = null
getter = ( =>
return ns.cpuTimesAsync().then( (res) =>
if lastValue? and (new Date().getTime() - lastTime) < 3000
return lastValue
if lastCpuTimes?
lastAll = sum(lastCpuTimes)
lastBusy = lastAll - lastCpuTimes.idle
all = sum(res)
busy = all - res.idle
busy_delta = busy - lastBusy
all_delta = all - lastAll
if all_delta is 0
return reschredule()
lastCpuTimes = res
lastTime = new Date().getTime()
return lastValue = Math.round(busy_delta / all_delta * 10000) / 100
else
lastCpuTimes = res
return reschredule()
)
)
@attributes[name].unit = '%'
@attributes[name].acronym = 'CPU'
when "memory"
getter = ( =>
return ns.virtualMemoryAsync().then( (res) =>
return res.total - res.avail
)
)
@attributes[name].unit = 'B'
@attributes[name].acronym = 'MEM'
when "memoryRss"
getter = ( => Promise.resolve(process.memoryUsage().rss) )
@attributes[name].unit = 'B'
@attributes[name].acronym = 'RSS'
when "memoryHeapUsed"
getter = ( => Promise.resolve(process.memoryUsage().heapUsed) )
@attributes[name].unit = 'B'
@attributes[name].acronym = 'HEAP'
when "memoryHeapTotal"
getter = ( => Promise.resolve(process.memoryUsage().heapTotal) )
@attributes[name].unit = 'B'
@attributes[name].acronym = 'THEAP'
when "diskusage"
diskusagepath = attr.path or '/'
getter = ( =>
return ns.diskUsageAsync(diskusagepath).then( (res) =>
return res.used / res.total * 100
)
)
@attributes[name].unit = '%'
@attributes[name].acronym = 'DISK'
when "temperature"
getter = ( =>
return fs.readFileAsync("/sys/class/thermal/thermal_zone0/temp")
.then( (rawTemp) -> rawTemp / 1000 )
)
@attributes[name].unit = '°C'
@attributes[name].acronym = 'T'
when "dbsize"
databaseConfig = framework.config.settings.database
unless databaseConfig.client is "sqlite3"
throw new Error("dbsize is only supported for sqlite3")
filename = path.resolve framework.maindir, '../..', databaseConfig.connection.filename
getter = ( =>
return fs.statAsync(filename).then( (stats) =>
return stats.size
)
)
@attributes[name].unit = 'B'
@attributes[name].acronym = 'DB'
when "uptime"
getter = ( => Promise.resolve(os.uptime()) )
@attributes[name].unit = 's'
@attributes[name].acronym = 'UP'
else
throw new Error("Illegal attribute name: #{name} in SystemSensor.")
# Create a getter for this attribute
@_createGetter(name, getter)
setInterval( (=>
getter().then( (value) =>
@emit name, value
).catch( (error) =>
env.logger.error "error updating syssensor value for #{name}:", error.message
env.logger.debug error.stack
)
), attr.interval or 10000)
super()
# ###Finally
# Create a instance of my plugin
sysinfoPlugin = new SysinfoPlugin
# and return it to the framework.
return sysinfoPlugin