/** 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; }
/** Handler for a Device Communication Control (DCC) request. * @ingroup DMDCC * 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 * - if not a known DCC state * - an Error if the DCC password is incorrect * - else tries to send a simple ACK for the DCC on success, * and sets the DCC state requested. * * @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_device_communication_control( uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data) { uint16_t timeDuration = 0; BACNET_COMMUNICATION_ENABLE_DISABLE state = COMMUNICATION_ENABLE; BACNET_CHARACTER_STRING password; int len = 0; int pdu_len = 0; BACNET_NPDU_DATA npdu_data; BACNET_ADDRESS my_address; /* encode the NPDU portion of the reply 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, "DeviceCommunicationControl!\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, "DeviceCommunicationControl: " "Sending Abort - segmented message.\n"); #endif goto DCC_ABORT; } /* decode the service request only */ len = dcc_decode_service_request(service_request, service_len, &timeDuration, &state, &password); #if PRINT_ENABLED if (len > 0) fprintf(stderr, "DeviceCommunicationControl: " "timeout=%u state=%u password=%s\n", (unsigned) timeDuration, (unsigned) state, characterstring_value(&password)); #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, "DeviceCommunicationControl: " "Sending Abort - could not decode.\n"); #endif goto DCC_ABORT; } if (state >= MAX_BACNET_COMMUNICATION_ENABLE_DISABLE) { len = reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION); #if PRINT_ENABLED fprintf(stderr, "DeviceCommunicationControl: " "Sending Reject - undefined enumeration\n"); #endif } else { #if BAC_ROUTING /* Check to see if the current Device supports this service. */ len = Routed_Device_Service_Approval (SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL, (int) state, &Handler_Transmit_Buffer[pdu_len], service_data->invoke_id); if (len > 0) goto DCC_ABORT; #endif if (characterstring_ansi_same(&password, My_Password)) { len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL); #if PRINT_ENABLED fprintf(stderr, "DeviceCommunicationControl: " "Sending Simple Ack!\n"); #endif dcc_set_status_duration(state, timeDuration); } else { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL, ERROR_CLASS_SECURITY, ERROR_CODE_PASSWORD_FAILURE); #if PRINT_ENABLED fprintf(stderr, "DeviceCommunicationControl: " "Sending Error - password failure.\n"); #endif } } DCC_ABORT: pdu_len += len; len = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); if (len <= 0) { #if PRINT_ENABLED fprintf(stderr, "DeviceCommunicationControl: " "Failed to send PDU (%s)!\n", strerror(errno)); #endif } return; }
/** Handler for a Reinitialize Device (RD) request. * @ingroup DMRD * 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 Error if * - the RD password is incorrect * - the Reinitialize Device operation fails * - a Reject if the request state is invalid * - else tries to send a simple ACK for the RD on success. * * @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_reinitialize_device( uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data) { BACNET_REINITIALIZE_DEVICE_DATA rd_data; int len = 0; int pdu_len = 0; BACNET_NPDU_DATA npdu_data; 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, "ReinitializeDevice!\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, "ReinitializeDevice: Sending Abort - segmented message.\n"); #endif goto RD_ABORT; } /* decode the service request only */ len = rd_decode_service_request(service_request, service_len, &rd_data.state, &rd_data.password); #if PRINT_ENABLED if (len > 0) { fprintf(stderr, "ReinitializeDevice: state=%u password=%s\n", (unsigned) rd_data.state, characterstring_value(&rd_data.password)); } else { fprintf(stderr, "ReinitializeDevice: 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, "ReinitializeDevice: Sending Abort - could not decode.\n"); #endif goto RD_ABORT; } /* check the data from the request */ if (rd_data.state >= MAX_BACNET_REINITIALIZED_STATE) { len = reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION); #if PRINT_ENABLED fprintf(stderr, "ReinitializeDevice: Sending Reject - undefined enumeration\n"); #endif } else { #if BAC_ROUTING /* Check to see if the current Device supports this service. */ len = Routed_Device_Service_Approval (SERVICE_CONFIRMED_REINITIALIZE_DEVICE, (int) rd_data.state, &Handler_Transmit_Buffer[pdu_len], service_data->invoke_id); if (len > 0) goto RD_ABORT; #endif if (Device_Reinitialize(&rd_data)) { len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE); #if PRINT_ENABLED fprintf(stderr, "ReinitializeDevice: Sending Simple Ack!\n"); #endif } else { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE, rd_data.error_class, rd_data.error_code); #if PRINT_ENABLED fprintf(stderr, "ReinitializeDevice: Sending Error.\n"); #endif } } RD_ABORT: pdu_len += len; len = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); if (len <= 0) { #if PRINT_ENABLED fprintf(stderr, "ReinitializeDevice: Failed to send PDU (%s)!\n", strerror(errno)); #endif } return; }
/** Handler for a COV Subscribe Service request. * @ingroup DSCOV * 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 cov_subscribe() succeeds * - an Error if cov_subscribe() fails * * @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_cov_subscribe( uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data) { BACNET_SUBSCRIBE_COV_DATA cov_data; int len = 0; int pdu_len = 0; int npdu_len = 0; int apdu_len = 0; BACNET_NPDU_DATA npdu_data; bool success = false; int bytes_sent = 0; BACNET_ADDRESS my_address; bool error = false; /* initialize a common abort code */ cov_data.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; /* encode the NPDU portion of the packet */ datalink_get_my_address(&my_address); npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); npdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address, &npdu_data); if (service_data->segmented_message) { /* we don't support segmentation - send an abort */ len = BACNET_STATUS_ABORT; #if PRINT_ENABLED fprintf(stderr, "SubscribeCOV: Segmented message. Sending Abort!\n"); #endif error = true; goto COV_ABORT; } len = cov_subscribe_decode_service_request(service_request, service_len, &cov_data); #if PRINT_ENABLED if (len <= 0) fprintf(stderr, "SubscribeCOV: Unable to decode Request!\n"); #endif if (len < 0) { error = true; goto COV_ABORT; } cov_data.error_class = ERROR_CLASS_OBJECT; cov_data.error_code = ERROR_CODE_UNKNOWN_OBJECT; success = cov_subscribe(src, &cov_data, &cov_data.error_class, &cov_data.error_code); if (success) { apdu_len = encode_simple_ack(&Handler_Transmit_Buffer[npdu_len], service_data->invoke_id, SERVICE_CONFIRMED_SUBSCRIBE_COV); #if PRINT_ENABLED fprintf(stderr, "SubscribeCOV: Sending Simple Ack!\n"); #endif } else { len = BACNET_STATUS_ERROR; error = true; #if PRINT_ENABLED fprintf(stderr, "SubscribeCOV: Sending Error!\n"); #endif } COV_ABORT: if (error) { if (len == BACNET_STATUS_ABORT) { apdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len], service_data->invoke_id, abort_convert_error_code(cov_data.error_code), true); #if PRINT_ENABLED fprintf(stderr, "SubscribeCOV: Sending Abort!\n"); #endif } else if (len == BACNET_STATUS_ERROR) { apdu_len = bacerror_encode_apdu(&Handler_Transmit_Buffer[npdu_len], service_data->invoke_id, SERVICE_CONFIRMED_SUBSCRIBE_COV, cov_data.error_class, cov_data.error_code); #if PRINT_ENABLED fprintf(stderr, "SubscribeCOV: Sending Error!\n"); #endif } else if (len == BACNET_STATUS_REJECT) { apdu_len = reject_encode_apdu(&Handler_Transmit_Buffer[npdu_len], service_data->invoke_id, reject_convert_error_code(cov_data.error_code)); #if PRINT_ENABLED fprintf(stderr, "SubscribeCOV: Sending Reject!\n"); #endif } } pdu_len = npdu_len + apdu_len; bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); #if PRINT_ENABLED if (bytes_sent <= 0) fprintf(stderr, "SubscribeCOV: Failed to send PDU (%s)!\n", strerror(errno)); #else bytes_sent = bytes_sent; #endif return; }
void handler_lso( uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data) { BACNET_LSO_DATA 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 (service_data->segmented_message) { /* we don't support segmentation - send an abort */ len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); #if PRINT_ENABLED fprintf(stderr, "LSO: Segmented message. Sending Abort!\n"); #endif goto LSO_ABORT; } len = lso_decode_service_request(service_request, service_len, &data); #if PRINT_ENABLED if (len <= 0) fprintf(stderr, "LSO: Unable to decode Request!\n"); #endif if (len < 0) { /* bad decoding - send an abort */ len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_OTHER, true); #if PRINT_ENABLED fprintf(stderr, "LSO: Bad Encoding. Sending Abort!\n"); #endif goto LSO_ABORT; } /* ** Process Life Safety Operation Here */ #if PRINT_ENABLED fprintf(stderr, "Life Safety Operation: Received operation %d from process id %d for object %id\n", data.operation, data.processId, data.targetObject.instance); #endif len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_LIFE_SAFETY_OPERATION); #if PRINT_ENABLED fprintf(stderr, "Life Safety Operation: " "Sending Simple Ack!\n"); #endif LSO_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, "Life Safety Operation: " "Failed to send PDU (%s)!\n", strerror(errno)); #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_reinitialize_device( uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data) { BACNET_REINITIALIZED_STATE state; BACNET_CHARACTER_STRING their_password; 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 (service_data->segmented_message) { len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); goto RD_ABORT; } /* decode the service request only */ len = rd_decode_service_request(service_request, service_len, &state, &their_password); /* 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 RD_ABORT; } /* check the data from the request */ if (state >= MAX_BACNET_REINITIALIZED_STATE) { len = reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION); } else { characterstring_init_ansi(&My_Password, Password); if (characterstring_same(&their_password, &My_Password)) { len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE); /* FIXME: now you can reboot, restart, quit, or something clever */ /* Note: you can use a mix of state and password to do specific stuff */ /* Note: if you don't do something clever like actually restart, you probably should clear any DCC status and timeouts */ /* Note: you probably need to send the reply BEFORE restarting */ } else { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE, ERROR_CLASS_SERVICES, ERROR_CODE_PASSWORD_FAILURE); } } RD_ABORT: pdu_len += len; bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); return; }
/** Handler for an Confirmed COV Notification. * @ingroup DSCOV * Decodes the received list of Properties to update, * and print them out with the subscription information. * @note Nothing is specified in BACnet about what to do with the * information received from Confirmed COV Notifications. * * @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_ccov_notification( uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data) { BACNET_NPDU_DATA npdu_data; BACNET_COV_DATA cov_data; BACNET_PROPERTY_VALUE property_value[MAX_COV_PROPERTIES]; BACNET_PROPERTY_VALUE *pProperty_value = NULL; unsigned index = 0; int len = 0; int pdu_len = 0; int bytes_sent = 0; BACNET_ADDRESS my_address; /* create linked list to store data if more than one property value is expected */ pProperty_value = &property_value[0]; while (pProperty_value) { index++; if (index < MAX_COV_PROPERTIES) { pProperty_value->next = &property_value[index]; } else { pProperty_value->next = NULL; } pProperty_value = pProperty_value->next; } cov_data.listOfValues = &property_value[0]; /* 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, "CCOV: Received Notification!\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, "CCOV: Segmented message. Sending Abort!\n"); #endif goto CCOV_ABORT; } /* decode the service request only */ len = cov_notify_decode_service_request(service_request, service_len, &cov_data); #if PRINT_ENABLED if (len > 0) { fprintf(stderr, "CCOV: PID=%u ", cov_data.subscriberProcessIdentifier); fprintf(stderr, "instance=%u ", cov_data.initiatingDeviceIdentifier); fprintf(stderr, "%s %u ", bactext_object_type_name(cov_data.monitoredObjectIdentifier.type), cov_data.monitoredObjectIdentifier.instance); fprintf(stderr, "time remaining=%u seconds ", cov_data.timeRemaining); fprintf(stderr, "\n"); pProperty_value = &property_value[0]; while (pProperty_value) { fprintf(stderr, "CCOV: "); if (pProperty_value->propertyIdentifier < 512) { fprintf(stderr, "%s ", bactext_property_name (pProperty_value->propertyIdentifier)); } else { fprintf(stderr, "proprietary %u ", pProperty_value->propertyIdentifier); } if (pProperty_value->propertyArrayIndex != BACNET_ARRAY_ALL) { fprintf(stderr, "%u ", pProperty_value->propertyArrayIndex); } fprintf(stderr, "\n"); pProperty_value = pProperty_value->next; } } #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, "CCOV: Bad Encoding. Sending Abort!\n"); #endif goto CCOV_ABORT; } else { len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_COV_NOTIFICATION); #if PRINT_ENABLED fprintf(stderr, "CCOV: Sending Simple Ack!\n"); #endif } CCOV_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, "CCOV: 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; /* 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; }
void handler_alarm_ack( uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data) { BACNET_ALARM_ACK_DATA 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 (service_data->segmented_message) { /* we don't support segmentation - send an abort */ len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); #if PRINT_ENABLED fprintf(stderr, "Alarm Ack: Segmented message. Sending Abort!\n"); #endif goto AA_ABORT; } len = alarm_ack_decode_service_request(service_request, service_len, &data); #if PRINT_ENABLED if (len <= 0) fprintf(stderr, "Alarm Ack: Unable to decode Request!\n"); #endif if (len < 0) { /* bad decoding - send an abort */ len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_OTHER, true); #if PRINT_ENABLED fprintf(stderr, "Alarm Ack: Bad Encoding. Sending Abort!\n"); #endif goto AA_ABORT; } /* ** Process Life Safety Operation Here */ #if PRINT_ENABLED fprintf(stderr, "Alarm Ack Operation: Received acknowledge for object id %d from %s for process id %d for object %id\n", data.eventObjectIdentifier.instance, data.ackSource.value, data.ackProcessIdentifier, data.eventObjectIdentifier.instance); #endif len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM); #if PRINT_ENABLED fprintf(stderr, "Alarm Acknowledge: " "Sending Simple Ack!\n"); #endif AA_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, "Alarm Acknowledge: " "Failed to send PDU (%s)!\n", strerror(errno)); #endif return; }