diff --git a/lib/db.coffee b/lib/db.coffee index 34fe66c..329a50d 100644 --- a/lib/db.coffee +++ b/lib/db.coffee @@ -275,7 +275,8 @@ fetchDevice = (id, timestamp, patterns, callback) -> else if k == '_tags' device['Tags'] ?= {'_timestamp': timestamp, '_writable': false, '_object': true} for t in v - device['Tags'][t] = {'_writable': false, '_value': true, '_type' : 'xsd:boolean', '_timestamp': timestamp} + 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} @@ -343,14 +344,14 @@ saveDevice = (deviceId, deviceData, isNew, callback) -> when 'SerialNumber' update['$set']['_deviceId._SerialNumber'] = v when 'Tags' - if diff[2].value?[1][0] != diff[1].value?[1][0] - v = diff[2].value?[1][0] + if diff[2]?.value?[1]?[0] != diff[1]?.value?[1]?[0] + v = diff[2]?.value?[1][0] if v? update['$addToSet']['_tags'] ?= {'$each' : []} - update['$addToSet']['_tags']['$each'].push(v) + update['$addToSet']['_tags']['$each'].push(diff[0][1]) else update['$pull']['_tags'] ?= {'$in' : []} - update['$pull']['_tags']['$in'].push(v) + update['$pull']['_tags']['$in'].push(diff[0][1]) else if not diff[2] update['$unset'][diff[0].join('.')] = 1 diff --git a/lib/session.coffee b/lib/session.coffee index 9e91331..06b4e95 100644 --- a/lib/session.coffee +++ b/lib/session.coffee @@ -315,6 +315,7 @@ runDeclarations = (sessionData, declarations) -> spv: new Map() gpn: new Set() gpnPatterns: new Map() + tags: new Map() virtualParameterDeclarations: [] instancesToDelete: new Map() @@ -494,6 +495,39 @@ rpcRequest = (sessionData, _declarations, callback) -> device.clearTrackers(sessionData.deviceData, 'prerequisite') return rpcRequest(sessionData, null, callback) + # Update tags + toClear = null + sessionData.syncState.tags.forEach((v, p) -> + c = sessionData.deviceData.attributes.get(p) + timestamp = sessionData.timestamp + sessionData.iteration + 1 + if v and not c? + toClear = device.set(sessionData.deviceData, p, timestamp, {object: [timestamp, false], writable: [timestamp, true], value: [timestamp, [true, 'xsd:boolean']]}, toClear) + else if c? and not v + toClear = device.set(sessionData.deviceData, p, timestamp, toClear) + noMoreTags = true + iter = sessionData.deviceData.paths.subset(['Tags', '*']) + while p = iter.next().value + if sessionData.deviceData.attributes.has(p) + noMoreTags = false + break + if noMoreTags + toClear = device.set(sessionData.deviceData, ['Tags'], timestamp, null, toClear) + ) + + if toClear + return clear(sessionData, toClear, (err) -> + return callback(err) if err + if sessionData.deviceData.changes.has('prerequisite') + delete sessionData.syncState + device.clearTrackers(sessionData.deviceData, 'prerequisite') + return rpcRequest(sessionData, null, callback) + ) + + if sessionData.deviceData.changes.has('prerequisite') + delete sessionData.syncState + device.clearTrackers(sessionData.deviceData, 'prerequisite') + return rpcRequest(sessionData, null, callback) + provisions = generateSetVirtualParameterProvisions(sessionData, sessionData.syncState.virtualParameterDeclarations[inception]) if not provisions sessionData.rpcRequest = generateSetRpcRequest(sessionData) @@ -824,6 +858,9 @@ processDeclarations = (sessionData, allDeclareTimestamps, allDeclareAttributeTim if currentPath.length == 1 if declareAttributeValues.value? syncState.factoryReset = +(new Date(declareAttributeValues.value[0])) + 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 'VirtualParameters' if currentPath.length <= 2 d = null