Esempio n. 1
0
def generate_protocol_file_src(directory, include_extension, src_extension):
    """
    Function will create the protocol source file in .../src/
    File has 3 main parts
        -declare msg_data_offset
        -create function unpack for all messages
        -create function proto_typestr for all messages
    """
    #load header structure and the messages in variables from xml file
    import xml.etree.ElementTree as ET
    tree = ET.parse('message_definition.xml')
    protocol = tree.findall('message')
    header = tree.find('header')
    tab = '   '
    #open file
    f = open(directory + "src/" + 'protonet_protocol' + src_extension, 'w')
    # warning
    f.write(
        '/* This file was autogenerated. All changes will be undone. */\n\n')
    f.write('#include <protonet_protocol' + include_extension + '>\n\n')

    #declare msg_data_offset
    f.write('const uint8_t msg_data_offset = 12;\n\n')
    #create function unpack for all messages
    f.write('void unpack_proto_msg_t(\n')
    f.write(tab + 'proto_msg_t* msg,\n')
    f.write(tab + 'proto_msg_buf_t* buf)\n')
    f.write('{\n')
    f.write(tab + 'uint8_t* unpack_offset = msg->data+msg_data_offset;\n')
    f.write(tab + 'switch(msg->header.message_type)\n')
    f.write(tab + '{\n')
    for message in protocol:
        name = message.get('name')
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        f.write(tab + 'case Proto_' + name + ':\n')
        f.write(tab + tab + 'unpack_' + variable_name +
                '(unpack_offset, &buf->' + variable_name + ');\n')
        f.write(tab + tab + 'break;\n')
    f.write(tab + 'default:\n')
    f.write(tab + tab + 'break;\n')
    f.write(tab + '}\n')
    f.write('}\n\n')

    #create function proto_typestr for all messages
    f.write('char* proto_typestr(proto_msg_type_t msg_type)\n')
    f.write('{\n')
    for message in protocol:
        name = message.get('name')
        print_name = name.replace("_", " ")
        f.write(tab + 'if(msg_type == Proto_' + name + ')\n')
        f.write(tab + '{\n')
        f.write(tab + tab + 'return "' + print_name + '";\n')
        f.write(tab + '}\n')
    f.write(tab + 'return 0;\n')
    f.write('}')

    print("Created: " + 'protonet_protocol' + src_extension)
Esempio n. 2
0
def generate_protonet_file_src(directory, include_extension, src_extension):
    """
    Function will create the protonet source file in .../src/
    File has 4 main parts
        -native node class methods
        -null_call_back storage init
        -handle_proto_msg_t for each message sequence
        -send_message methods    
    """
    #load header structure and the messages in variables from xml file
    import xml.etree.ElementTree as ET
    tree = ET.parse('message_definition.xml')
    protocol = tree.findall('message')
    header = tree.find('header')
    tab = '   '            
    #open file
    f = open(directory + "src/" + 'protonet' + src_extension, 'w')
    # warning
    f.write('/* This file was autogenerated. All changes will be undone. */\n\n')
    f.write('#include <stdio.h>\n')
    f.write('#include <stdlib.h>\n')
    f.write('#include <time.h>\n\n')
    #include files
    f.write('#include <protonet' +include_extension+'>\n')
    f.write('#include <protonet_parser' +include_extension+'>\n')
    f.write('#include <protonet_message' +include_extension+'>\n')
    f.write('#include <datalink' +include_extension+'>\n')
    f.write('#include <serial' +include_extension+'>\n')
    f.write('#include <udp' +include_extension+'>\n')
    f.write('#include <queue' +include_extension+'>\n')
    f.write('#include <thread' +include_extension+'>\n\n')
    f.write('using namespace protonet;\n\n')
    # native methods
    f.write(r'''node::node(uint8_t node_id)
{ 
	memset(datalinks,0,sizeof(datalinks));
	num_datalinks = 0;

	null_callback_storage();

	/* destroy pointer and node in the event of invalid id */
	if(node_id == 0)
	{
		this->~node();
		return;
	}
	this->node_id = node_id;

	thread_create(&handler_thread, &node::handler_helper, this);
	queue = proto_msg_queue();
}

/* Create a node with a specified mode, TBD */
node::node(uint8_t node_id, int32_t mode)
{ 
	memset(datalinks,0,sizeof(datalinks));
	num_datalinks = 0;

	null_callback_storage();

	if(node_id == 0)
	{
		this->~node();
		return;
	}
	this->node_id = node_id;

	//thread_create(&handler_thread, &node::handler_helper, this);
	queue = proto_msg_queue();
}
node::~node()
{
	int32_t i;
	for(i = 0; i<num_datalinks; i++)
	{
		datalinks[i]->close();
	}

}

/* Need to call start to create the protonet handler, usually after establish functions */
void node::start()
{
	try
	{
		//thread_create(&upkeep_thread, &node::upkeep_helper, this);
	}
	catch(int e)
	{
		printf("thread_create out: %d\n", e);
	
	}
}

/* Entry point for the event handler that performs callbacks based on incoming messages */
void* node::protonet_handler()
{
	proto_msg_t proto_msg;	
	while(1)
	{
		/* Blocking call to the message queue, unblock when messages are in queue */
		queue.remove(&proto_msg);
		{
			{				
				/* Behavior on an outgoing message from client*/
				if(proto_msg.direction == Proto_Out)
				{
//#ifdef DEBUG
					printf("Node %d Outbound: Source id: %d, Dest. id %d, Message type: %s\n", this->node_id,proto_msg.header.node_src_id, proto_msg.header.node_dest_id, proto_typestr((proto_msg_type_t)proto_msg.header.message_type));
//#endif
					int32_t i;
					if(num_datalinks>0)
					{
						for(i = 0;i<num_datalinks;i++)
						{
							datalinks[i]->send(proto_msg.header.node_dest_id, proto_msg.data, proto_msg.tx_len);
						}
					}
				}
				/* Behavior on an incoming message from client*/
				else if(proto_msg.direction == Proto_In)				
				{
//#ifdef DEBUG
					printf("Node %d Inbound: Source id: %d, Dest. id %d, Message type: %s\n", this->node_id,proto_msg.header.node_src_id, proto_msg.header.node_dest_id, proto_typestr((proto_msg_type_t)proto_msg.header.message_type));
//#endif
					if((proto_msg.header.node_dest_id == this->node_id) || (proto_msg.header.node_dest_id == 0))
					{

						proto_msg_buf_t rx_buf;
						/* Unpack and identify the type of incoming message */
						unpack_proto_msg_t(&proto_msg, &rx_buf);
						/* Perform a callback based on message type */
						handle_proto_msg_t(&proto_msg, &rx_buf);
					}
				}
			}
		}
	}
	return 0;
}

void* node::upkeep_handler()
{
	while(1)
	{
		//this->send_enter();
#ifdef _WIN32
		_sleep(5000);
#endif
#ifdef __unix__
		sleep(5000);
#endif
	}
	return 0;
}

void node::add_serial(int8_t* link_id, uint32_t baud_rate, char device_path[50])
{
	/* Initialize a datalink pointer as a Serial link */
	datalinks[num_datalinks] = new Serial();

	/* Cast the datalink as a Serial datalink and open it with required options */
	if(((Serial*)(datalinks[num_datalinks]))->open(baud_rate, device_path) == 0)
	{
		/* Provide a reference to the queue for access to protonet handler, runs the datalink */
		datalinks[num_datalinks]->set_link_id(num_datalinks);
		datalinks[num_datalinks]->set_queue(&this->queue);
		datalinks[num_datalinks]->run();

		/* Provide the link_id for future reference, simply increment to keep track */
		*link_id = num_datalinks;
		num_datalinks++;
	}
}


void node::add_udp(int8_t* link_id, uint16_t port)
{
	/* Follows the same format as the above function, except UDP oriented */
	datalinks[num_datalinks] = new UDP(port);
	if(datalinks[num_datalinks]->is_connected())
	{
		datalinks[num_datalinks]->set_link_id(num_datalinks);
		datalinks[num_datalinks]->set_queue(&this->queue);
		datalinks[num_datalinks]->run();
		*link_id = num_datalinks;
		num_datalinks++;
	}
}
	
void node::add_udp(int8_t* link_id, uint16_t port, char addr[16])
{
	/* 
	Follows the same format as the above function, 
	except targets an interface specified by IP
	*/
	datalinks[num_datalinks] = new UDP(port, addr);
	if(datalinks[num_datalinks]->is_connected())
	{
		datalinks[num_datalinks]->set_link_id(num_datalinks);
		datalinks[num_datalinks]->set_queue(&this->queue);
		datalinks[num_datalinks]->run();
		*link_id = num_datalinks;
		num_datalinks++;
	}
}

void node::establish_serial(int8_t link_id, uint8_t node_id)
{
	/* 
	Check that the datalink is of the correct type & connected, 
	and set the node_id 
	*/
	if(datalinks[link_id]->get_datalink_type() == SERIAL_TYPE && datalinks[link_id]->is_connected())
	{
		datalinks[link_id]->establish(node_id);
	}
	
}
void node::establish_udp(int8_t link_id, uint8_t node_id, uint16_t port, char addr[16])
{
	/* This is similar to the Serial establish function, except for UDP */
	if(datalinks[link_id]->get_datalink_type()== UDP_TYPE && datalinks[link_id]->is_connected())
	{
		((UDP*)datalinks[link_id])->establish(node_id, port, addr);
	}
}

uint8_t node::get_num_datalinks()
{
	return(this->num_datalinks);
}

int32_t node::query_datalink_connected(int8_t link_id)
{
	/* Returns 1 if the datalink is connected */
	return(datalinks[link_id]->is_connected());
}

datalink_type_t node::query_datalink_type(int8_t link_id)
{
	return(datalinks[link_id]->get_datalink_type());
}

/* Helper functions from C style from C++ entry point with class member linkage */
void* node::handler_helper(void* context)
{
	return ((node*)context)->protonet_handler();
}

void* node::upkeep_helper(void* context)
{
	return ((node*)context)->upkeep_handler();
}'''+'\n\n')
    
    #message call back storage init
    f.write('void node::null_callback_storage()\n')
    f.write('{\n')
    for message in protocol:
        name = message.get('name')
        variable_name = lower_case_acronym(name)
        f.write(tab+'on_'+ variable_name+' = NULL;\n')
    f.write('}\n')
    
    #handles each message type with giant switch case
    f.write('void node::handle_proto_msg_t(proto_msg_t* rx_msg, proto_msg_buf_t* rx_buf)\n{\n' + tab +'switch(rx_msg->header.message_type)\n'+tab+'{\n')
    for message in protocol:
        name = message.get('name')
        variable_name = lower_case_acronym(name)
        f.write(tab + 'case Proto_'+name+':\n'+tab+tab+'{\n')
        f.write(tab+tab+tab+'if(on_'+variable_name+' == NULL)\n')
        f.write(tab+tab+tab+'{\n')
        f.write(tab+tab+tab+'}\n')
        f.write(tab+tab+tab+'else\n')
        f.write(tab+tab+tab+'{\n')
        f.write(tab+tab+tab+tab+'this->on_'+ variable_name+'(rx_msg->link_id, rx_msg->header, rx_buf->'+variable_name+', this);\n')
        f.write(tab+tab+tab+'}\n')
        f.write(tab+tab+tab+'break;\n')
        f.write(tab+tab+'}\n')
    f.write(tab+'}\n')
    f.write('}\n\n')
    
    #create all send_message methods
    for message in protocol:
        name = message.get('name')
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        f.write('void node::send_'+ variable_name+'(\n')
        f.write(tab+'uint8_t dest_id,')
        for field in message:
            f.write('\n'+tab+field.get('type')+' '+ field.get('name')+',')
        f.seek(-1, 1)
        f.write(')\n')
        f.write('{\n')
        f.write(tab+'proto_msg_t proto_msg;\n')
        f.write(tab+type_t_name+' '+variable_name+';\n')
        for field in message:
            f.write(tab+variable_name+'.'+ field.get('name')+' = '+ field.get('name')+';\n')
        f.write(tab+'encode_'+variable_name+'(this->node_id, dest_id, 3, 0, &'+variable_name+', &proto_msg);\n')
        f.write(tab+'queue.add(&proto_msg);\n')
        f.write(tab+'return;\n')
        f.write('}\n\n')
    print("Created: " + 'protonet' + src_extension)
Esempio n. 3
0
def generate_proto_wrapper_include(directory, include_extension,
                                   src_extension):
    """
    Protowrapper is used to create a Managed C which calls c++ 
    Function will create the protowrapper source file in .../Protowrapper
    File has 4 main parts
        -header struct
        -message struct
        -message callbacks
        -class node
            -public native methods
            -public send_message methods
            -public message call backs definitions
            -public register message definitions
            -private members
            -private message helper methods definitions            
    """
    #load header structure and the messages in variables from xml file
    import xml.etree.ElementTree as ET
    tree = ET.parse('message_definition.xml')
    protocol = tree.findall('message')
    header = tree.find('header')
    tab = '   '
    #open file
    f = open(directory + 'proto_wrapper' + include_extension, 'w')
    # warning
    f.write(
        '/** @file This file was autogenerated. All changes will be undone.')
    f.write(
        '\nWrapper Class is used to call c++ function through managed c++/cli for c# */\n\n'
    )
    f.write('#ifndef _PROTO_WRAPPER_H_\n')
    f.write('#define _PROTO_WRAPPER_H_\n\n')
    #include
    f.write('#include <stdio.h>\n')
    f.write('#include <vcclr.h>\n')
    f.write('#include <protonet' + include_extension + '>\n')
    f.write('#using <mscorlib.dll>\n\n')

    f.write('using namespace System;\n')
    f.write('using namespace System::Runtime::InteropServices;\n\n')

    #declare namespace
    f.write('namespace Protonet\n{\n')

    f.write(
        tab +
        "/** Redefines C++ header struct in c# any changes in c++ should also be made here*/ \n"
    )
    f.write(tab + 'public ref struct Header\n' + tab + '{\n')
    #create header struct
    for field in header:
        f.write(tab + tab + field.get('type') + ' ' + field.get('name') +
                ';\n')
    #header constructors
    f.write(tab + tab + 'Header(){}\n')
    f.write(tab + tab + 'Header(const Header% to_copy)\n')
    f.write(tab + tab + '{\n')
    for field in header:
        f.write(tab + tab + tab + field.get('name') + ' = ' + 'to_copy.' +
                field.get('name') + ';\n')
    f.write(tab + tab + '}\n')

    f.write(tab + tab + 'Header(const proto_header_t to_copy)\n')
    f.write(tab + tab + '{\n')
    for field in header:
        f.write(tab + tab + tab + field.get('name') + ' = ' + 'to_copy.' +
                field.get('name') + ';\n')
    f.write(tab + tab + '}\n')
    f.write(tab + '};\n\n')

    #message structures
    for message in protocol:
        name = message.get('name')
        cs_name = message.get('name').replace("_", "")
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        f.write(tab + "/** Redefine c++ " + name +
                " struct as c# struct which is auto generated*/ \n")
        f.write(tab + 'public ref struct ' + cs_name + '\n' + tab + '{\n')
        for field in message:
            f.write(tab + tab + field.get('type') + ' ' + field.get('name') +
                    ';\n')
        f.write(tab + tab + cs_name + '(){}\n')
        f.write(tab + tab + cs_name + '(const ' + cs_name + '% to_copy)\n')
        f.write(tab + tab + '{\n')
        for field in message:
            f.write(tab + tab + tab + field.get('name') + ' = ' + 'to_copy.' +
                    field.get('name') + ';\n')
        f.write(tab + tab + '}\n')

        f.write(tab + tab + cs_name + '(const ' + type_t_name + ' to_copy)\n')
        f.write(tab + tab + '{\n')
        for field in message:
            f.write(tab + tab + tab + field.get('name') + ' = ' + 'to_copy.' +
                    field.get('name') + ';\n')
        f.write(tab + tab + '}\n')
        f.write(tab + '};\n\n')
    #message call backs
    f.write(
        tab +
        "/* Note [UnmanagedFunctionPointerAttribute(CallingConvention::Cdecl)] is used to set c# pointer type to Cdecl\n"
    )
    f.write(
        tab +
        "which is the default c++ pointer type. If you get stack pointer error then the pointer type does not match c++ pointer type.*/ \n\n"
    )
    for message in protocol:
        name = message.get('name')
        cs_name = message.get('name').replace("_", "")
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        f.write(
            tab +
            "[UnmanagedFunctionPointerAttribute(CallingConvention::Cdecl)]")
        f.write(
            tab +
            "/** Redefine c++ callback pointer as managed c++/cli pointer for c#.*/\n"
        )
        f.write(tab + 'public delegate void* ' + cs_name +
                'Callback(int8_t, proto_header_t, ' + type_t_name +
                ', protonet::node*);\n')
    #class node
    f.write(
        "\n" + tab +
        "/** Redefine c++ node class as c++/cli managed class for c#. Just look up c++ class for documentation.*/\n"
    )
    f.write(tab + 'public ref class Node\n' + tab + '{\n')
    f.write(tab + 'public:\n')
    f.write(tab + tab + 'Node(uint8_t node_id);\n')
    f.write(tab + tab + '~Node();\n')
    f.write(tab + tab + 'void Start();\n')
    f.write(
        tab + tab +
        'void AddUDPDatalink([System::Runtime::InteropServices::Out]int8_t% link_id,uint16_t port);\n'
    )
    f.write(
        tab + tab +
        'void AddUDPDatalink([System::Runtime::InteropServices::Out]int8_t% link_id,uint16_t port, String^ addr);\n'
    )
    f.write(
        tab + tab +
        'void EstablishUDPEndpoint(int8_t link_id, uint8_t node_id, uint16_t port, String^ addr);\n'
    )
    f.write(
        tab + tab +
        'void AddSerialDatalink([System::Runtime::InteropServices::Out]int8_t% link_id, uint32_t baud_rate, String^ device_path);\n'
    )
    f.write(
        tab + tab +
        'void EstablishSerialEndpoint(int8_t link_id, uint8_t node_id);\n\n')

    #node send_message
    for message in protocol:
        name = message.get('name')
        cs_name = message.get('name').replace("_", "")
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        f.write(tab + 'void Send' + cs_name + '(\n')
        f.write(tab + tab + 'uint8_t dest_id,')
        for field in message:
            f.write('\n' + tab + tab + field.get('type') + ' ' +
                    field.get('name') + ',')
        f.seek(-1, 1)
        f.write(');\n\n')
    #node message methods enter, exit, ping, ect
    for message in protocol:
        name = message.get('name')
        cs_name = message.get('name').replace("_", "")
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        f.write(tab + 'delegate void ' + cs_name +
                'Delegate(int8_t, Header^%, ' + cs_name +
                '^%, Protonet::Node^);\n')

    f.write('\n')

    #node register methods
    for message in protocol:
        name = message.get('name')
        cs_name = message.get('name').replace("_", "")
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        f.write(tab + 'void Register' + cs_name + 'Event(' + cs_name +
                'Delegate^ ' + cs_name + 'Event);\n')

    #node private members
    f.write('\n' + tab + 'private:\n')
    f.write(tab + tab + 'protonet::node* node;\n\n')

    for message in protocol:
        name = message.get('name')
        cs_name = message.get('name').replace("_", "")
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        f.write(tab + tab + 'IntPtr On' + cs_name + 'Ptr;\n')
        f.write(tab + tab + cs_name + 'Callback^ On' + cs_name + 'Callback;\n')
        f.write(tab + tab + cs_name + 'Delegate^ On' + cs_name +
                'Delegate;\n\n')
    #node message helper methods
    for message in protocol:
        name = message.get('name')
        cs_name = message.get('name').replace("_", "")
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        f.write(tab + tab + 'void* ' + cs_name +
                'Helper(int8_t link_id, proto_header_t header, ' +
                type_t_name + ' ' + variable_name +
                ', protonet::node* ptr);\n')
    f.write('\n' + tab + '};\n}\n#endif')

    print("Created: " + 'proto_wrapper' + src_extension)
Esempio n. 4
0
def generate_message_includes(directory, include_extension, src_extension):
    """
    Function will create all message header files in .../include/message/
    File has 3 main parts
        -message structure
        -pack / unpack
        -encode
    """
    #load header structure and the messages in variables from xml file
    import xml.etree.ElementTree as ET
    tree = ET.parse('message_definition.xml')
    protocol = tree.findall('message')
    header = tree.find('header')
    tab = '   '
    for message in protocol:#for each message
        #declare message variables from xml
        name = message.get('name')        
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        filename = name.replace("_", "")
        #open file
        f = open(directory + "include/message/"+ filename + include_extension, 'w')
        # warning message
        f.write('/**@file This file was autogenerated. All changes will be undone. */\n\n')
        f.write('/** Message: '+ name +', ID: ' + message.get('id')+ '*/\n\n')
        # include guards
        f.write('#ifndef ' + '_' + name.upper()+'_H_\n')
        f.write('#define ' + '_' + name.upper()+'_H_\n\n')
        # protonet includes
        f.write('#include <protonet_marshal'+include_extension+'>\n')
        f.write('#include <protonet_message'+include_extension+'>\n\n')
        # message structure
        f.write('typedef struct {\n')
        for field in message:
            if(check_valid_type(field.get('type')) == 0):
                print 'error: field: '+ field.get('name') + ' in message: '+ name+ ' has invalid type.'
            f.write(tab + field.get('type') + ' ' + field.get('name') + ';\n')
            
            
        f.write('} '+type_t_name+';\n\n')
        # pack/unpack
        f.write('msg_offset pack_'+variable_name+'(\n')
        f.write(tab+type_t_name+'* ' +variable_name +',\n')
        f.write(tab+'msg_offset offset);\n\n')

        f.write('msg_offset unpack_'+variable_name+'(\n')
        f.write(tab+'msg_offset offset,\n')        
        f.write(tab+type_t_name+'* ' 'out_ptr);\n\n')
        
        # encode
        f.write('void encode_' + variable_name+'(\n')
        f.write(tab + 'uint8_t src_id,\n')
        f.write(tab + 'uint8_t dest_id,\n')
        f.write(tab + 'uint8_t msg_ttl,\n')
        f.write(tab + 'uint8_t seq_number,\n')
        f.write(tab + type_t_name+'* tx_msg,\n')
        f.write(tab + 'proto_msg_t* msg);\n\n')
        
        # include guard #endif
        f.write('#endif')
       
        f.close()
        
        print("Created message header: " + filename + include_extension)
Esempio n. 5
0
def generate_protocol_file_include(directory, include_extension,
                                   src_extension):
    """
    Function will create the protocol header file in .../include/
    File has 4 main parts
        -include all message header files
        -union of all messages
        -unpack function
        -proto_typster function
    """
    #load header structure and the messages in variables from xml file
    import xml.etree.ElementTree as ET
    tree = ET.parse('message_definition.xml')
    protocol = tree.findall('message')
    header = tree.find('header')
    tab = '   '
    #open file
    f = open(directory + "include/" + 'protonet_protocol' + include_extension,
             'w')
    # warning
    f.write(
        '/** @file This file was autogenerated. All changes will be undone. */\n\n'
    )
    # include guards
    f.write('#ifndef _PROTOCOL_H_\n')
    f.write('#define _PROTOCOL_H_\n\n')

    #include message header
    f.write('#include <protonet_message' + include_extension + '>\n')
    # include all messages header files
    for message in protocol:
        name = message.get('name')
        filename = name.replace("_", "")
        f.write('#include <message/' + filename + include_extension + '>\n')

    #create a union with all the message types as proto_msg_buf_t
    f.write(
        "\n/**Global typdef union with all message types declared as proto_msg_bug_t.\n"
    )
    f.write(
        "Used to easily transmit data as same variable. Could of used base class as message and created derived classes for polymorphism.\n"
    )
    f.write("Would have lost C ability if done so.*/\n")
    f.write('typedef union {\n')
    for message in protocol:
        name = message.get('name')
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        f.write(tab + type_t_name + ' ' + variable_name + ';\n')
    f.write('} proto_msg_buf_t;\n\n')

    #declare unpack function
    f.write(
        "/**Global function to unpack message with proto_msg and proto_msg_bug_t union.*/\n"
    )
    f.write('void unpack_proto_msg_t(\n')
    f.write(tab + 'proto_msg_t* msg,\n')
    f.write(tab + 'proto_msg_buf_t* buf);\n\n')

    #declare proto_typster function
    f.write(
        "/**Global function which returns the message string description*/\n")
    f.write('char* proto_typestr(proto_msg_type_t msg_type);\n\n')
    #end of guard
    f.write('#endif')

    print("Created: " + 'protonet_protocol' + include_extension)
Esempio n. 6
0
def generate_protonet_file_include(directory, include_extension, src_extension):
    """
    Function will create the protonet header file in .../include/
    File has 2 main parts
        -message callback prototypes
        -class node
            -public functions
            -public send_message
            -public register_on_message
            -private members / functions
            -callback data type functions on_message
    """
    #load header structure and the messages in variables from xml file
    import xml.etree.ElementTree as ET
    tree = ET.parse('message_definition.xml')
    protocol = tree.findall('message')
    header = tree.find('header')
    tab = '   '
    #open file
    f = open(directory + "include/" + 'protonet' + include_extension, 'w')
    # warning
    f.write('/**@file This file was autogenerated. All changes will be undone. */\n\n')
    # include guards
    f.write('#ifndef _PROTONET_H_\n')
    f.write('#define _PROTONET_H_\n\n')
    #include files
    f.write("/*Include files*/ \n")
    f.write('#include <datalink' +include_extension+'>\n')
    f.write('#include <protonet_protocol' +include_extension+'>\n')
    f.write('#include <queue' +include_extension+'>\n')
    f.write('#include <thread' +include_extension+'>\n\n')
    #declare name space
    f.write('namespace protonet\n')
    f.write('{\n')
    #extern/class of node
    f.write(tab + "/*Let compiler know class node exists some where else */ \n")
    f.write(tab + 'class node;\n\n')
    #for each message declare prototype of call back function
    for message in protocol:
        name = message.get('name')
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        f.write(tab + "/**Global function call back used for message " + name + " must be implemented on platform for use*/ \n")
        f.write(tab+'typedef void* (*'+ variable_name+'_callback)(int8_t, proto_header_t, '+type_t_name+', protonet::node* node_ptr);\n')
    
    #declare class node
    f.write(tab + "/** Class node represents each point of communication. The Node will be able to establish type of communication and send and receive messages. The callbacks must be implemented on the platform*/ \n")
    f.write('\n'+ tab+'class node\n')
    f.write(tab+'{\n')
    #public members
    f.write(tab+'public:\n')
    f.write(tab+tab+'node(uint8_t node_id);\n')
    f.write(tab+tab+'node(uint8_t node_id, int32_t mode);\n')
    f.write(tab+tab+'~node();\n')
    f.write(tab + tab + "/**Public method used to start node connection and messages*/ \n")
    f.write(tab+tab+'void start();\n\n')
    
    f.write(tab + tab + "/** Public method used to add serial communication*/ \n")
    f.write(tab+tab+'void add_serial(int8_t* link_id, uint32_t baud_rate, char device_path[50]);\n')
    f.write(tab + tab + "/** Public method used to add UDP communication*/ \n")
    f.write(tab+tab+'void add_udp(int8_t* link_id, uint16_t port);\n')
    f.write(tab + tab + "/** Public method used to add UDP communication*/ \n")
    f.write(tab+tab+'void add_udp(int8_t* link_id, uint16_t port, char addr[16]);\n\n')
    f.write(tab + tab + "/** Public method used to establish serial communication*/ \n")
    f.write(tab+tab+'void establish_serial(int8_t link_id, uint8_t node_id);\n')
    f.write(tab + tab + "/** Public method used to establish UDP communication*/ \n")
    f.write(tab+tab+'void establish_udp(int8_t link_id, uint8_t node_id, uint16_t port, char addr[16]);\n\n')
    
    f.write(tab+ tab + "/** method returns the number of datalink for this node*/ \n")
    f.write(tab+tab+'uint8_t get_num_datalinks();\n')
    f.write(tab+tab + "/**Public method used to find if datalink is connected*/ \n")
    f.write(tab+tab+'int32_t query_datalink_connected(int8_t link_id);\n')
    f.write(tab+tab + "/**Public method used to find what type of communication the datalink is*/ \n")
    f.write(tab+tab+'datalink_type_t query_datalink_type(int8_t link_id);\n\n')
    
    #declare each send_message
    for message in protocol:
        name = message.get('name')
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"        
        f.write(tab + tab + "/**Public definition of the send " + name + " message which will be put into the message queue.*/ \n")
        f.write(tab+tab+'void send_'+ variable_name+'(\n')
        f.write(tab+tab+tab+'uint8_t dest_id,')
        for field in message:
            f.write('\n'+tab+tab+tab+field.get('type')+' '+ field.get('name')+',')
        f.seek(-1, 1)
        f.write(');\n\n')
    #declare register_on_message
    for message in protocol:
        name = message.get('name')
        variable_name = lower_case_acronym(name)
        f.write(tab + tab + "/**Public definition of the register on " + name + " message which will use the message call back.*/ \n")
        f.write(tab+tab+'void register_on_'+ variable_name+'('+variable_name+'_callback callback){on_'+variable_name +' = callback;}\n')
    
    #private members
    f.write('\n'+tab+'private:\n')

    f.write(tab + tab + "/**Private data member hold the node id.*/ \n")
    f.write(tab+tab+'uint8_t node_id;\n\n')

    f.write(tab + tab + "/**Private data member used to keep track of the number of data links associated with this node*/ \n")
    f.write(tab+tab+'int8_t num_datalinks;\n')
    f.write(tab + tab + "/**Private array used to store all the datalink in this node*/ \n")
    f.write(tab+tab+'datalink* datalinks[255];\n')
    f.write(tab + tab + "/**Private data member to keep track of the threads associated with this node*/ \n")
    f.write(tab+tab+'thread_t datalink_threads[255];\n\n')
    
    f.write(tab + tab + "/**Private pointer to the message queue*/ \n")
    f.write(tab+tab+'proto_msg_queue queue;\n')    
    f.write(tab + tab + "/**Private method to handle the message to determine the type of message and its following actions  */ \n")
    f.write(tab+tab+'void handle_proto_msg_t(proto_msg_t* rx_msg, proto_msg_buf_t* rx_buf);\n\n')
    
    f.write(tab + tab + "/**Private data member to hold thread handler*/ \n")
    f.write(tab+tab+'thread_t handler_thread;\n')
    f.write(tab + tab + "/**Private method which is entry point for the event handler that performs callbacks based on incoming messages  */ \n")
    f.write(tab+tab+'void* protonet_handler();\n')
    f.write(tab + tab + "/**Private method Helper functions from C style from C++ entry point with class member linkage*/ \n")
    f.write(tab+tab+'static void* handler_helper(void* context);\n\n')
    
    f.write(tab + tab + "/**Private data member to keep track of upkeep thread data.*/ \n")
    f.write(tab+tab+'thread_t upkeep_thread;\n')
    f.write(tab + tab + "/**Private method for posix and windows compatible sleep method*/ \n")
    f.write(tab+tab+'void* upkeep_handler();\n')
    f.write(tab + tab + "/**Private method returns pointer to upkeep_handler*/ \n")
    f.write(tab+tab+'static void* upkeep_helper(void* context);\n\n')
    
    
    
    f.write(tab + tab + "/**Private methods sets all call backs to null */ \n")
    f.write(tab+tab+'void null_callback_storage();\n\n')

    #declare function as data type callback function name on_message
    for message in protocol:
        name = message.get('name')
        variable_name = lower_case_acronym(name)
        f.write(tab + tab + "/**Private data declares on " + name + " as call back data type used to hold call back*/ \n")
        f.write(tab+tab+variable_name+'_callback on_'+variable_name +';\n')    
    f.write(tab+'};\n')
    f.write('}\n')
    f.write('#endif')
   
    print("Created: " + 'protonet' + include_extension)
Esempio n. 7
0
def generate_proto_wrapper_src(directory, include_extension, src_extension):
    """
    Protowrapper is used to create a Managed C which calls c++ 
    Function will create the protowrapper source file in .../Protowrapper
    File has 3 main parts    
        -class node        
            -public send_message
            -public native functions
            -public register message and  private helper message methods        
            -callback data type functions on_message
    """
    #load header structure and the messages in variables from xml file
    import xml.etree.ElementTree as ET
    tree = ET.parse('message_definition.xml')
    protocol = tree.findall('message')
    header = tree.find('header')
    tab = '   '
    #open file
    f = open(directory + 'proto_wrapper' + src_extension, 'w')
    f.write(
        '/* This file was autogenerated. All changes will be undone. */\n\n')
    f.write('#include <proto_wrapper' + include_extension + '>\n')
    f.write('using namespace Protonet;\n\n')
    #constructor
    f.write('Node::Node(uint8_t node_id)\n{\n')
    f.write(tab + 'node = new protonet::node(node_id);\n')
    f.write('}\n\nNode::~Node()\n{\n')
    f.write(tab + 'delete(node);\n}\n\n')
    f.write('void Node::Start()\n{\n')
    f.write(tab + 'node->start();\n}\n\n')
    #send_message methods
    for message in protocol:
        name = message.get('name')
        cs_name = message.get('name').replace("_", "")
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        f.write('void Node::Send' + cs_name + '(\n')
        f.write(tab + 'uint8_t dest_id,')
        for field in message:
            f.write('\n' + tab + field.get('type') + ' ' + field.get('name') +
                    ',')
        f.seek(-1, 1)
        f.write(')\n{\n')
        f.write(tab + 'node->send_' + variable_name + '(\n')
        f.write(tab + 'dest_id,')
        for field in message:
            f.write('\n' + tab + field.get('name') + ',')
        f.seek(-1, 1)
        f.write(');\n}\n\n')
    #public native methods
    f.write(
        r'''void Node::AddUDPDatalink([System::Runtime::InteropServices::Out]int8_t% link_id,uint16_t port)
{
	int8_t link_data;
	node->add_udp(&link_data, port);
	link_id = link_data;
}
void Node::AddUDPDatalink([System::Runtime::InteropServices::Out]int8_t% link_id,uint16_t port, String^ addr)
{
	IntPtr addr_ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(addr);
	if(sizeof(addr_ptr)>16)
	{
		return;
	}
	int8_t link_data;
	node->add_udp(&link_data, port, static_cast<char*>(addr_ptr.ToPointer()));
	link_id = link_data;
}

void Node::EstablishUDPEndpoint(int8_t link_id, uint8_t node_id, uint16_t port, String^ addr)
{
	IntPtr addr_ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(addr);
	if(sizeof(addr_ptr)>16)
	{
		return;
	}
	node->establish_udp(link_id, node_id, port, static_cast<char*>(addr_ptr.ToPointer()));
}

void Node::AddSerialDatalink([System::Runtime::InteropServices::Out]int8_t% link_id, uint32_t baud_rate, String^ device_path)
{
	IntPtr device_path_ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(device_path);
	if(sizeof(device_path_ptr)>16)
	{
		return;
	}
	int8_t link_data;
	node->add_serial(&link_data, baud_rate, static_cast<char*>(device_path_ptr.ToPointer()));
	link_id = link_data;
}

void Node::EstablishSerialEndpoint(int8_t link_id, uint8_t node_id)
{
	node->establish_serial(link_id,node_id);
}''' + '\n\n')
    #public register messages and helper message methods
    for message in protocol:
        name = message.get('name')
        cs_name = message.get('name').replace("_", "")
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        f.write('void* Node::' + cs_name +
                'Helper(int8_t link_id, proto_header_t header, ' +
                type_t_name + ' ' + variable_name +
                ', protonet::node* ptr)\n{\n')
        f.write(tab + 'Header^ managed_header = gcnew Header(header);\n')
        f.write(tab + cs_name + '^ managed_' + variable_name + ' = gcnew ' +
                cs_name + '(' + variable_name + ');\n')
        f.write(tab + 'On' + cs_name +
                'Delegate(link_id, managed_header, managed_' + variable_name +
                ', this);\n')
        f.write(tab + 'return 0;\n}\n\n')
        f.write('void Node::Register' + cs_name + 'Event(' + cs_name +
                'Delegate^ ' + cs_name + 'Event)\n{\n')
        f.write(tab + 'On' + cs_name + 'Delegate = ' + cs_name + 'Event;\n')
        f.write(tab + 'On' + cs_name + 'Callback = gcnew ' + cs_name +
                'Callback(this, &Node::' + cs_name + 'Helper);\n')
        f.write(tab + 'On' + cs_name +
                'Ptr = Marshal::GetFunctionPointerForDelegate(On' + cs_name +
                'Callback);\n')
        f.write(tab + 'node->register_on_' + variable_name +
                '(static_cast<protonet::' + variable_name + '_callback>(On' +
                cs_name + 'Ptr.ToPointer()));\n')
        f.write('}\n\n')

    print("Created: " + 'proto_wrapper' + src_extension)
Esempio n. 8
0
def generate_message_sources(directory, include_extension, src_extension):
    """
    Function will create all message source files in .../src/message/
    File has 3 main parts
        -pack
        -unpack
        -encode
    """
    #load header structure and the messages in variables from xml file
    import xml.etree.ElementTree as ET
    tree = ET.parse('message_definition.xml')
    protocol = tree.findall('message')
    header = tree.find('header')
    tab = '   '
    for message in protocol:
        #declare message variables from xml
        name = message.get('name')
        variable_name = lower_case_acronym(name)
        type_t_name = variable_name + "_t"
        filename = name.replace("_", "")
        #open file
        f = open(directory + "src/message/" + filename + src_extension, 'w')
        # warning message
        f.write(
            '/* This file was autogenerated. All changes will be undone. */\n\n'
        )
        f.write('/* Message: ' + name + ', ID: ' + message.get('id') +
                '*/\n\n')
        # includes
        f.write('#include <protonet_marshal' + include_extension + '>\n')
        f.write('#include <protonet_message' + include_extension + '>\n')
        f.write('#include <message/' + filename + include_extension + '>\n\n')

        # pack
        f.write('msg_offset pack_' + variable_name + '(\n')
        f.write(tab + type_t_name + '* ' + variable_name + ',\n')
        f.write(tab + 'msg_offset offset)\n')
        f.write('{\n')

        for field in message:
            if (check_valid_type(field.get('type')) == 0):
                print 'error: field: ' + field.get(
                    'name') + ' in message: ' + name + ' has invalid type.'
            f.write(tab + 'offset = pack_' + field.get('type') + '(' +
                    variable_name + '->' + field.get('name') + ',offset);\n')
        f.write(tab + 'return offset;\n')
        f.write('}\n\n')

        #unpack
        f.write('msg_offset unpack_' + variable_name + '(\n')
        f.write(tab + 'msg_offset offset,\n')
        f.write(tab + type_t_name + '* ' 'out_ptr)\n')
        f.write('{\n')
        message_length = 0
        for field in message:
            if (check_valid_type(field.get('type')) == 0):
                print 'error: field: ' + field.get(
                    'name') + ' in message: ' + name + ' has invalid type.'
            field_type_string = field.get('type')
            s = ''.join(x for x in field_type_string if x.isdigit())
            message_length = message_length + int(s)
            f.write(tab + 'offset = unpack_' + field.get('type') +
                    '(offset, &out_ptr->' + field.get('name') + ');\n')
        message_length = message_length / 8

        f.write(tab + 'return offset;\n')
        f.write('}\n\n')

        # encode
        f.write('void encode_' + variable_name + '(\n')
        f.write(tab + 'uint8_t src_id,\n')
        f.write(tab + 'uint8_t dest_id,\n')
        f.write(tab + 'uint8_t msg_ttl,\n')
        f.write(tab + 'uint8_t seq_number,\n')
        f.write(tab + type_t_name + '* tx_msg,\n')
        f.write(tab + 'proto_msg_t* msg)\n')
        f.write('{\n')
        f.write(tab + 'msg_offset start_offset, offset;\n')
        f.write(tab + 'msg->direction = Proto_Out;\n')
        f.write(tab + 'start_offset = msg->data;\n')
        f.write(tab + 'offset = msg->data;\n')
        f.write(tab + 'msg->header.node_src_id = src_id;\n')
        f.write(tab + 'msg->header.node_dest_id = dest_id;\n')
        f.write(tab + 'msg->header.message_ttl = msg_ttl;\n')
        f.write(tab + 'msg->header.sequence_number = seq_number;\n')
        f.write(tab + 'msg->header.message_length = ' + str(message_length) +
                ';\n')
        f.write(tab + 'msg->header.message_type = Proto_' + name + ';\n')
        f.write(tab + 'offset = pack_sync(offset);\n')
        f.write(tab + 'offset = pack_header(&msg->header, offset);\n')
        f.write(tab + 'offset = pack_' + variable_name + '(tx_msg, offset);\n')
        f.write(tab + 'offset = pack_checksum(start_offset, offset);\n')
        f.write(tab + 'msg->tx_len = offset-start_offset;\n')
        f.write('}')
        f.close()
        #print what file was created
        print("Created message source: " + filename + src_extension)