diff --git a/lib/cwmp.coffee b/lib/cwmp.coffee index b6afc2d..ff138da 100644 --- a/lib/cwmp.coffee +++ b/lib/cwmp.coffee @@ -157,7 +157,7 @@ applyPresets = (currentRequest) -> deviceEvents = {} iter = currentRequest.sessionData.deviceData.paths.subset(['Events', '*']) while (p = iter.next().value) - if currentRequest.sessionData.timestamp == currentRequest.sessionData.deviceData.attributes.get(p)?.value?[1][0] + if currentRequest.sessionData.timestamp <= currentRequest.sessionData.deviceData.attributes.get(p)?.value?[1][0] deviceEvents[p[1]] = true parameters = {} diff --git a/lib/db.coffee b/lib/db.coffee index 329a50d..5afe7fe 100644 --- a/lib/db.coffee +++ b/lib/db.coffee @@ -159,6 +159,10 @@ fetchDevice = (id, timestamp, patterns, callback) -> func([], patterns, projectionTree) + delete projectionTree['DeviceID'] + delete projectionTree['Events'] + delete projectionTree['Tags'] + if projection['']? proj = {} else @@ -252,44 +256,62 @@ fetchDevice = (id, timestamp, patterns, callback) -> loaded.push([p, ((1 << path.length) - 1) ^ ((1 << MAX_DEPTH) - 1)]) for k, v of device - if k == '_lastInform' - device['Events'] ?= {'_timestamp': timestamp, '_writable': false, '_object': true} - device['Events']['Inform'] = {'_writable': false, '_value': v, '_type' : 'xsd:dateTime', '_timestamp': v} - delete device[k] - else if k == '_lastBoot' - device['Events'] ?= {'_timestamp': timestamp, '_writable': false, '_object': true} - device['Events']['1_BOOT'] = {'_writable': false, '_value': v, '_type' : 'xsd:dateTime', '_timestamp': v} - delete device[k] - else if k == '_lastBootstrap' - device['Events'] ?= {'_timestamp': timestamp, '_writable': false, '_object': true} - device['Events']['0_BOOTSTRAP'] = {'_writable': false, '_value': v, '_type' : 'xsd:dateTime', '_timestamp': v} - delete device[k] - else if k == '_registered' - device['Events'] ?= {'_timestamp': timestamp, '_writable': false, '_object': true} - device['Events']['Registered'] = {'_writable': false, '_value': v, '_type' : 'xsd:dateTime', '_timestamp': v} - delete device[k] - else if k == '_id' - device['DeviceID'] ?= {'_timestamp': timestamp, '_writable': false, '_object': true} - device['DeviceID']['ID'] = {'_writable': false, '_value': v, '_type' : 'xsd:string', '_timestamp': timestamp} - delete device[k] - else if k == '_tags' - device['Tags'] ?= {'_timestamp': timestamp, '_writable': false, '_object': true} - for t in v - t = t.replace(/[^a-zA-Z0-9\-]+/g, '_') - device['Tags'][t] = {'_writable': true, '_value': true, '_type' : 'xsd:boolean', '_timestamp': timestamp} - delete device[k] - else if k == '_deviceId' - device['DeviceID'] ?= {'_timestamp': timestamp, '_writable': false, '_object': true} - for kk, vv of v - if kk == '_Manufacturer' - device['DeviceID']['Manufacturer'] = {'_writable': false, '_value': vv, '_type' : 'xsd:string', '_timestamp': timestamp} - else if kk == '_OUI' - device['DeviceID']['OUI'] = {'_writable': false, '_value': vv, '_type' : 'xsd:string', '_timestamp': timestamp} - if kk == '_ProductClass' - device['DeviceID']['ProductClass'] = {'_writable': false, '_value': vv, '_type' : 'xsd:string', '_timestamp': timestamp} - if kk == '_SerialNumber' - device['DeviceID']['SerialNumber'] = {'_writable': false, '_value': vv, '_type' : 'xsd:string', '_timestamp': timestamp} - delete device[k] + switch k + when '_lastInform' + res.push([['Events'], timestamp, + {object: [timestamp, 1], writable: [timestamp, 0]}]) + res.push([['Events', 'Inform'], +v, + {object: [+v, 0], writable: [+v, 0], value: [+v, [+v, 'xsd:dateTime']]}]) + delete device[k] + when '_lastInform' + res.push([['Events'], timestamp, + {object: [timestamp, 1], writable: [timestamp, 0]}]) + res.push([['Events', '1_BOOT'], +v, + {object: [+v, 0], writable: [+v, 0], value: [+v, [+v, 'xsd:dateTime']]}]) + delete device[k] + when '_lastBootstrap' + res.push([['Events'], timestamp, + {object: [timestamp, 1], writable: [timestamp, 0]}]) + res.push([['Events', '0_BOOTSTRAP'], +v, + {object: [+v, 0], writable: [+v, 0], value: [+v, [+v, 'xsd:dateTime']]}]) + delete device[k] + when '_registered' + res.push([['Events'], timestamp, + {object: [timestamp, 1], writable: [timestamp, 0]}]) + # Use current timestamp for registered event attribute timestamps + res.push([['Events', 'Registered'], timestamp, + {object: [timestamp, 0], writable: [timestamp, 0], value: [timestamp, [v, 'xsd:dateTime']]}]) + delete device[k] + when '_id' + res.push([['DeviceID'], timestamp, + {object: [timestamp, 1], writable: [timestamp, 0]}]) + res.push([['DeviceID', 'ID'], timestamp, + {object: [timestamp, 0], writable: [timestamp, 0], value: [timestamp, [v, 'xsd:string']]}]) + delete device[k] + when '_tags' + res.push([['Tags'], timestamp, + {object: [timestamp, 1], writable: [timestamp, 0]}]) + for t in v + t = t.replace(/[^a-zA-Z0-9\-]+/g, '_') + res.push([['Tags', t], timestamp, + {object: [timestamp, 0], writable: [timestamp, 1], value: [timestamp, [true, 'xsd:boolean']]}]) + delete device[k] + when '_deviceId' + res.push([['DeviceID'], timestamp, + {object: [timestamp, 1], writable: [timestamp, 0]}]) + if v['_Manufacturer']? + res.push([['DeviceID', 'Manufacturer'], timestamp, + {object: [timestamp, 0], writable: [timestamp, 0], value: [timestamp, [v['_Manufacturer'], 'xsd:string']]}]) + if v['_OUI']? + res.push([['DeviceID', 'OUI'], timestamp, + {object: [timestamp, 0], writable: [timestamp, 0], value: [timestamp, [v['_OUI'], 'xsd:string']]}]) + if v['_ProductClass']? + res.push([['DeviceID', 'ProductClass'], timestamp, + {object: [timestamp, 0], writable: [timestamp, 0], value: [timestamp, [v['_ProductClass'], 'xsd:string']]}]) + if v['_SerialNumber']? + res.push([['DeviceID', 'SerialNumber'], timestamp, + {object: [timestamp, 0], writable: [timestamp, 0], value: [timestamp, [v['_SerialNumber'], 'xsd:string']]}]) + delete device[k] storeParams(device, [], 0, false, projectionTree) @@ -318,17 +340,28 @@ saveDevice = (deviceId, deviceData, isNew, callback) -> path = diff[0] switch path[0] when 'Events' - if diff[0].length == 2 and diff[2].value?[1][0] != diff[1]?.value?[1][0] - t = new Date(diff[2].value[1][0]) - switch path[1] - when 'Inform' - update['$set']['_lastInform'] = t - when '1_BOOT' - update['$set']['_lastBoot'] = t - when '0_BOOTSTRAP' - update['$set']['_lastBootstrap'] = t - when 'Registered' - update['$set']['_registered'] = t + if diff[0].length == 2 and diff[2]?.value?[1][0] != diff[1]?.value?[1][0] + if not diff[2] + switch path[1] + when 'Inform' + update['$unset']['_lastInform'] = 1 + when '1_BOOT' + update['$unset']['_lastBoot'] = 1 + when '0_BOOTSTRAP' + update['$unset']['_lastBootstrap'] = 1 + when 'Registered' + update['$unset']['_registered'] = 1 + else + t = new Date(diff[2].value[1][0]) + switch path[1] + when 'Inform' + update['$set']['_lastInform'] = t + when '1_BOOT' + update['$set']['_lastBoot'] = t + when '0_BOOTSTRAP' + update['$set']['_lastBootstrap'] = t + when 'Registered' + update['$set']['_registered'] = t when 'DeviceID' if diff[2].value?[1]?[0] != diff[1]?.value?[1]?[0] v = diff[2].value[1][0] @@ -385,7 +418,6 @@ saveDevice = (deviceId, deviceData, isNew, callback) -> update['$unset'][path.concat('_type').join('.')] = 1 update['$unset'][path.concat('_timestamp').join('.')] = 1 - # Remove empty keys for k of update if k == '$addToSet' diff --git a/lib/session.coffee b/lib/session.coffee index 613bee4..a79bb5f 100644 --- a/lib/session.coffee +++ b/lib/session.coffee @@ -80,10 +80,7 @@ loadParameters = (sessionData, callback) -> # Device not available in database, mark as new sessionData.new = true loaded = [[[], (1 << config.get('MAX_DEPTH', sessionData.deviceId)) - 1]] - parameters = [ - [['DeviceID', '*'], sessionData.timestamp], - [['Events', '*'], sessionData.timestamp] - ] + parameters = [] for p in loaded path = sessionData.deviceData.paths.add(p[0]) @@ -114,7 +111,7 @@ generateRpcId = (sessionData) -> inform = (sessionData, rpcReq, callback) -> - timestamp = sessionData.timestamp + timestamp = sessionData.timestamp + sessionData.iteration + 1 params = [] params.push([['DeviceID', 'Manufacturer'], timestamp, @@ -179,8 +176,8 @@ addProvisions = (sessionData, channel, provisions) -> sessionData.channels.push(channel) if sessionData.revisions.length > 1 or sessionData.revisions[0] > 0 - v.collapse(1) for k, v of sessionData.timestamps - v.collapse(1) for k, v of sessionData.attributes + v.collapse(1) for k, v of sessionData.deviceData.timestamps + v.collapse(1) for k, v of sessionData.deviceData.attributes sessionData.rpcCount = 0 sessionData.revisions = [0] sessionData.extensionsCache.length = 0 @@ -434,9 +431,12 @@ rpcRequest = (sessionData, _declarations, callback) -> for ad in device.getAliasDeclarations(d[0], 1) loadPath(sessionData, ad[0]) - return loadParameters(sessionData, (err) -> + return clear(sessionData, toClear, (err) -> return callback(err) if err - return rpcRequest(sessionData, _declarations, callback) + loadParameters(sessionData, (err) -> + return callback(err) if err + rpcRequest(sessionData, _declarations, callback) + ) ) ) @@ -867,6 +867,8 @@ processDeclarations = (sessionData, allDeclareTimestamps, allDeclareAttributeTim when 'Tags' if currentPath.length == 2 and currentPath.wildcard == 0 and declareAttributeValues?.value? syncState.tags.set(currentPath, device.sanitizeParameterValue([declareAttributeValues.value[0], 'xsd:boolean'])[0]) + when 'Events', 'DeviceID' then + # Do nothing when 'VirtualParameters' if currentPath.length <= 2 d = null