add device-related DB storage & DB manager
ref #3069
Change-Id: I8a6c9f7c8c742b082ed92bf44a3afe002257084b
diff --git a/device_profile.py b/device_profile.py
index d6feec6..966886f 100644
--- a/device_profile.py
+++ b/device_profile.py
@@ -20,11 +20,20 @@
"""
This module defines the DeviceProfile class with holds descriptors of device
"""
+from pyndn import Name
class DeviceProfile(object):
def __init__(self, prefix = None, location = None, manufacturer = None, category = None, type_ = None, model = None, serialNumber = None, serviceProfileList = None):
- '''initialize device profile.'''
+ '''initialize device profile.
+ param Name prefix: device's prefix
+ param str location: device's location
+ param str manufacturer: device's manufacturer
+ param str category: device's category
+ param str type: device's type
+ param str model: device's model
+ parma str lsit serviceProfileList: the list of service profile names
+ '''
self._prefix = prefix
self._location = location
self._manufacturer = manufacturer
@@ -39,7 +48,7 @@
self._metadata = ['prefix', 'location', 'manufacturer', 'category', 'type', 'model', 'serialNumber', 'serviceProfileList']
def __str__(self):
- info ='prefix: '+ self._prefix + '\nlocation: '+ self._location + '\nmanufacturer: ' + self._manufacturer + '\ncategory: ' + self._category + '\ntype: ' + self._type + '\nserial number: ' + self._serialNumber + '\nservice profile list: '
+ info ='prefix: '+ self._prefix.toUri() + '\nlocation: '+ str(self._location) + '\nmanufacturer: ' + str(self._manufacturer) + '\ncategory: ' + str(self._category) + '\ntype: ' + str(self._type) + '\nserial number: ' + str(self._serialNumber) + '\nservice profile list: '
info += ', '.join(self._serviceProfileList)
info += '\nmetadata: '
info += ', '.join(self._metadata)
diff --git a/device_user_access_manager.py b/device_user_access_manager.py
new file mode 100644
index 0000000..fa989c9
--- /dev/null
+++ b/device_user_access_manager.py
@@ -0,0 +1,153 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2014-2015 Regents of the University of California.
+# Author: Weiwei Liu <summerwing10@gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# A copy of the GNU Lesser General Public License is in the file COPYING.
+
+"""
+This module defines the DeviceUserAccessManager class which is the interface of
+operations related to identity, keys, and certificates.
+"""
+
+import sys
+from pyndn.name import Name
+from device_profile import DeviceProfile
+from device_user_access_storage import DeviceUserAccessStorage
+
+class DeviceUserAccessManager(object):
+ """
+ Create a new DeviceUserAccessManager
+ """
+ def __init__(self, databaseFilePath = None):
+ deviceUserAccessStorage = DeviceUserAccessStorage(databaseFilePath)
+ self._deviceUserAccessStorage = deviceUserAccessStorage
+
+ def createDevice(self, deviceProfile, seed, configurationToken, commandList = None):
+ """
+ Create a device in the database, including it's corresponding commands and serrvice profiles
+ @param DeviceProfile deviceProfile: the device profile
+ @param SymmetricKey seed: the seed of the device
+ @param SymmetricKey configurationToken: the configuration Token of the device
+ @param list commandList: the command list of the device, must have following structure: each element in the list should be a two-tuple (commandName, commandToken), the commandName should be a string, and commandToken should be a SymmetricKey. Here is an example of a valid commandList : [('turn_on', commandToken1), ('turn_off', commandToken2)]
+ return True if succeed, otherwise False
+ """
+ result = False
+
+ #add device
+ deviceId = self._deviceUserAccessStorage.addDevice(deviceProfile, seed, configurationToken)
+ if deviceId == 0:
+ raise RuntimeError("device already exists in database")
+ return result
+ elif deviceId == -1:
+ raise RuntimeError("error occured during adding device into database")
+ return result
+
+ #add service profile
+ serviceProfileList = deviceProfile.getServiceProfileList()
+ for serviceProfileName in serviceProfileList:
+ serviceProfileId = self._deviceUserAccessStorage.addServiceProfile(deviceId, serviceProfileName)
+ if serviceProfileId == 0:
+ raise RuntimeError("service profile: " + serviceProfileName + " already exists in database")
+ return result
+ elif serviceProfileId == -1:
+ raise RuntimeError("error occured during adding service profile :" + serviceProfileName)
+ return result
+ #add command
+ for commandTuple in commandList:
+ commandId = self._deviceUserAccessStorage.addCommand(deviceId, commandTuple[0], commandTuple[1])
+ if commandId == 0:
+ raise RuntimeError("command: " + commandTuple[0] + " already exists in database")
+ return result
+ elif commandId == -1:
+ raise RuntimeError("error occured during adding command:" +commandTuple[0])
+ return result
+ result = True
+ return result
+
+ def getDeviceProfile(self, prefix):
+ """
+ get device profile of a specified device
+ :param Name prefix: the device prefix
+ :return device profile of the device if exists, otherwise return None
+ :rtype: DeviceProfile
+ """
+ deviceProfile = self._deviceUserAccessStorage.getDeviceProfileFromDevice(prefix)
+ if deviceProfile == None:
+ return deviceProfile
+ else:
+ # get device Id
+ deviceId = self._deviceUserAccessStorage.getDeviceId(deviceProfile.getPrefix())
+ if deviceId == 0:
+ raise RuntimeError("device doesn't exist")
+
+ serviceProfileList = self._deviceUserAccessStorage.getServiceProfilesOfDevice(deviceId)
+ deviceProfile.setServiceProfile(serviceProfileList)
+
+ return deviceProfile
+
+ def getSeed(self, prefix):
+ """
+ get seed of a specified device
+ :param Name prefix: the device prefix
+ :return seed of the device if exists, otherwise return None
+ :rtype: SymmetricKey
+ """
+ return self._deviceUserAccessStorage.getSeed(prefix)
+
+ def getConfigurationToken(self, prefix):
+ """
+ get configuration token of a specified device
+ :param Name prefix: the device prefix
+ :return seed of the device if exists, otherwise return None
+ :rtype: SymmetricKey
+ """
+ return self._deviceUserAccessStorage.getConfigurationToken(prefix)
+
+ def getCommandToken(self, prefix, commandName):
+ """
+ get command token of a specified command
+ :param Name prefix: the device prefix
+ :param str commandName: device name of the command
+ :return command token if command existsm, otherwise None
+ :rtype SymmetricKey
+ """
+ deviceId = self._deviceUserAccessStorage.getDeviceId(prefix)
+ if deviceId == 0:
+ return None
+ return self._deviceUserAccessStorage.getCommandToken(deviceId, commandName)
+
+ def getCommandsOfDevice(self, prefix):
+ """
+ get all the commands of a specified device
+ :param Name prefix: the device prefix
+ :return command name list if any commands exist, otherwise None
+ """
+ deviceId = self._deviceUserAccessStorage.getDeviceId(prefix)
+ if deviceId == 0:
+ return None
+ return self._deviceUserAccessStorage.getCommandsOfDevice(deviceId)
+
+ def getServiceProfilesOfDevice(self, prefix):
+ """
+ get all the service profiles of a specified device
+ :param Name prefix: the device prefix
+ :return service profiles name list if any service profiles exist, otherwise None
+ """
+ deviceId = self._deviceUserAccessStorage.getDeviceId(prefix)
+ if deviceId == 0:
+ return None
+ return self._deviceUserAccessStorage.getServiceProfilesOfDevice(deviceId)
+
diff --git a/device_user_access_storage.py b/device_user_access_storage.py
new file mode 100644
index 0000000..fb0fd9e
--- /dev/null
+++ b/device_user_access_storage.py
@@ -0,0 +1,601 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2014 Regents of the University of California.
+# Author: Teng Liang <philoliang2011@gmail.com>
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# A copy of the GNU General Public License is in the file COPYING.
+"""
+DeviceUserAccessStorage implements a basic storage of devices, users and access
+"""
+
+import os
+import sqlite3
+from pyndn import Name
+from device_profile import DeviceProfile
+from hmac_key import HMACKey
+INIT_DEVICE_TABLE = ["""
+CREATE TABLE IF NOT EXISTS
+ Device(
+ id INTEGER,
+ prefix BLOB NOT NULL UNIQUE,
+ location BLOB,
+ category BLOB,
+ type BLOB,
+ model BLOB,
+ serial_number BLOB,
+ manufacturer BLOB,
+ seed_name BLOB NOT NULL,
+ seed_sequence BLOB NOT NULL,
+ seed_counter BLOB NOT NULL,
+ seed BLOB NOT NULL,
+ configuration_token BLOB NOT NULL,
+ configuration_token_sequence BLOB NOT NULL,
+ configuration_token_counter BLOB NOT NULL,
+
+ PRIMARY KEY (id)
+ );
+"""]
+
+INIT_COMMAND_TABLE = ["""
+CREATE TABLE IF NOT EXISTS
+ Command(
+ id INTEGER,
+ device_id INTEGER NOT NULL,
+ name BLOB NOT NULL,
+ command_token_name BLOB NOT NULL,
+ command_token_sequence BLOB NOT NULL,
+ command_token_counter BLOB NOT NULL,
+ command_token BLOB NOT NULL,
+
+ PRIMARY KEY(id)
+ FOREIGN KEY(device_id) REFERENCES Device(id)
+ );
+"""]
+
+INIT_SERVICE_PROFILE_TABLE = ["""
+CREATE TABLE IF NOT EXISTS
+ ServiceProfile(
+ id INTEGER,
+ device_id INTEGER NOT NULL,
+ name BLOB NOT NULL,
+
+ PRIMARY KEY(id)
+ FOREIGN KEY(device_id) REFERENCES Device(id)
+ );
+"""]
+
+class DeviceUserAccessStorage(object):
+ """
+ Create a new DeviceUserStorage to work with an SQLite file.
+ :param str databaseFilePath: (optional) The path of the SQLite file. If ommitted, use the default path.
+ """
+ def __init__(self, databaseFilePath = None):
+ if databaseFilePath == None or databaseFilePath == "":
+ if not "HOME" in os.environ:
+ home = '.'
+ else:
+ home = os.environ["HOME"]
+
+ dbDirectory = os.path.join(home, '.ndn')
+ if not os.path.exists(dbDirectory):
+ os.makedirs(dbDirectory)
+
+ databaseFilePath = os.path.join(dbDirectory, 'ndnhome-controller.db')
+
+ self._database = sqlite3.connect(databaseFilePath)
+
+ #Check if the Device table exists
+ cursor = self._database.cursor()
+ cursor.execute("SELECT name FROM sqlite_master WHERE TYPE ='table' and NAME = 'Device'")
+ if cursor.fetchone() == None:
+ #no device table exists, create one
+ for command in INIT_DEVICE_TABLE:
+ self._database.execute(command)
+ cursor.close()
+
+ #Check if the Command table exists
+ cursor = self._database.cursor()
+ cursor.execute("SELECT name FROM sqlite_master WHERE TYPE ='table' and NAME = 'Command'")
+ if cursor.fetchone() == None:
+ #no command table exists, create one
+ for command in INIT_COMMAND_TABLE:
+ self._database.execute(command)
+ cursor.close()
+
+ #Check if the ServiceProfile table exists
+ cursor = self._database.cursor()
+ cursor.execute("SELECT name FROM sqlite_master WHERE TYPE ='table' and NAME = 'ServiceProfile'")
+ if cursor.fetchone() == None:
+ #no ServiceProfile table exists, create one
+ for command in INIT_SERVICE_PROFILE_TABLE:
+ self._database.execute(command)
+ cursor.close()
+
+ self._database.commit()
+
+ def doesTableExist(self, tableName):
+ """
+ check if table exists
+ :param str tableName
+ :return True if exists, otherwise False
+ """
+ selectOperation = "SELECT name FROM sqlite_master WHERE TYPE='table' and NAME='" + tableName +"'"
+ #print selectOperation
+ cursor = self._database.cursor()
+ cursor.execute(selectOperation)
+ if cursor.fetchone() == None:
+ result = False
+ else:
+ result = True
+ cursor.close()
+ return result
+
+ def doesDeviceExist(self, prefix):
+ """
+ Check if the specified device already exists.
+
+ :param Name prefix: the prefix of device
+ :return True if the device exists, otherwise False
+ :rtype: bool
+ """
+ result = False
+ #print prefix
+ cursor = self._database.cursor()
+ cursor.execute("SELECT count(*) FROM Device WHERE prefix =?", (prefix.toUri(),))
+ (count,) = cursor.fetchone()
+ if count > 0:
+ result = True
+ #print 'device with %s is founnd, count %d' %(prefix, count)
+
+ cursor.close()
+ return result
+
+ def addDevice(self, deviceProfile, seed, configurationToken):
+ """
+ Add a new device to the Device table, do nothing if the device already exists
+
+ :param DeviceProfile devicePorfile: the deviceProfile of the device
+ :param Key seed: the seed of the device
+ :param Key configurationToken: the configurationToken of the device
+ :return the device id if it's added successfully, 0 if the device already exists, otherwise -1
+ :rtype: INTEGER
+ """
+ result = -1
+ data = (deviceProfile.getPrefix().toUri(),
+ deviceProfile.getLocation(),
+ deviceProfile.getCategory(),
+ deviceProfile.getType(),
+ deviceProfile.getModel(),
+ deviceProfile.getManufacturer(),
+ deviceProfile.getSerialNumber(),
+ seed.getName(),
+ seed.getSequence(),
+ seed.getCounter(),
+ seed.getKey(),
+ configurationToken.getKey(),
+ configurationToken.getSequence(),
+ configurationToken.getCounter()
+ )
+
+ #check if the device already exists, if yes return 0
+ prefixName = deviceProfile.getPrefix()
+ if self.doesDeviceExist(prefixName):
+ return 0
+
+ insertDevice = (
+ "INSERT INTO Device(prefix, location, category, type, model, manufacturer, serial_number, seed_name, seed_sequence, seed_counter,seed, configuration_token, configuration_token_sequence, configuration_token_counter)"
+ "VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
+ )
+ cursor = self._database.cursor()
+ cursor.execute(insertDevice, data)
+ self._database.commit()
+ result = cursor.lastrowid
+ cursor.close()
+ return result
+
+ def getDeviceProfileFromDevice(self, prefix):
+ """
+ get the specified device profile
+ :param Name prefix: the device prefix
+ :return device profile of the device if exists, otherwise return None
+ :rtype: DeviceProfile
+ """
+ operation = (
+ "Select location, category, type, model, manufacturer, serial_number FROM Device "
+ "WHERE prefix = ?"
+ )
+
+ cursor = self._database.cursor()
+ cursor.execute(operation, (prefix.toUri(),))
+ result = cursor.fetchone()
+ cursor.close()
+ # print result
+ if result == None:
+ return None
+ else:
+ deviceProfile = DeviceProfile(prefix)
+ deviceProfile.setLocation(result[0])
+ deviceProfile.setCategory(result[1])
+ deviceProfile.setType(result[2])
+ deviceProfile.setModel(result[3])
+ deviceProfile.setManufacturer(result[4])
+ deviceProfile.setSerialNumber(result[5])
+
+ return deviceProfile
+
+ def getSeed(self, prefix):
+ """
+ get the seed of the specified device
+ :param Name prefix: the device prefix
+ :return seed of the device if exists, otherwise return None
+ :rtype: HMACKey
+
+ """
+ operation = (
+ "Select seed_name, seed_sequence, seed_counter, seed FROM Device "
+ "WHERE prefix = ?"
+ )
+
+ cursor = self._database.cursor()
+ cursor.execute(operation, (prefix.toUri(),))
+ result = cursor.fetchone()
+ cursor.close()
+ print result
+ if result == None:
+ return None
+ else:
+ seed = HMACKey(result[1], result[2], result[3], result[0])
+ return seed
+
+ # raise RuntimeError("getSeed is not implemented")
+
+ def getConfigurationToken(self, prefix):
+ """
+ get the seed of the specified device
+ :param Name prefix: the device prefix
+ :return seed of the device if exists, otherwise return None
+ :rtype: HMACKey
+
+ """
+ operation = (
+ "Select configuration_token_sequence, configuration_token_counter, configuration_token FROM Device "
+ "WHERE prefix = ?"
+ )
+
+ cursor = self._database.cursor()
+ cursor.execute(operation, (prefix.toUri(),))
+ result = cursor.fetchone()
+ cursor.close()
+ print result
+ if result == None:
+ return None
+ else:
+ configurationToken = HMACKey(result[0], result[1], result[2])
+ return configurationToken
+ # raise RuntimeError("getConfigurationToken is not implemented")
+
+ def getDeviceEntry(self, prefix):
+ """
+ get the specified device entry
+ :param Name prefix: the device prefix
+ :return '' return the corresponding row of the device
+ :rtype: str
+ """
+ cursor = self._database.cursor()
+ cursor.execute("SELECT * FROM Device WHERE prefix =?", (prefix.toUri(),))
+ row = cursor.fetchone()
+ cursor.close()
+ return row
+
+ def deleteDevice(self, prefix):
+ """
+ delete specified device.
+ :param Name prefix: The device prefix
+ :return: 1 if successful, 0 if no device to delete, otherwise -1.
+ :rtype: INTEGER
+ """
+ result = -1
+ if not self.doesDeviceExist(prefix):
+ return 0
+ cursor = self._database.cursor()
+ deleteDevice = "DELETE FROM Device WHERE prefix=?"
+ cursor.execute(deleteDevice, (prefix.toUri(),))
+ self._database.commit()
+ cursor.close()
+ return 1
+
+ def getDeviceId(self, prefix):
+ """
+ get the device id of some specified device
+ :param Name prefix: the device prefix
+ :return id of the device, 0 if the device doesn't exist
+ :rtype: INTEGER
+ """
+ if not self.doesDeviceExist(prefix):
+ return 0
+ cursor = self._database.cursor()
+ operation = "SELECT id FROM Device WHERE prefix=?"
+ cursor.execute(operation, (prefix.toUri(),))
+ result = cursor.fetchone()
+ deviceId = result[0]
+ self._database.commit()
+ cursor.close()
+ return deviceId
+
+ def updateDevice(self, prefix, newDeviceProfile = None , newSeed = None , newcConfigurationToken = None ):
+ """
+ update specifided device
+ :param Name prefix
+ :param DeviceProfile newDeviceProfile
+ :param HMACKey newSeed
+ :param newConfigurationToken
+ :return id of the device if successful, 0 if device not found, otherwise -1
+ :rtype int
+ """
+ raise RuntimeError("getConfigurationToken is not implemented")
+
+ def updateOneColumnOfDevice(self, prefix, columnName, newColumnValue):
+ """
+ update the value of a specified column of a specified device
+ :param Name prefix: the device prefix
+ :param str columnName: column to be updated
+ :param newColumnValue: new column value
+ :return id of the device if successful. 0 if device not found, otherwise -1
+ :rtype int
+ """
+ result = -1
+ if not self.doesDeviceExist(prefix):
+ return 0
+
+ updateDevice = "UPDATE Device Set " + columnName + "=? WHERE prefix=?"
+ #print updateDevice
+ cursor = self._database.cursor()
+ #print newColumnValue
+ cursor.execute(updateDevice, (newColumnValue,prefix.toUri()))
+ self._database.commit()
+ result = cursor.lastrowid
+ cursor.close()
+ return result
+
+ def doesCommandExist(self, deviceId, commandName):
+ """
+ check if the specified command already exists.
+
+ :param Integer device_id: the device id
+ :return True if the command exists, otherwise False
+ :rtype: bool
+ """
+ result = False
+
+ cursor = self._database.cursor()
+ cursor.execute("SELECT count(*) FROM Command WHERE device_id =? AND name = ?", (deviceId, commandName))
+ (count,) = cursor.fetchone()
+ if count > 0:
+ result = True
+
+ cursor.close()
+ return result
+
+ def addCommand(self, deviceId, name, commandToken):
+ """
+ Add a new command to the Command table, do nothing if the device already exists
+
+ :param int deviceId: the device id to which the command belongs to
+ :param str name: the command name
+ :param HMACKey commandToken: the command token
+ :return the command id if it's added successfully, 0 if the command already exists, otherwise -1
+ :rtype: int
+ """
+ result = -1
+ data = (deviceId,
+ name,
+ commandToken.getName(),
+ commandToken.getSequence(),
+ commandToken.getCounter(),
+ commandToken.getKey()
+ )
+
+ #check if the command already exists, if yes return 0
+ if self.doesCommandExist(deviceId, name):
+ return 0
+
+ insertCommand = (
+ "INSERT INTO Command(device_id, name, command_token_name, command_token_sequence, command_token_counter, command_token)"
+ "VALUES(?,?,?,?,?,?)"
+ )
+ cursor = self._database.cursor()
+ cursor.execute(insertCommand, data)
+ self._database.commit()
+ result = cursor.lastrowid
+ cursor.close()
+ return result
+
+ def deleteCommand(self, deviceId, name = None):
+ """
+ delete specified commands.
+ :param str name: The command name, if None, delete all commands of the device
+ :param int deviceId: device id of the command
+ :return: 1 if successful, 0 if no command to delete, otherwise -1.
+ :rtype: int
+ """
+ result = -1
+ if not name == None:
+ if not self.doesCommandExist(deviceId, name):
+ return 0
+ cursor = self._database.cursor()
+ deleteCommand = "DELETE FROM Command WHERE device_id=? AND name=?"
+ cursor.execute(deleteCommand, (deviceId, name))
+ self._database.commit()
+ cursor.close()
+ return 1
+ else:
+ selectOperation = "SELECT count(*) FROM Command WHERE deviceId=?"
+ cursor = self._database.cursor()
+ cursor.execute(selectOperation, (deviceId,))
+ (count,) = cursor.fetchone()
+ if not count > 0:
+ return 0
+ deleteCommand = "DELETE FROM Command WHERE deviceId=?"
+ cursor.execute(deleteCommand, (deviceId))
+ self._database.commit()
+ cursor.close()
+ return 1
+
+ return result
+
+ def getCommandsOfDevice(self, deviceId):
+ """
+ get all the commands of a specified device
+ :param int deviceId: device id of the command
+ :return command name list if any commands exist, otherwise None
+
+ """
+ operation = "SELECT name FROM Command WHERE device_id = ?"
+ #operation2 = "SELECT count(*) FROM Command WHERE device_id = ? "
+ cursor = self._database.cursor()
+ #cursor.execute(operation2,(deviceId,))
+ #(count,) = cursor.fetchone
+
+ #if not count > 0:
+ #return None
+ cursor.execute(operation, (deviceId,))
+ result = cursor.fetchall()
+ print result
+ commandList = []
+ if result == None:
+ return commandList
+ else:
+ for row in result:
+ commandList.append(row[0])
+
+ return commandList
+
+ def getCommandToken(self, deviceId, commandName):
+ """
+ get command token of a specified command
+ :param int deviceId: device id of the command
+ :param str commandName: device name of the command
+ :return command token if command existsm, otherwise None
+ :rtype HMACKey
+ """
+ operation = "SELECT command_token_sequence, command_token_counter,command_token, command_token_name FROM Command WHERE device_id = ? AND name = ?"
+ cursor = self._database.cursor()
+ cursor.execute(operation, (deviceId, commandName))
+ result = cursor.fetchone()
+ if result == None:
+ return None
+ else:
+ commandToken = HMACKey(result[0], result[1], result[2], result[3])
+ return commandToken
+
+ def doesServiceProfileExist(self, deviceId, serviceProfileName):
+ """
+ check if the specified service profile already exists.
+
+ :param Integer device_id: the device id
+ :param str serviceProfileName: name of the service profile
+ :return True if the service profile exists, otherwise False
+ :rtype: bool
+ """
+ result = False
+
+ cursor = self._database.cursor()
+ cursor.execute("SELECT count(*) FROM ServiceProfile WHERE device_id =? AND name = ?", (deviceId, serviceProfileName))
+ (count,) = cursor.fetchone()
+ if count > 0:
+ result = True
+
+ cursor.close()
+ return result
+
+ def addServiceProfile(self, deviceId, name):
+ """
+ Add a new command to the ServiceProfile table, do nothing if the device already exists
+
+ :param int deviceId: the device id to which the command belongs to
+ :param str name: the service profile name
+ :return the service profile id if it's added successfully, 0 if the service profile already exists, otherwise -1
+ :rtype: int
+ """
+ result = -1
+ data = (deviceId,
+ name,
+ )
+
+ #check if the service profile already exists, if yes return 0
+ if self.doesServiceProfileExist(deviceId, name):
+ return 0
+
+ insertCommand = (
+ "INSERT INTO ServiceProfile(device_id, name)"
+ "VALUES(?,?)"
+ )
+ cursor = self._database.cursor()
+ cursor.execute(insertCommand, data)
+ self._database.commit()
+ result = cursor.lastrowid
+ cursor.close()
+ return result
+
+ def deleteServiceProfile(self, deviceId, name = None):
+ """
+ delete specified service profile.
+ :param str name: The command name, if None, delete all profiless of the device
+ :param int deviceId: device id
+ :return: 1 if successful, 0 if no service profile to delete, otherwise -1.
+ :rtype: int
+ """
+ result = -1
+ if not name == None:
+ if not self.doesServiceProfileExist(deviceId, name):
+ return 0
+ cursor = self._database.cursor()
+ deleteProfile = "DELETE FROM ServiceProfile WHERE device_id=? AND name=?"
+ cursor.execute(deleteProfile, (deviceId, name))
+ self._database.commit()
+ cursor.close()
+ return 1
+ else:
+ selectOperation = "SELECT count(*) FROM ServiceProfile WHERE deviceId=?"
+ cursor = self._database.cursor()
+ cursor.execute(selectOperation, (deviceId,))
+ (count,) = cursor.fetchone()
+ if not count > 0:
+ return 0
+ deleteProfile = "DELETE FROM ServiceProfile WHERE deviceId=?"
+ cursor.execute(deleteProfile, (deviceId))
+ self._database.commit()
+ cursor.close()
+ return 1
+
+ return result
+
+ def getServiceProfilesOfDevice(self, deviceId):
+ """
+ get all the service profiles of a specified device
+ :param int deviceId: device id of the command
+ :return service profiles name list if any service profiles exist, otherwise None
+ """
+ operation = "SELECT name FROM ServiceProfile WHERE device_id = ?"
+ cursor = self._database.cursor()
+ cursor.execute(operation, (deviceId,))
+ result = cursor.fetchall()
+ #print result
+ serviceProfileList = []
+ if not result == None:
+ for row in result:
+ serviceProfileList.append(row[0])
+ return serviceProfileList
+
+
diff --git a/fill_database_for_test.py b/fill_database_for_test.py
new file mode 100644
index 0000000..6ffc096
--- /dev/null
+++ b/fill_database_for_test.py
@@ -0,0 +1,81 @@
+
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2014 Regents of the University of California.
+# Author: Weiwei Liu <summerwing10@gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# A copy of the GNU General Public License is in the file COPYING.
+
+import os.path
+from pyndn import Name
+from device_user_access_storage import DeviceUserAccessStorage
+from device_profile import DeviceProfile
+from hmac_key import HMACKey
+
+
+class FillDatabaseForTest(object):
+ def __init__(self, count = None):
+ if count == None:
+ self.count = 1
+ else:
+ self.count = count
+ if not "HOME" in os.environ:
+ home = '.'
+ else:
+ home = os.environ["HOME"]
+
+ dbDirectory = os.path.join(home, '.ndn')
+ self.databaseFilePath = os.path.join(dbDirectory, 'ndnhome-controller.db')
+
+ if os.path.isfile(self.databaseFilePath):
+ os.remove(self.databaseFilePath)
+
+ self.storage = DeviceUserAccessStorage()
+
+ def fillDatabase(self):
+ count = self.count
+ prefixStrBase = 'home/sensor/LED/'
+ serviceProfileNameBase = '/standard/sensor/simple-LED-control/v'
+ commandNameBase = 'turn_on'
+ commandNameBase2 = 'turn_off'
+ for i in range(1, count+1):
+ prefixStr = prefixStrBase + str(i)
+ self.add_a_default_device(prefixStr)
+ name = Name(prefixStr)
+ deviceId = self.storage.getDeviceId(name)
+ serviceProfileName = serviceProfileNameBase + str(i)
+ self.storage.addServiceProfile(deviceId, serviceProfileName)
+
+ commandName = commandNameBase + str(i)
+ commandName2 = commandNameBase2 + str(i)
+ commandToken = self.create_a_default_key(commandName)
+ commandToken2 = self.create_a_default_key(commandName2)
+ self.storage.addCommand(deviceId, commandName, commandToken)
+ self.storage.addCommand(deviceId,commandName2,commandToken2)
+
+ def add_a_default_device(self, prefixStr):
+ name = Name(prefixStr)
+ profile = DeviceProfile(prefix = name)
+ seed = self.create_a_default_key('')
+ configurationToken = self.create_a_default_key()
+ self.storage.addDevice(profile, seed, configurationToken)
+
+ def create_a_default_key(self, keyName = None):
+ keyContent = 'this is key content'
+ seed = HMACKey(0,0, keyContent, keyName)
+ return seed
+
+test = FillDatabaseForTest(8)
+test.fillDatabase()
diff --git a/hmac_key.py b/hmac_key.py
new file mode 100644
index 0000000..98d1b51
--- /dev/null
+++ b/hmac_key.py
@@ -0,0 +1,40 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2014 Regents of the University of California.
+# Author: Weiwei Liu <summerwing10@gmail.com>
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# A copy of the GNU General Public License is in the file COPYING.
+
+class HMACKey(object):
+ """
+ HMACKey implements the HMAC symmetric key
+ """
+ def __init__(self, sequence, counter, key, name = None):
+ self._name = name
+ self._sequence = sequence
+ self._counter = counter
+ self._key = key
+
+ def getName(self):
+ return self._name
+
+ def getSequence(self):
+ return self._sequence
+
+ def getCounter(self):
+ return self._counter
+
+ def getKey(self):
+ return self._key
+
diff --git a/show_devices.py b/show_devices.py
new file mode 100644
index 0000000..924ba3a
--- /dev/null
+++ b/show_devices.py
@@ -0,0 +1,63 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2014-2015 Regents of the University of California.
+# Author: Weiwei Liu <summerwing10@gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# A copy of the GNU Lesser General Public License is in the file COPYING.
+
+import sys
+import os
+import sqlite3
+from device_user_access_storage import DeviceUserAccessStorage
+def showDefault(databaseFilePath = None):
+ if databaseFilePath == None or databaseFilePath == "":
+ if not "HOME" in os.environ:
+ home = '.'
+ else:
+ home = os.environ["HOME"]
+
+ dbDirectory = os.path.join(home, '.ndn')
+ if not os.path.exists(dbDirectory):
+ os.makedirs(dbDirectory)
+
+ databaseFilePath = os.path.join(dbDirectory, 'ndnhome-controller.db')
+
+ database = sqlite3.connect(databaseFilePath)
+ storage = DeviceUserAccessStorage(databaseFilePath)
+ cursor = database.cursor()
+ cursor.execute("SELECT id, prefix FROM Device")
+ print 'id: prefix: Commands: ServiceProfile:'
+ for row in cursor.fetchall():
+ commandResult = storage.getCommandsOfDevice(row[0])
+ commandStr =''
+ for command in commandResult:
+ commandStr += command[0] + ';'
+ profileResult = storage.getServiceProfilesOfDevice(row[0])
+ profileStr=''
+ for profile in profileResult:
+ profileStr = profile[0] +';'
+ print '%d %s %s %s' %(row[0], row[1], commandStr, profileStr )
+
+ cursor.close()
+
+
+
+if len(sys.argv) < 2:
+ showDefault()
+
+else:
+ raise RuntimeError("options is not implemented yet")
+
+
diff --git a/tests/test_device_profile.py b/tests/test_device_profile.py
index 52986ce..906d0d6 100644
--- a/tests/test_device_profile.py
+++ b/tests/test_device_profile.py
@@ -1,4 +1,5 @@
from device_profile import DeviceProfile
+from pyndn import Name
def readProfile(profile):
print ' prefix: ', profile.getPrefix()
@@ -19,7 +20,7 @@
readProfile(profile)
print "set prefix to '/home/sensor/LED/23'..."
- profile.setPrefix('/home/sensor/LED/23')
+ profile.setPrefix(Name('/home/sensor/LED/23'))
print "set location to 'Alice's bedroom'..."
profile.setLocation('Alice\'s bedroom')
diff --git a/tests/test_manager.py b/tests/test_manager.py
new file mode 100644
index 0000000..710aa79
--- /dev/null
+++ b/tests/test_manager.py
@@ -0,0 +1,113 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2014 Regents of the University of California.
+# Author: Weiwei Liu <summerwing10@gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# A copy of the GNU General Public License is in the file COPYING.
+
+import unittest as ut
+import os.path
+from pyndn import Name
+from device_user_access_manager import DeviceUserAccessManager
+from device_profile import DeviceProfile
+from hmac_key import HMACKey
+
+class TestManagerMethods(ut.TestCase):
+ def setUp(self):
+ if not "HOME" in os.environ:
+ home = '.'
+ else:
+ home = os.environ["HOME"]
+
+ dbDirectory = os.path.join(home, '.ndn')
+ self.databaseFilePath = os.path.join(dbDirectory, 'ndnhome-controller.db')
+
+ if os.path.isfile(self.databaseFilePath):
+ os.remove(self.databaseFilePath)
+ self.manager = DeviceUserAccessManager()
+
+ def tearDown(self):
+ pass
+
+ def test_01_manager_constructor(self):
+ print("test")
+ if not "HOME" in os.environ:
+ home = '.'
+ else:
+ home = os.environ["HOME"]
+
+ dbDirectory = os.path.join(home, '.ndn')
+ self.databaseFilePath = os.path.join(dbDirectory, 'ndnhome-controller.db')
+ self.manager = DeviceUserAccessManager()
+ self.assertTrue(os.path.isfile(self.databaseFilePath), 'fail to create database file')
+
+ def test_02_methods(self):
+ #create device
+ prefixStr = '/home/sensor/LED/1'
+ name = Name(prefixStr)
+ profile = DeviceProfile(prefix = name)
+ location = 'living_room'
+ profile.setLocation(location)
+ serviceProfileList = ['/standard/sensor/simple-camera-control/v0', '/standard/sensor/simple-motionsensor-control/v0']
+ profile.setServiceProfile(serviceProfileList)
+ keyContent = 'this is key content'
+ seedName = 'led1'
+ seed = HMACKey( 0, 0 ,keyContent, seedName)
+ configurationToken = HMACKey(0, 0, keyContent)
+ commandTokenName1 = 'commandToken1'
+ commandTokenName2 = 'commandToken2'
+ commandToken = HMACKey(0,0, keyContent, commandTokenName1)
+ commandToken2 = HMACKey(0,0,keyContent, commandTokenName2)
+ commandName1 = 'turn_on'
+ commandName2 = 'turn_off'
+ commandTuple = (commandName1, commandToken)
+ commandTuple2 = (commandName2, commandToken2)
+ commandList = [commandTuple, commandTuple2]
+ result = self.manager.createDevice(profile, seed, configurationToken, commandList)
+ self.assertTrue(result, 'fail to create device')
+
+ #getDeviceProfile()
+ deviceProfile = self.manager.getDeviceProfile(name)
+ self.assertTrue(deviceProfile.getLocation() == location, 'wrong location in device profile ')
+ self.assertTrue(deviceProfile.getServiceProfileList() == serviceProfileList, 'wrong service profile list in device profile' )
+
+ #getSeed()
+ seed = self.manager.getSeed(name)
+ self.assertTrue(seed.getName() == seedName, 'wrong seed name')
+
+ #getConfigurationToken()
+ configurationToken = self.manager.getConfigurationToken(name)
+ self.assertTrue(configurationToken.getKey()== keyContent, 'wrong configration token')
+
+ #getCommandToken()
+ commandToken1 = self.manager.getCommandToken(name, commandName1 )
+ commandToken2 = self.manager.getCommandToken(name, commandName2)
+ self.assertTrue(commandToken1.getName() == commandTokenName1, 'wrong commandToken')
+ self.assertTrue(commandToken2.getName() == commandTokenName2, 'wrong commandToken')
+
+ #getCommandsOfDevice()
+ commandNameList = self.manager.getCommandsOfDevice(name)
+ self.assertTrue(commandName1 in commandNameList, 'command:' + commandName1 + ' not found')
+ self.assertTrue(commandName2 in commandNameList, 'command:' + commandName2 + ' not found')
+
+ #getServiceProfilesOfDevice()
+ serviceProfileListReturned = self.manager.getServiceProfilesOfDevice(name)
+ self.assertTrue(serviceProfileList[0] in serviceProfileListReturned, 'service profile:' + serviceProfileList[0] + ' not found')
+ self.assertTrue(serviceProfileList[1] in serviceProfileListReturned, 'service profile:' + serviceProfileList[1] + ' not found')
+
+
+if __name__ == '__main__':
+ ut.main(verbosity=2)
+
diff --git a/tests/test_storage.py b/tests/test_storage.py
new file mode 100644
index 0000000..dbdce7f
--- /dev/null
+++ b/tests/test_storage.py
@@ -0,0 +1,338 @@
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2014 Regents of the University of California.
+# Author: Weiwei Liu <summerwing10@gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# A copy of the GNU General Public License is in the file COPYING.
+
+import unittest as ut
+import os.path
+from pyndn import Name
+from device_user_access_storage import DeviceUserAccessStorage
+from device_profile import DeviceProfile
+from hmac_key import HMACKey
+
+class TestStorageMethods(ut.TestCase):
+ def setUp(self):
+ if not "HOME" in os.environ:
+ home = '.'
+ else:
+ home = os.environ["HOME"]
+
+ dbDirectory = os.path.join(home, '.ndn')
+ self.databaseFilePath = os.path.join(dbDirectory, 'ndnhome-controller.db')
+
+ if os.path.isfile(self.databaseFilePath):
+ os.remove(self.databaseFilePath)
+
+ self.storage = DeviceUserAccessStorage()
+
+ def tearDown(self):
+ pass
+
+ def test_01_storage_constructor(self):
+
+ self.assertTrue(os.path.isfile(self.databaseFilePath), 'fail to create database file')
+ self.assertTrue(self.storage.doesTableExist("Device"), "Device table doesn't exist")
+ self.assertTrue(self.storage.doesTableExist("Command"), "Command table doesn't exist")
+ self.assertTrue(self.storage.doesTableExist("ServiceProfile"), "ServiceProfile table doesn't exist")
+ #test constructor with file path HOME/.ndn/homedb
+ home = os.environ["HOME"]
+ dir = os.path.join(home, '.ndn')
+ dbdir = os.path.join(dir, 'homedb')
+
+ if not os.path.exists(dbdir):
+ os.makedirs(dbdir)
+
+ filePath = os.path.join(dbdir, 'ndnhome-controller.db')
+ storage2 = DeviceUserAccessStorage(filePath)
+ self.assertTrue(os.path.isfile(filePath), 'fail to create database file' )
+ os.remove(filePath)
+
+ def test_02_entry_existence_methods(self):
+ # test the existence of non-existed device (prefix = /home/sensor/LED/1)
+ prefixStr = '/home/sensor/LED/1'
+ name = Name(prefixStr)
+ profile = DeviceProfile(prefix = name)
+ keyContent = 'this is key content'
+ seed = HMACKey( 0, 0 ,keyContent, 'led1')
+ configurationToken = HMACKey(0, 0, keyContent)
+ result = self.storage.doesDeviceExist(name)
+ self.assertFalse(result, "device with prefix '" + prefixStr + "' shouldn't exist")
+
+ #test existence of an existed device
+ self.storage.addDevice(profile, seed, configurationToken)
+ result = self.storage.doesDeviceExist(name)
+ self.assertTrue(result, "device with prefix '" + prefixStr +"' should exist")
+
+ #test existence of a non-existed command
+ deviceId = 1
+ commandName = 'turn_on'
+ result = self.storage.doesCommandExist(deviceId, commandName)
+ self.assertFalse(result, "Command : 'device_id =" + str(deviceId) + ", name = " + commandName + "' shouldn't exist" )
+
+ #test existence of a existed command
+ deviceId = self.storage.getDeviceId(name)
+ commandName = 'turn_on'
+ commandToken = self.create_a_default_key('turn_on')
+ self.storage.addCommand(deviceId, commandName, commandToken)
+ result = self.storage.doesCommandExist(deviceId, commandName)
+ self.assertTrue(result, "Command : 'device_id =" + str(deviceId) + ", name = " + commandName + "' should exist" )
+
+ #test existence of a non-existed service profile
+ deviceId = 1
+ serviceProfileName = '/standard/sensor/simple-LED-control/v0'
+
+ result = self.storage.doesServiceProfileExist(deviceId, serviceProfileName)
+ self.assertFalse(result, "service profile : 'device_id =" + str(deviceId) + ", name = " + serviceProfileName + "' shouldn't exist" )
+
+ #test existence of a existed service profile
+ deviceId = self.storage.getDeviceId(name)
+ serviceProfileName = '/standard/sensor/simple-LED-control/v0'
+
+ self.storage.addServiceProfile(deviceId, serviceProfileName)
+ result = self.storage.doesServiceProfileExist(deviceId, serviceProfileName)
+ self.assertTrue(result, "service profile : 'device_id =" + str(deviceId) + ", name = " + serviceProfileName + "' should exist" )
+
+
+ def test_03_add_device(self):
+ prefixStr = '/home/sensor/LED/1'
+ name = Name(prefixStr)
+ profile = DeviceProfile(prefix = name)
+ keyContent = 'this is key content'
+ seed = HMACKey( 0, 0 ,keyContent, 'led1')
+ configurationToken = HMACKey(0, 0, keyContent)
+
+ result = self.storage.addDevice(profile, seed, configurationToken)
+
+ self.assertTrue(result > 0, 'fail to add device entry')
+ self.assertTrue(self.storage.doesDeviceExist(name), "device doesn't exist in table")
+ row = self.storage.getDeviceEntry(name)
+ self.assertTrue(row[1] == prefixStr, "column prefix has incorrect value")
+ #print row[2:7]
+ self.assertTrue(row[2:8] == (None, None, None, None, None, None), "column 2-7 have incorrect values ")
+ self.assertTrue(row[8] == 'led1', 'colum seed_name has incorrect values')
+ self.assertTrue(row[9:12] == (0,0,keyContent), 'colum seed_sequence or seed_counter has incorrect value')
+ self.assertTrue(row[12:] == (keyContent,0,0), 'one or more configuration token columns have incoorect value')
+ #try to insert the same device
+ result = self.storage.addDevice(profile, seed, configurationToken)
+ self.assertTrue(result == 0, 'unexpected result when trying to insert an already existed device')
+
+ def test_04_delete_device(self):
+ name = Name('/home/sensor/LED/1')
+ profile = DeviceProfile(prefix = name)
+ seed = HMACKey( 0, 0 ,'this is key content', 'led1')
+ configurationToken = HMACKey(0, 0, 'this is key content')
+ self.storage.addDevice(profile, seed, configurationToken)
+ self.assertTrue(self.storage.doesDeviceExist(name), "device doesn't exist in table")
+ result = self.storage.deleteDevice(name)
+ #print 'result : %d' %(result)
+ self.assertTrue(result == 1, 'fail to delete device')
+
+ def test_05_get_deviceid(self):
+ name = Name('/home/sensor/LED/1')
+ profile = DeviceProfile(prefix = name)
+ seed = HMACKey( 0, 0 ,'this is key content', 'led1')
+ configurationToken = HMACKey(0, 0, 'this is key content')
+ self.storage.addDevice(profile, seed, configurationToken)
+ deviceId = self.storage.getDeviceId(name)
+ self.assertTrue(deviceId==1, "get a wrong device id")
+
+ name2 = Name('/home/sensor/LED/2')
+ profile = DeviceProfile(prefix = name2)
+ seed = HMACKey( 0, 0 ,'this is key content', 'led1')
+ configurationToken = HMACKey(0, 0, 'this is key content')
+ self.storage.addDevice(profile, seed, configurationToken)
+ deviceId2 = self.storage.getDeviceId(name2)
+ self.assertTrue(deviceId2 == 2, "get a wrong device id")
+
+ def test_06_update_device(self):
+ prefixStr = '/home/sensor/LED/1'
+ name = Name(prefixStr)
+ self.add_a_default_device(prefixStr)
+
+ #update column prefix of device
+ newPrefixStr = '/home/sensor/LED/2'
+ newSeedName = 'led2'
+ self.storage.updateOneColumnOfDevice(name, 'seed_name', newSeedName)
+ row = self.storage.getDeviceEntry(name)
+ self.assertTrue(row[8] == newSeedName, "fail to update column: seed_name")
+
+ self.storage.updateOneColumnOfDevice(name, 'prefix', newPrefixStr)
+ row = self.storage.getDeviceEntry(Name(newPrefixStr))
+
+ self.assertTrue(row[1] == newPrefixStr, "fail to update coumn: prefix")
+
+ def test_07_add_command(self):
+ prefixStr = '/home/sensor/LED/2'
+ name = Name(prefixStr)
+ self.add_a_default_device(prefixStr)
+ deviceId = self.storage.getDeviceId(name)
+ commandName = 'turn_on'
+ commandToken = self.create_a_default_key('turn_on')
+ self.storage.addCommand(deviceId, commandName, commandToken)
+ result = self.storage.doesCommandExist(deviceId, commandName)
+ self.assertTrue(result == True, "fail to add command")
+
+ def test_08_delete_command(self):
+ prefixStr1 = 'home/sensor/LED/1'
+ name1 = Name(prefixStr1)
+ self.add_a_default_device(prefixStr1)
+ deviceId = self.storage.getDeviceId(name1)
+ commandName = 'turn_on'
+ commandToken = self.create_a_default_key(commandName)
+ self.storage.addCommand(deviceId, commandName, commandToken)
+ self.assertTrue(self.storage.doesCommandExist(deviceId, commandName), 'before delete, the command should exist')
+ self.storage.deleteCommand(deviceId, commandName)
+ self.assertFalse(self.storage.doesCommandExist(deviceId, commandName), "after delete, the command shouldn't exist")
+
+ def test_09_get_commands_of_device(self):
+ #test with an empty table
+ deviceId = 2
+ result = self.storage.getCommandsOfDevice(deviceId)
+ print result
+ self.assertTrue(not result, "there should be no command found")
+
+ #test with a device has two commands
+ prefixStr = 'home/sensor/LED/1'
+ name = Name(prefixStr)
+ self.add_a_default_device(prefixStr)
+ deviceId = self.storage.getDeviceId(name)
+ commandName = 'turn_on'
+ commandName2 = 'turn_off'
+ commandToken = self.create_a_default_key(commandName)
+ commandToken2 = self.create_a_default_key(commandName2)
+ self.storage.addCommand(deviceId, commandName, commandToken)
+ self.storage.addCommand(deviceId, commandName2, commandToken)
+ result = self.storage.getCommandsOfDevice(deviceId)
+ print 'result %s' %(result)
+
+ def test_10_add_service_profile(self):
+ prefixStr = '/home/sensor/LED/2'
+ name = Name(prefixStr)
+ self.add_a_default_device(prefixStr)
+ deviceId = self.storage.getDeviceId(name)
+
+ serviceProfileName = '/standard/sensor/simple-LED-control/v0'
+ self.storage.addServiceProfile(deviceId, serviceProfileName)
+ result = self.storage.doesServiceProfileExist(deviceId, serviceProfileName)
+ self.assertTrue(result == True, "fail to add service profile")
+
+ def test_11_delete_service_profile(self):
+ prefixStr1 = 'home/sensor/LED/1'
+ name1 = Name(prefixStr1)
+ self.add_a_default_device(prefixStr1)
+ deviceId = self.storage.getDeviceId(name1)
+ serviceProfileName = '/standard/sensor/simple-LED-control/v0'
+
+ self.storage.addServiceProfile(deviceId, serviceProfileName)
+ self.assertTrue(self.storage.doesServiceProfileExist(deviceId, serviceProfileName), 'before delete, the service profile should exist')
+ self.storage.deleteServiceProfile(deviceId, serviceProfileName)
+ self.assertFalse(self.storage.doesServiceProfileExist(deviceId, serviceProfileName), "after delete, the service profile shouldn't exist")
+
+ def test_12_get_service_profiles_of_device(self):
+ #test with an empty table
+ deviceId = 2
+ result = self.storage.getServiceProfilesOfDevice(deviceId)
+ print result
+ self.assertTrue(not result, "there should be no command found")
+
+ #test with a device has two commands
+ prefixStr = 'home/sensor/LED/1'
+ name = Name(prefixStr)
+ self.add_a_default_device(prefixStr)
+ deviceId = self.storage.getDeviceId(name)
+ serviceProfileName = '/standard/sensor/simple-LED-control/v0'
+ serviceProfileName2 = '/standard/sensor/simple-LED-control/v2'
+ self.storage.addServiceProfile(deviceId, serviceProfileName)
+ self.storage.addServiceProfile(deviceId, serviceProfileName2)
+ result = self.storage.getServiceProfilesOfDevice(deviceId)
+ print 'result %s' %(result)
+
+ def test_13_get_device_profile_from_device(self):
+ #test with a non exisited device prefix
+ prefixStr = '/home/sensor/LED/2'
+ name = Name(prefixStr)
+ deviceProfile = self.storage.getDeviceProfileFromDevice(name)
+ self.assertTrue(deviceProfile == None, "no device profile should be return with an non-existed prefix ")
+
+ #test with a existed device prefix
+ profile = DeviceProfile(prefix = name, location = 'bedroom', category = 'sensors')
+ seed = self.create_a_default_key('led1')
+ configurationToken = self.create_a_default_key()
+ self.storage.addDevice(profile, seed, configurationToken)
+
+ deviceProfile = self.storage.getDeviceProfileFromDevice(name)
+
+ self.assertTrue(deviceProfile.getLocation() == 'bedroom', 'wrong field: location')
+ self.assertTrue(deviceProfile.getCategory() == 'sensors', 'wrong field: category')
+
+ def test_14_get_seed_and_get_configuration_token(self):
+ #test with a non existed device prefix
+ prefixStr = '/home/sensor/LED/2'
+ name = Name(prefixStr)
+ seed = self.storage.getSeed(name)
+ configurationToken = self.storage.getConfigurationToken(name)
+ self.assertTrue(seed == None, "no seed should be returned with an non-existed prefix ")
+ self.assertTrue(configurationToken == None, "no configuration token should be returned with an non-existed prefix ")
+
+ #test with an existed device prefix
+ profile= DeviceProfile(prefix = name)
+ seed = self.create_a_default_key('led2')
+ configurationToken = self.create_a_default_key()
+ self.storage.addDevice(profile, seed, configurationToken)
+ seed = self.storage.getSeed(name)
+ configurationToken = self.storage.getConfigurationToken(name)
+ keyContent = 'this is key content'
+ self.assertTrue(seed.getKey() == keyContent, 'key content of seed is incorrect')
+ self.assertTrue(configurationToken.getKey() == keyContent, 'key content of configuration token is incorrect')
+ self.assertTrue(seed.getName() == 'led2', 'name of seed is incorrect')
+ self.assertTrue(configurationToken.getName() == None, 'name of configuration token is incorrect')
+
+ def test_15_get_Command_Token(self):
+ #test with a non existed command
+ deviceId = 5
+ commandName = "turn_on"
+ commandToken = self.storage.getCommandToken(deviceId, commandName)
+ self.assertTrue(commandToken == None, 'no commandToken should be returned with an non-existed command')
+
+ #test with an existed command
+ prefixStr = 'home/sensor/LED/1'
+ name = Name(prefixStr)
+ self.add_a_default_device(prefixStr)
+ deviceId = self.storage.getDeviceId(name)
+ commandToken = self.create_a_default_key(commandName)
+ self.storage.addCommand(deviceId, commandName, commandToken)
+
+ commandTokenReturned = self.storage.getCommandToken(deviceId, commandName)
+ #print commandTokenReturned.getName()
+ self.assertTrue(commandTokenReturned.getName() == commandName, 'wrong command token')
+
+ def add_a_default_device(self, prefixStr):
+ name = Name(prefixStr)
+ profile = DeviceProfile(prefix = name)
+ seed = self.create_a_default_key('led1')
+ configurationToken = self.create_a_default_key()
+ self.storage.addDevice(profile, seed, configurationToken)
+
+ def create_a_default_key(self, keyName = None):
+ keyContent = 'this is key content'
+ seed = HMACKey(0,0, keyContent, keyName)
+ return seed
+
+if __name__ == '__main__':
+ ut.main(verbosity=2)
+
+