int wp_decode_apdu( uint8_t * apdu, unsigned apdu_len, uint8_t * invoke_id, BACNET_WRITE_PROPERTY_DATA * wpdata) { int len = 0; unsigned offset = 0; if (!apdu) return -1; /* optional checking - most likely was already done prior to this call */ if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST) return -1; /* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */ *invoke_id = apdu[2]; /* invoke id - filled in by net layer */ if (apdu[3] != SERVICE_CONFIRMED_WRITE_PROPERTY) return -1; offset = 4; if (apdu_len > offset) { len = wp_decode_service_request(&apdu[offset], apdu_len - offset, wpdata); } return len; }
/** Handler for a WriteProperty Service request. * @ingroup DSWP * This handler will be invoked by apdu_handler() if it has been enabled * by a call to apdu_set_confirmed_handler(). * This handler builds a response packet, which is * - an Abort if * - the message is segmented * - if decoding fails * - an ACK if Device_Write_Property() succeeds * - an Error if Device_Write_Property() fails * or there isn't enough room in the APDU to fit the data. * * @param service_request [in] The contents of the service request. * @param service_len [in] The length of the service_request. * @param src [in] BACNET_ADDRESS of the source of the message * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information * decoded from the APDU header of this message. */ void handler_write_property( uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data) { BACNET_WRITE_PROPERTY_DATA wp_data; int len = 0; int pdu_len = 0; BACNET_NPDU_DATA npdu_data; int bytes_sent = 0; BACNET_ADDRESS my_address; /* encode the NPDU portion of the packet */ datalink_get_my_address(&my_address); npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address, &npdu_data); #if PRINT_ENABLED fprintf(stderr, "WP: Received Request!\n"); #endif if (service_data->segmented_message) { len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); #if PRINT_ENABLED fprintf(stderr, "WP: Segmented message. Sending Abort!\n"); #endif goto WP_ABORT; } /* decode the service request only */ len = wp_decode_service_request(service_request, service_len, &wp_data); #if PRINT_ENABLED if (len > 0) fprintf(stderr, "WP: type=%lu instance=%lu property=%lu priority=%lu index=%ld\n", (unsigned long) wp_data.object_type, (unsigned long) wp_data.object_instance, (unsigned long) wp_data.object_property, (unsigned long) wp_data.priority, (long) wp_data.array_index); else fprintf(stderr, "WP: Unable to decode Request!\n"); #endif /* bad decoding or something we didn't understand - send an abort */ if (len <= 0) { len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_OTHER, true); #if PRINT_ENABLED fprintf(stderr, "WP: Bad Encoding. Sending Abort!\n"); #endif goto WP_ABORT; } if (Device_Write_Property(&wp_data)) { len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); #if PRINT_ENABLED fprintf(stderr, "WP: Sending Simple Ack!\n"); #endif } else { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, wp_data.error_class, wp_data.error_code); #if PRINT_ENABLED fprintf(stderr, "WP: Sending Error!\n"); #endif } WP_ABORT: pdu_len += len; bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); #if PRINT_ENABLED if (bytes_sent <= 0) { fprintf(stderr, "WP: Failed to send PDU (%s)!\n", strerror(errno)); } #else bytes_sent = bytes_sent; #endif return; }
void handler_write_property( uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data) { int len = 0; int pdu_len = 0; BACNET_NPDU_DATA npdu_data; BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT; BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT; int bytes_sent = 0; BACNET_ADDRESS my_address; /* decode the service request only */ len = wp_decode_service_request(service_request, service_len, &wp_data); /* encode the NPDU portion of the packet */ datalink_get_my_address(&my_address); npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address, &npdu_data); /* bad decoding or something we didn't understand - send an abort */ if (len <= 0) { len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_OTHER, true); } else if (service_data->segmented_message) { len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); } else { switch (wp_data.object_type) { case OBJECT_DEVICE: if (Device_Write_Property(&wp_data, &error_class, &error_code)) { len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); } else { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); } break; case OBJECT_ANALOG_VALUE: if (Analog_Value_Write_Property(&wp_data, &error_class, &error_code)) { len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); } else { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); } break; case OBJECT_BINARY_VALUE: if (Binary_Value_Write_Property(&wp_data, &error_class, &error_code)) { len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); } else { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); } break; default: len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); break; } } pdu_len += len; bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); return; }
void handler_write_property( uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data) { int len = 0; int pdu_len = 0; BACNET_NPDU_DATA npdu_data; BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT; BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT; int bytes_sent = 0; BACNET_ADDRESS my_address; /* encode the NPDU portion of the packet */ datalink_get_my_address(&my_address); npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address, &npdu_data); if (service_data->segmented_message) { len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); goto WP_ABORT; } /* decode the service request only */ len = wp_decode_service_request(service_request, service_len, &wp_data); /* bad decoding or something we didn't understand - send an abort */ if (len <= 0) { len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_OTHER, true); goto WP_ABORT; } switch (wp_data.object_type) { case OBJECT_DEVICE: if (Device_Write_Property(&wp_data, &error_class, &error_code)) { len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); #if PRINT_ENABLED fprintf(stderr, "Sending Write Property Simple Ack for Device!\n"); #endif } else { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); #if PRINT_ENABLED fprintf(stderr, "Sending Write Property Error for Device!\n"); #endif } break; case OBJECT_ANALOG_INPUT: case OBJECT_BINARY_INPUT: error_class = ERROR_CLASS_PROPERTY; error_code = ERROR_CODE_WRITE_ACCESS_DENIED; len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); #if PRINT_ENABLED fprintf(stderr, "Sending Write Access Error!\n"); #endif break; case OBJECT_BINARY_VALUE: if (Binary_Value_Write_Property(&wp_data, &error_class, &error_code)) { len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); #if PRINT_ENABLED fprintf(stderr, "Sending Write Property Simple Ack for BV!\n"); #endif } else { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); #if PRINT_ENABLED fprintf(stderr, "Sending Write Access Error for BV!\n"); #endif } break; case OBJECT_ANALOG_VALUE: if (Analog_Value_Write_Property(&wp_data, &error_class, &error_code)) { len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY); #if PRINT_ENABLED fprintf(stderr, "Sending Write Property Simple Ack for AV!\n"); #endif } else { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); #if PRINT_ENABLED fprintf(stderr, "Sending Write Access Error for AV!\n"); #endif } break; default: len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code); #if PRINT_ENABLED fprintf(stderr, "Sending Unknown Object Error!\n"); #endif break; } WP_ABORT: pdu_len += len; bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); #if PRINT_ENABLED if (bytes_sent <= 0) fprintf(stderr, "Failed to send PDU (%s)!\n", strerror(errno)); #endif return; }