| 779 | } |
| 780 | |
| 781 | EipStatus SendConnectedData(CipConnectionObject *connection_object) { |
| 782 | |
| 783 | /* TODO think of adding an own send buffer to each connection object in order to preset up the whole message on connection opening and just change the variable data items e.g., sequence number */ |
| 784 | |
| 785 | CipCommonPacketFormatData *common_packet_format_data = |
| 786 | &g_common_packet_format_data_item; |
| 787 | /* TODO think on adding a CPF data item to the S_CIP_ConnectionObject in order to remove the code here or even better allocate memory in the connection object for storing the message to send and just change the application data*/ |
| 788 | |
| 789 | connection_object->eip_level_sequence_count_producing++; |
| 790 | |
| 791 | /* assembleCPFData */ |
| 792 | common_packet_format_data->item_count = 2; |
| 793 | if ( kConnectionObjectTransportClassTriggerTransportClass0 != |
| 794 | ConnectionObjectGetTransportClassTriggerTransportClass(connection_object) ) |
| 795 | { /* use Sequenced Address Items if not Connection Class 0 */ |
| 796 | common_packet_format_data->address_item.type_id = |
| 797 | kCipItemIdSequencedAddressItem; |
| 798 | common_packet_format_data->address_item.length = 8; |
| 799 | common_packet_format_data->address_item.data.sequence_number = |
| 800 | connection_object->eip_level_sequence_count_producing; |
| 801 | } else { |
| 802 | common_packet_format_data->address_item.type_id = |
| 803 | kCipItemIdConnectionAddress; |
| 804 | common_packet_format_data->address_item.length = 4; |
| 805 | |
| 806 | } |
| 807 | common_packet_format_data->address_item.data.connection_identifier = |
| 808 | connection_object->cip_produced_connection_id; |
| 809 | |
| 810 | common_packet_format_data->data_item.type_id = kCipItemIdConnectedDataItem; |
| 811 | |
| 812 | CipByteArray *producing_instance_attributes = |
| 813 | (CipByteArray *) connection_object->producing_instance->attributes->data; |
| 814 | common_packet_format_data->data_item.length = 0; |
| 815 | |
| 816 | /* notify the application that data will be sent immediately after the call */ |
| 817 | if ( BeforeAssemblyDataSend(connection_object->producing_instance) ) { |
| 818 | /* the data has changed increase sequence counter */ |
| 819 | connection_object->sequence_count_producing++; |
| 820 | } |
| 821 | |
| 822 | /* set AddressInfo Items to invalid Type */ |
| 823 | common_packet_format_data->address_info_item[0].type_id = 0; |
| 824 | common_packet_format_data->address_info_item[1].type_id = 0; |
| 825 | |
| 826 | ENIPMessage outgoing_message = {0}; |
| 827 | InitializeENIPMessage(&outgoing_message); |
| 828 | EipUint16 reply_length = AssembleIOMessage(common_packet_format_data, |
| 829 | &outgoing_message); |
| 830 | |
| 831 | |
| 832 | outgoing_message.current_message_position -= 2; |
| 833 | common_packet_format_data->data_item.length = producing_instance_attributes |
| 834 | ->length; |
| 835 | #ifdef OPENER_PRODUCED_DATA_HAS_RUN_IDLE_HEADER |
| 836 | common_packet_format_data->data_item.length += 4; |
| 837 | #endif /* OPENER_PRODUCED_DATA_HAS_RUN_IDLE_HEADER */ |
| 838 |
nothing calls this directly
no test coverage detected