Files
genieacs/profiles.coffee
T

123 lines
3.7 KiB
CoffeeScript

config = require './config'
db = require './db'
getProfiles = (callback) ->
db.memcached.get('profiles', (err, res) ->
throw err if err
if res
callback(res)
return
db.profilesCollection.find().toArray((err, res) ->
if err
callback(err, res)
return
profiles = {}
for p in res
profiles[p['_id']] = p
db.memcached.set('profiles', profiles, config.PROFILES_CACHE_DURATION)
callback(profiles)
)
)
getProfilesHash = (callback) ->
db.memcached('profiles_hash', (err, res) ->
if res
callback(res)
else
getProfiles((profiles) ->
hash = callback(calculateProfilesHash(profiles))
db.memcached.set('profiles_hash', hash, config.PROFILES_CACHE_DURATION, (err, res) ->
callback(hash)
)
)
)
calculateProfilesHash = (profiles) ->
crypto = require('crypto')
hash = crypto.createHash('md5').update(JSON.stringify(profiles)).digest('hex')
return hash
exports.findDeviceConfigurationDiscrepancy = (deviceId, profilesHash, callback) ->
getProfiles((profiles) ->
params = {'_tags' : 1}
for p of profiles
profile = profiles[p]
for c in profile.configurations
if c.type == 'get' or c.type == 'set'
params[c.name] = 1
db.devicesCollection.findOne({'_id' : deviceId}, params, (err, device) ->
tags = device['_tags'] or []
tags.push('default')
deviceProfiles = []
for t in tags
if profiles[t]?
deviceProfiles.push(profiles[t])
combinedConfigurations = combineProfileConfigurations(deviceProfiles)
now = Date.now()
taskList = []
expiry = config.PROFILES_CACHE_DURATION
getParameterValues = []
setParameterValues = []
for c in combinedConfigurations
switch c.type
when 'set'
if c.value != getDeviceParamFromPath(device, "#{c.name}._value")
setParameterValues.push([c.name, c.value])
when 'get'
timeDiff = (now - getDeviceParamFromPath(device, "#{c.name}._timestamp")) / 1000
if (c.age - timeDiff < config.PROFILES_TIME_PADDING)
expiry = Math.min(expiry, c.age)
getParameterValues.push(c.name)
else
expiry = Math.min(expiry, c.age - timeDiff)
else
throw new Error('Unknown configuration type')
if getParameterValues.length
taskList.push {device : deviceId, name : 'getParameterValues', parameterNames: getParameterValues, timestamp : db.mongo.Timestamp()}
if setParameterValues.length
taskList.push {device : deviceId, name : 'setParameterValues', parameterValues: getParameterValues, timestamp : db.mongo.Timestamp()}
if not profilesHash
profilesHash = calculateProfilesHash(profiles)
db.memcached.set('profiles_hash', profilesHash, expiry - config.PROFILES_TIME_PADDING, (err, res) ->
)
db.memcached.set("#{deviceId}_profiles_hash", profilesHash, expiry - config.PROFILES_TIME_PADDING, (err, res) ->
callback(taskList)
)
)
)
combineProfileConfigurations = (profiles) ->
maxWeights = {}
configurations = {}
for p in profiles
for c in p.configurations
configurationHash = if c.name? then "#{c.type}_#{c.name}" else c.type
if not maxWeights[configurationHash]? or p.weight > maxWeights[configurationHash]
configurations[configurationHash] = c
maxWeights[configurationHash] = p.weight
configurationsList = (configurations[c] for c of configurations)
return configurationsList
getDeviceParamFromPath = (device, paramPath) ->
path = paramPath.split('.')
ref = device
for p in path
ref = ref[p]
return ref