Files
genieacs/presets.coffee
T

120 lines
3.8 KiB
CoffeeScript

config = require './config'
common = require './common'
db = require './db'
mongoQuery = require './mongo-query'
getPresets = (callback) ->
db.memcached.get('presets', (err, res) ->
throw new Error(err) if err
if res
callback(res)
return
db.presetsCollection.find().toArray((err, presets) ->
throw new Error(err) if err
db.memcached.set('presets', presets, config.PRESETS_CACHE_DURATION)
callback(presets)
)
)
getPresetsHash = (callback) ->
db.memcached('presets_hash', (err, res) ->
if res
callback(res)
else
getPresets((presets) ->
hash = callback(calculatePresetsHash(presets))
db.memcached.set('presets_hash', hash, config.PRESETS_CACHE_DURATION, (err, res) ->
callback(hash)
)
)
)
calculatePresetsHash = (presets) ->
crypto = require('crypto')
hash = crypto.createHash('md5').update(JSON.stringify(presets)).digest('hex')
return hash
exports.assertPresets = (deviceId, presetsHash, callback) ->
getPresets((presets) ->
# only fetch relevant params
projection = {}
for p in presets
mongoQuery.projection(p.precondition, projection)
for c in p.configurations
switch c.type
when 'value', 'age'
projection[c.name] = 1
when 'firmware'
projection['InternetGatewayDevice.DeviceInfo.SoftwareVersion'] = 1
else
throw new Error('Unknown configuration type')
db.devicesCollection.findOne({'_id' : deviceId}, projection, (err, device) ->
devicePresets = []
for p in presets
if mongoQuery.test(device, p.precondition)
devicePresets.push(p)
configurations = accumulateConfigurations(devicePresets)
now = Date.now()
taskList = []
expiry = config.PRESETS_CACHE_DURATION
getParameterValues = []
setParameterValues = []
for c in configurations
switch c.type
when 'value'
src = common.getParamValueFromPath(device, "#{c.name}._value")
if src isnt undefined # ignore parameters that don't exist
dst = common.matchType(src, c.value)
if src != dst
setParameterValues.push([c.name, dst])
when 'age'
timeDiff = (now - common.getParamValueFromPath(device, "#{c.name}._timestamp")) / 1000
if (c.age - timeDiff < config.PRESETS_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: setParameterValues, timestamp : db.mongo.Timestamp()}
if not presetsHash
presetsHash = calculatePresetsHash(presets)
db.memcached.set('presets_hash', presetsHash, expiry - config.PRESETS_TIME_PADDING, (err, res) ->
)
db.memcached.set("#{deviceId}_presets_hash", presetsHash, expiry - config.PRESETS_TIME_PADDING, (err, res) ->
callback(taskList)
)
)
)
accumulateConfigurations = (presets) ->
maxWeights = {}
configurations = {}
for p in presets
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