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)
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)
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)
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)
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)
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)
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)
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)