def test_set_data(self): """ Test XplMessage.set_data() method. """ self.__xpl_message.set_data({ "command": "dim", "device": "a1", "level": "75" }) self.assertEqual( self.__xpl_message.data, OrderedDict({ "command": "dim", "device": "a1", "level": "75" })) # Check if correctly remove previous data self.__xpl_message.set_data({ "command2": "dim", "device2": "a1", "level2": "75" }) self.assertEqual( self.__xpl_message.data, OrderedDict({ "command2": "dim", "device2": "a1", "level2": "75" }))
def __init__(self, packet=None): """ Message object. Create Message instance from a message string and check if the structure is correct. Raise exception if it is not The message can be None (to allow building a message) @param packet : message packet, as sent on the network @type packet: str """ super(XplMessage, self).__init__() self.type = "" self.hop_count = 1 self.source = "" self.source_vendor_id = "" self.source_device_id = "" self.source_instance_id = "" self.target = "" self.target_vendor_id = "" self.target_device_id = "" self.target_instance_id = "" self.schema = "" self.schema_class = "" self.schema_type = "" self.data = OrderedDict() if packet is not None: self.from_packet(packet)
def set_data(self, data): """ Set message data, replacing previous ones. ??? First build data as str, to be parsed by the regexp. @param data: message data, as name/value pairs @type data: dict or L{OrderedDict} """ data_backup = copy.deepcopy(self.data) try: self.data = OrderedDict() self.add_data(data) except XplMessageError: self.data = copy.deepcopy(data_backup) raise
def fragment_message(message, uid): """ Fill the instance with fragments from the message @param message: XplMessage instance to split @param uid : the unique ID that should identify this message @return an OrderedDict which contains all the fragments """ #we use an OrderedDict to store messages until we know the total number of messages message_list = OrderedDict() msg = FragmentedXplMessage.__init_fragment(message, uid) base_len = len(msg.to_packet()) f_id = 1 for k in message.data: if type(message.data[k]) == list: for l in message.data[k]: if not FragmentedXplMessage.__try_add_item_to_message( msg, k, l): message_list[f_id] = msg msg = FragmentedXplMessage.__init_fragment( message, uid) FragmentedXplMessage.__try_add_item_to_message( msg, k, l) f_id = f_id + 1 else: if not FragmentedXplMessage.__try_add_item_to_message( msg, k, message.data[k]): message_list[f_id] = msg msg = FragmentedXplMessage.__init_fragment(message, uid) FragmentedXplMessage.__try_add_item_to_message( msg, k, message.data[k]) f_id = f_id + 1 message_list[f_id] = msg return FragmentedXplMessage.__update_fragments_ids(message_list, uid)
def test_from_packet(self): """ Test the XplMessage.from_packet() method. """ wrong_packet = \ """xpl-cmnd { target=acme-cm12.server } { command=dim device=a1 level=75 } """ self.assertRaises(XplMessageError, self.__xpl_message.from_packet, wrong_packet) packet = \ """xpl-cmnd { hop=1 source=xpl-xplhal.myhouse target=acme-cm12.server } x10.basic { command=dim device=a1 level=75 } """ self.__xpl_message.from_packet(packet) self.assertEqual(self.__xpl_message.type, 'xpl-cmnd') self.assertEqual(self.__xpl_message.hop_count, 1) self.assertEqual(self.__xpl_message.source, "xpl-xplhal.myhouse") self.assertEqual(self.__xpl_message.source_vendor_id, "xpl") self.assertEqual(self.__xpl_message.source_device_id, "xplhal") self.assertEqual(self.__xpl_message.source_instance_id, "myhouse") self.assertEqual(self.__xpl_message.target, "acme-cm12.server") self.assertEqual(self.__xpl_message.target_vendor_id, "acme") self.assertEqual(self.__xpl_message.target_device_id, "cm12") self.assertEqual(self.__xpl_message.target_instance_id, "server") self.assertEqual(self.__xpl_message.schema, "x10.basic") self.assertEqual(self.__xpl_message.schema_class, "x10") self.assertEqual(self.__xpl_message.schema_type, "basic") self.assertEqual( self.__xpl_message.data, OrderedDict({ "command": "dim", "device": "a1", "level": "75" }))
def from_packet(self, packet): """ Decode message from given packet. @param packet: message packet, as sent on the network @type packet: str @raise XplMessageError: the message packet is incorrect @raise XplMessageError: invalid message packet """ match_global = XplMessage.__regexp_global.match(packet) if match_global is None: raise XplMessageError("Invalid message packet") else: match_global_dict = match_global.groupdict() self.set_type(match_global_dict['type_']) self.set_hop_count(match_global_dict['hop_count']) self.set_source(match_global_dict['source']) self.set_target(match_global_dict['target']) self.set_schema(match_global_dict['schema']) self.data = OrderedDict() data = match_global_dict[ 'data'] + '\n' # The global match remove the last '\n' self.__parse_data(data)
def from_packet(self, packet): """ Decode message from given packet. @param packet: message packet, as sent on the network @type packet: str @raise XplMessageError: the message packet is incorrect @raise XplMessageError: invalid message packet """ match_global = XplMessage.__regexp_global.match(packet) if match_global is None: raise XplMessageError("Invalid message packet") else: match_global_dict = match_global.groupdict() self.set_type(match_global_dict['type_']) self.set_hop_count(match_global_dict['hop_count']) self.set_source(match_global_dict['source']) self.set_target(match_global_dict['target']) self.set_schema(match_global_dict['schema']) self.data = OrderedDict() data = match_global_dict['data'] + '\n' # The global match remove the last '\n' self.__parse_data(data)
def clear_data(self): """ Clear the message data. """ self.data = OrderedDict()
class XplMessage(object): """ xPL Message facility. XplMessage is the object for data send/received on the network. """ __regexp_type = re.compile(REGEXP_TYPE, re.UNICODE | re.VERBOSE) __regexp_hop_count = re.compile(REGEXP_HOP_COUNT, re.UNICODE | re.VERBOSE) __regexp_source = re.compile(REGEXP_SOURCE, re.UNICODE | re.VERBOSE) __regexp_target = re.compile(REGEXP_TARGET, re.UNICODE | re.VERBOSE) __regexp_schema = re.compile(REGEXP_SCHEMA, re.UNICODE | re.VERBOSE) __regexp_data = re.compile(REGEXP_DATA, re.UNICODE | re.VERBOSE) __regexp_single_data = re.compile(REGEXP_SINGLE_DATA, re.UNICODE | re.VERBOSE) __regexp_global = re.compile(REGEXP_GLOBAL, re.DOTALL | re.UNICODE | re.VERBOSE) def __init__(self, packet=None): """ Message object. Create Message instance from a message string and check if the structure is correct. Raise exception if it is not The message can be None (to allow building a message) @param packet : message packet, as sent on the network @type packet: str """ super(XplMessage, self).__init__() self.type = "" self.hop_count = 1 self.source = "" self.source_vendor_id = "" self.source_device_id = "" self.source_instance_id = "" self.target = "" self.target_vendor_id = "" self.target_device_id = "" self.target_instance_id = "" self.schema = "" self.schema_class = "" self.schema_type = "" self.data = OrderedDict() if packet is not None: self.from_packet(packet) def __str__(self): return self.to_packet() def __parse_data(self, data): """ Parse message data. The data are added to existing ones. @param data: message data, as "<name1>=>value1>\n<name2>=<value2>\n..." @type data: str @raise XplMessageError: invalid data @todo: use OrderedDict for data storage """ match_data = XplMessage.__regexp_data.match(data) if match_data is None: raise XplMessageError("Invalid data") match_data_dict = match_data.groupdict() data_list = match_data_dict['data'].split('\n') for data_ in data_list: if data_: self.__parse_single_data(data_) def __parse_single_data(self, data): """ Parse single message data. The data are added to existing ones. @param data: single message data, as "<name>=<value>" @type data: str @raise XplMessageError: invalid data """ match_single_data = XplMessage.__regexp_single_data.match(data) if match_single_data is None: raise XplMessageError("Invalid data (%s)" % data) match_single_data_dict = match_single_data.groupdict() #self.data.append((match_single_data_dict['data_name'], match_single_data_dict['data_value'])) key = match_single_data_dict['data_name'] if key in self.data: if type(self.data[key]) != list: v = self.data[key] self.data[key] = [v] self.data[key].append(match_single_data_dict['data_value']) else: self.data[key] = match_single_data_dict['data_value'] def set_type(self, type_): """ Set the message type. @param type_: message type, in ('xpl-stat', 'xpl-trig', 'xpl-cmnd') @type type_: str @raise XplMessageError: invalid type """ match_type = XplMessage.__regexp_type.match(type_) if match_type is None: raise XplMessageError("Invalid type (%s)" % type_) self.type = type_ def set_hop_count(self, hop_count): """ Set hop count value. @param hop_count: hop count @type hop_count: int or str @raise XplMessageError: invalid hop count value """ match_hop_count = XplMessage.__regexp_hop_count.match(str(hop_count)) if match_hop_count is None: raise XplMessageError("Invalid hop count value (%d)" % int(hop_count)) self.hop_count = int(hop_count) def inc_hop_count(self): """ Increment hop count value. @raise XplMessageError: exceeded hop count value """ hop_count = self.hop_count + 1 match_hop_count = XplMessage.__regexp_hop_count.match(str(hop_count)) if match_hop_count is None: raise XplMessageError("Exceeded hop count value (%s)" % str(hop_count)) self.hop_count = hop_count def set_source(self, source): """ Set source. @param source: message source @type source: str @raise XplMessageError: invalid source """ match_source = XplMessage.__regexp_source.match(source) if match_source is None: raise XplMessageError("Invalid source (%s)" % source) match_source_dict = match_source.groupdict() for key, value in match_source_dict.items(): setattr(self, key, value) def set_target(self, target): """ Set target. @param target: message target @type targer: str @raise XplMessageError: invalid target """ match_target = XplMessage.__regexp_target.match(target) if match_target is None: raise XplMessageError("Invalid target (%s)" % target) match_target_dict = match_target.groupdict() for key, value in match_target_dict.items(): setattr(self, key, value) def set_header(self, hop_count=None, source=None, target=None): """ Set the message header. @param hop_count: hop count @type hop_count: int @param source: message source @type source: str @param target: message target @type targer: str """ if hop_count is not None: self.set_hop_count(hop_count) if source is not None: self.set_source(source) if target is not None: self.set_target(target) def set_schema(self, schema): """ Set message schema. @param schema: message schema @type schema: str @raise XplMessageError: invalid schema """ match_schema = XplMessage.__regexp_schema.match(schema) if match_schema is None: raise XplMessageError("Invalid schema (%s)" % schema) match_schema_dict = match_schema.groupdict() for key, value in match_schema_dict.items(): setattr(self, key, value) def add_single_data(self, name, value): """ Add a single message data. @param name: data name @type name: str @param value: data value @type value: any """ data_str = "%s=%s" % (name, value) self.__parse_single_data(data_str) def add_data(self, data): """ Add message data to the existing ones. First build data as str, to be parsed by the regexp. @param data: message data, as name/value pairs @type data: dict or L{OrderedDict} """ for name, value in data.items(): self.add_single_data(name, value) def set_data(self, data): """ Set message data, replacing previous ones. ??? First build data as str, to be parsed by the regexp. @param data: message data, as name/value pairs @type data: dict or L{OrderedDict} """ data_backup = copy.deepcopy(self.data) try: self.data = OrderedDict() self.add_data(data) except XplMessageError: self.data = copy.deepcopy(data_backup) raise def clear_data(self): """ Clear the message data. """ self.data = OrderedDict() def from_packet(self, packet): """ Decode message from given packet. @param packet: message packet, as sent on the network @type packet: str @raise XplMessageError: the message packet is incorrect @raise XplMessageError: invalid message packet """ match_global = XplMessage.__regexp_global.match(packet) if match_global is None: raise XplMessageError("Invalid message packet") else: match_global_dict = match_global.groupdict() self.set_type(match_global_dict['type_']) self.set_hop_count(match_global_dict['hop_count']) self.set_source(match_global_dict['source']) self.set_target(match_global_dict['target']) self.set_schema(match_global_dict['schema']) self.data = OrderedDict() data = match_global_dict['data'] + '\n' # The global match remove the last '\n' self.__parse_data(data) def to_packet(self): """ Convert the message to packet. @return: message packet, as sent on the network @rtype: str """ packet = "%s\n" % self.type packet += "{\n" packet += "hop=%d\n" % self.hop_count packet += "source=%s\n" % self.source packet += "target=%s\n" % self.target packet += "}\n" packet += "%s\n" % self.schema packet += "{\n" for key, value in self.data.items(): if type(value) == list: for v in value: packet += "%s=%s\n" % (key, v) else: packet += "%s=%s\n" % (key, value) packet += "}\n" return packet def is_valid(self): """ Check if the message is valid. @return: True if message is valid, False otherwise @rtype: bool """ try: self.from_packet(self.to_packet()) except XplMessageError: return False else: return True
class HeyuManager: """ This class manages the heyu configuration file """ ITEMS_SECTION = OrderedDict() ITEMS_SECTION['general'] = [ 'TTY', 'TTY_AUX', 'LOG_DIR', 'HOUSECODE', 'REPORT_PATH', 'DEFAULT_MODULE', 'START_ENGINE', 'DATE_FORMAT', 'LOGDATE_YEAR', 'TAILPATH', 'HEYU_UMASK', 'STATUS_TIMEOUT', 'SPF_TIMEOUT', 'TRANS_DIMLEVEL' ] ITEMS_SECTION['aliases'] = ['ALIAS'] ITEMS_SECTION['scenes'] = ['SCENE', 'USERSYN', 'MAX_PPARMS'] ITEMS_SECTION['scripts'] = ['SCRIPT', 'SCRIPT_MODE', 'SCRIPT_CTRL'] ITEMS_SECTION['scheduler'] = [ 'SCHEDULE_FILE', 'MODE', 'PROGRAM_DAYS', 'COMBINE_EVENTS', 'COMPRESS_MACROS', 'REPL_DELAYED_MACROS', 'WRITE_CHECK_FILES' ] ITEMS_SECTION['dawnduk'] = [ 'LONGITUDE', 'LATITUDE', 'DAWN_OPTION', 'DUSK_OPTION', 'MIN_DAWN', 'MAX_DAWN', 'MIN_DUSK', 'MAX_DUSK' ] def __init__(self, path): """ @param path = The heyu config file path, must be absolute """ self._file = "%s" % path def load(self): """ Load the file and parse it @return a list containing all the *uncommented* lines of config file """ f = open(self._file, "r") lines = f.readlines() f.close() result = [] for line in lines: if not line.startswith("#") and line.strip() != "": result.append(line.strip()) return result def write(self, data): """ Write config datas in the config file @param data : list of config lines @Warning : it will erease the previous config file @raise IOError if the file can'"t be opened """ f = open(self._file, "w") for section in self.ITEMS_SECTION: f.write("##### %s #####\n\n" % section) for item in self.ITEMS_SECTION[section]: for d in data: if d.startswith("%s " % item) or d.startswith( "%s\t" % item): f.write("%s\n" % d) f.write("\n") f.close() def restart(self): """ Restart heyu process, needed to reload config @return the output of heyu restart command on stderr, should be empty if everything goes well """ return ""
class XplMessage(object): """ xPL Message facility. XplMessage is the object for data send/received on the network. """ __regexp_type = re.compile(REGEXP_TYPE, re.UNICODE | re.VERBOSE) __regexp_hop_count = re.compile(REGEXP_HOP_COUNT, re.UNICODE | re.VERBOSE) __regexp_source = re.compile(REGEXP_SOURCE, re.UNICODE | re.VERBOSE) __regexp_target = re.compile(REGEXP_TARGET, re.UNICODE | re.VERBOSE) __regexp_schema = re.compile(REGEXP_SCHEMA, re.UNICODE | re.VERBOSE) __regexp_data = re.compile(REGEXP_DATA, re.UNICODE | re.VERBOSE) __regexp_single_data = re.compile(REGEXP_SINGLE_DATA, re.UNICODE | re.VERBOSE) __regexp_global = re.compile(REGEXP_GLOBAL, re.DOTALL | re.UNICODE | re.VERBOSE) def __init__(self, packet=None): """ Message object. Create Message instance from a message string and check if the structure is correct. Raise exception if it is not The message can be None (to allow building a message) @param packet : message packet, as sent on the network @type packet: str """ super(XplMessage, self).__init__() self.type = "" self.hop_count = 1 self.source = "" self.source_vendor_id = "" self.source_device_id = "" self.source_instance_id = "" self.target = "" self.target_vendor_id = "" self.target_device_id = "" self.target_instance_id = "" self.schema = "" self.schema_class = "" self.schema_type = "" self.data = OrderedDict() if packet is not None: self.from_packet(packet) def __str__(self): return self.to_packet() def __parse_data(self, data): """ Parse message data. The data are added to existing ones. @param data: message data, as "<name1>=>value1>\n<name2>=<value2>\n..." @type data: str @raise XplMessageError: invalid data @todo: use OrderedDict for data storage """ match_data = XplMessage.__regexp_data.match(data) if match_data is None: raise XplMessageError("Invalid data") match_data_dict = match_data.groupdict() data_list = match_data_dict['data'].split('\n') for data_ in data_list: if data_: self.__parse_single_data(data_) def __parse_single_data(self, data): """ Parse single message data. The data are added to existing ones. @param data: single message data, as "<name>=<value>" @type data: str @raise XplMessageError: invalid data """ match_single_data = XplMessage.__regexp_single_data.match(data) if match_single_data is None: raise XplMessageError("Invalid data (%s)" % data) match_single_data_dict = match_single_data.groupdict() #self.data.append((match_single_data_dict['data_name'], match_single_data_dict['data_value'])) key = match_single_data_dict['data_name'] if key in self.data: if type(self.data[key]) != list: v = self.data[key] self.data[key] = [v] self.data[key].append(match_single_data_dict['data_value']) else: self.data[key] = match_single_data_dict['data_value'] def set_type(self, type_): """ Set the message type. @param type_: message type, in ('xpl-stat', 'xpl-trig', 'xpl-cmnd') @type type_: str @raise XplMessageError: invalid type """ match_type = XplMessage.__regexp_type.match(type_) if match_type is None: raise XplMessageError("Invalid type (%s)" % type_) self.type = type_ def set_hop_count(self, hop_count): """ Set hop count value. @param hop_count: hop count @type hop_count: int or str @raise XplMessageError: invalid hop count value """ match_hop_count = XplMessage.__regexp_hop_count.match(str(hop_count)) if match_hop_count is None: raise XplMessageError("Invalid hop count value (%d)" % int(hop_count)) self.hop_count = int(hop_count) def inc_hop_count(self): """ Increment hop count value. @raise XplMessageError: exceeded hop count value """ hop_count = self.hop_count + 1 match_hop_count = XplMessage.__regexp_hop_count.match(str(hop_count)) if match_hop_count is None: raise XplMessageError("Exceeded hop count value (%s)" % str(hop_count)) self.hop_count = hop_count def set_source(self, source): """ Set source. @param source: message source @type source: str @raise XplMessageError: invalid source """ match_source = XplMessage.__regexp_source.match(source) if match_source is None: raise XplMessageError("Invalid source (%s)" % source) match_source_dict = match_source.groupdict() for key, value in match_source_dict.iteritems(): setattr(self, key, value) def set_target(self, target): """ Set target. @param target: message target @type targer: str @raise XplMessageError: invalid target """ match_target = XplMessage.__regexp_target.match(target) if match_target is None: raise XplMessageError("Invalid target (%s)" % target) match_target_dict = match_target.groupdict() for key, value in match_target_dict.iteritems(): setattr(self, key, value) def set_header(self, hop_count=None, source=None, target=None): """ Set the message header. @param hop_count: hop count @type hop_count: int @param source: message source @type source: str @param target: message target @type targer: str """ if hop_count is not None: self.set_hop_count(hop_count) if source is not None: self.set_source(source) if target is not None: self.set_target(target) def set_schema(self, schema): """ Set message schema. @param schema: message schema @type schema: str @raise XplMessageError: invalid schema """ match_schema = XplMessage.__regexp_schema.match(schema) if match_schema is None: raise XplMessageError("Invalid schema (%s)" % schema) match_schema_dict = match_schema.groupdict() for key, value in match_schema_dict.iteritems(): setattr(self, key, value) def add_single_data(self, name, value): """ Add a single message data. @param name: data name @type name: str @param value: data value @type value: any """ data_str = "%s=%s" % (name, value) self.__parse_single_data(data_str) def add_data(self, data): """ Add message data to the existing ones. First build data as str, to be parsed by the regexp. @param data: message data, as name/value pairs @type data: dict or L{OrderedDict} """ for name, value in data.iteritems(): self.add_single_data(name, value) def set_data(self, data): """ Set message data, replacing previous ones. ??? First build data as str, to be parsed by the regexp. @param data: message data, as name/value pairs @type data: dict or L{OrderedDict} """ data_backup = copy.deepcopy(self.data) try: self.data = OrderedDict() self.add_data(data) except XplMessageError: self.data = copy.deepcopy(data_backup) raise def clear_data(self): """ Clear the message data. """ self.data = OrderedDict() def from_packet(self, packet): """ Decode message from given packet. @param packet: message packet, as sent on the network @type packet: str @raise XplMessageError: the message packet is incorrect @raise XplMessageError: invalid message packet """ match_global = XplMessage.__regexp_global.match(packet) if match_global is None: raise XplMessageError("Invalid message packet") else: match_global_dict = match_global.groupdict() self.set_type(match_global_dict['type_']) self.set_hop_count(match_global_dict['hop_count']) self.set_source(match_global_dict['source']) self.set_target(match_global_dict['target']) self.set_schema(match_global_dict['schema']) self.data = OrderedDict() data = match_global_dict[ 'data'] + '\n' # The global match remove the last '\n' self.__parse_data(data) def to_packet(self): """ Convert the message to packet. @return: message packet, as sent on the network @rtype: str """ packet = "%s\n" % self.type packet += "{\n" packet += "hop=%d\n" % self.hop_count packet += "source=%s\n" % self.source packet += "target=%s\n" % self.target packet += "}\n" packet += "%s\n" % self.schema packet += "{\n" for key, value in self.data.iteritems(): if type(value) == list: for v in value: packet += "%s=%s\n" % (key, v) else: packet += "%s=%s\n" % (key, value) packet += "}\n" return packet def is_valid(self): """ Check if the message is valid. @return: True if message is valid, False otherwise @rtype: bool """ try: self.from_packet(self.to_packet()) except XplMessageError: return False else: return True