RP and RPM Network Port indefinite object instance (#146)

* RP and RPM Network Port indefinite object instance

Added ReadProperty and ReadPropertyMultiple handling for
Network Port object indefinite object instance 4194303.

* Add network port object to some examples

* Fix stm32f10x build

* Fix Endian order of network port IP UDP port

* Add network port object to BDK Makefile

* Add network port object header to BDK device.c

* fix BDK and AT91SAM7S port builds

Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
Steve Karg
2021-01-07 10:21:11 -06:00
committed by GitHub
parent 63e4fa1f4b
commit 7cb63dcf06
31 changed files with 3205 additions and 136 deletions
+1
View File
@@ -61,6 +61,7 @@ DEMOSRC = ai.c \
bi.c \
bv.c \
device.c \
netport.c \
$(BACNET_BASIC)/tsm/tsm.c \
$(BACNET_BASIC)/sys/ringbuf.c \
$(BACNET_BASIC)/npdu/h_npdu.c \
+3
View File
@@ -1108,6 +1108,9 @@
<file>
<name>$PROJ_DIR$\device.c</name>
</file>
<file>
<name>$PROJ_DIR$\netport.c</name>
</file>
<file>
<name>$PROJ_DIR$\dlmstp.c</name>
</file>
+19 -9
View File
@@ -39,6 +39,9 @@
#include "bacnet/basic/services.h"
#include "bacnet/proplist.h"
/* objects */
#if (BACNET_PROTOCOL_REVISION >= 17)
#include "bacnet/basic/object/netport.h"
#endif
#include "bacnet/basic/object/device.h"
#include "bacnet/basic/object/ai.h"
#include "bacnet/basic/object/av.h"
@@ -64,11 +67,12 @@ static struct my_object_functions {
read_property_function Object_Read_Property;
write_property_function Object_Write_Property;
rpm_property_lists_function Object_RPM_List;
} Object_Table[] = { { OBJECT_DEVICE, NULL, /* don't init - recursive! */
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists },
} Object_Table[] = {
{ OBJECT_DEVICE, NULL, /* don't init - recursive! */
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists },
{ OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
Analog_Input_Object_Name, Analog_Input_Read_Property, NULL,
@@ -85,6 +89,12 @@ static struct my_object_functions {
Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance,
Binary_Value_Object_Name, Binary_Value_Read_Property,
Binary_Value_Write_Property, Binary_Value_Property_Lists },
#if (BACNET_PROTOCOL_REVISION >= 17)
{ OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
Network_Port_Object_Name, Network_Port_Read_Property,
Network_Port_Write_Property, Network_Port_Property_Lists },
#endif
{ MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL } };
/* note: you really only need to define variables for
@@ -769,7 +779,7 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
break;
case 9600:
apdu_len =
encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
encode_application_unsigned(&apdu[0], rs485_baud_rate());
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
@@ -896,9 +906,9 @@ bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data)
case 9600:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 115200) {
RS485_Set_Baud_Rate(value.type.Unsigned_Int);
status = true;
} else {
status = rs485_baud_rate_set(value.type.Unsigned_Int);
}
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
+10
View File
@@ -1396,3 +1396,13 @@ void dlmstp_get_broadcast_address(BACNET_ADDRESS *dest)
return;
}
uint8_t dlmstp_max_info_frames_limit(void)
{
return MSTP_PDU_PACKET_COUNT;
}
uint8_t dlmstp_max_master_limit(void)
{
return 127;
}
+20
View File
@@ -21,12 +21,32 @@
/* Include the board file description */
#include "board.h"
#if defined(__ICCARM__)
//------------------------------------------------------------------------------
// Internal functions
//------------------------------------------------------------------------------
static void AT91F_Spurious_handler( void )
{
while (1);
}
static void AT91F_Default_FIQ_handler( void )
{
while (1);
}
static void AT91F_Default_IRQ_handler( void )
{
while (1);
}
#else
/* The following functions must be write in ARM mode this function called
* directly */
/* by exception vector */
extern void AT91F_Spurious_handler(void);
extern void AT91F_Default_IRQ_handler(void);
extern void AT91F_Default_FIQ_handler(void);
#endif
/**----------------------------------------------------------------------------
*/
+3
View File
@@ -23,6 +23,8 @@
#include "at91sam7s256.h"
#include "isr.h"
#if defined(__GNUC__)
/* GCC */
#define IRQ_MASK 0x00000080
#define FIQ_MASK 0x00000040
#define INT_MASK (IRQ_MASK | FIQ_MASK)
@@ -91,3 +93,4 @@ unsigned enableFIQ(void)
__set_cpsr(_cpsr & ~FIQ_MASK);
return _cpsr;
}
#endif
+2
View File
@@ -32,6 +32,8 @@
#include <intrinsics.h>
#define isr_enable() __enable_interrupt()
#define isr_disable() __disable_interrupt()
#define __get_cpsr __get_CPSR
#define __set_cpsr __set_CPSR
#endif
#if defined(__GNUC__)
#define isr_enable() enableIRQ();enableFIQ();
+1 -1
View File
@@ -133,7 +133,7 @@ static inline void bacnet_init(void)
#if defined(BACDL_MSTP)
uint8_t MAC_Address = 0x55;
RS485_Set_Baud_Rate(38400);
rs485_baud_rate_set(38400);
dlmstp_set_mac_address(MAC_Address);
dlmstp_set_max_master(127);
dlmstp_set_max_info_frames(1);
+748
View File
@@ -0,0 +1,748 @@
/**
* @file
* @author Steve Karg
* @date 2016
* @brief Network port objects, customize for your use
*
* @section DESCRIPTION
*
* The Network Port object provides access to the configuration
* and properties of network ports of a device.
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "bacnet/config.h"
#include "bacnet/basic/binding/address.h"
#include "bacnet/bacdef.h"
#include "bacnet/bacapp.h"
#include "bacnet/bacdcode.h"
#include "bacnet/npdu.h"
#include "bacnet/apdu.h"
#include "bacnet/basic/object/device.h"
/* MS/TP specific */
#include "bacnet/datalink/dlmstp.h"
#include "rs485.h"
//#include "nvdata.h"
/* me */
#include "bacnet/basic/object/netport.h"
/* our local object data */
struct object_data {
bool Changes_Pending : 1;
uint8_t MAC_Address[1];
uint8_t Max_Master;
uint8_t Max_Info_Frames;
float Link_Speed;
};
/* this object example only supports 1 instance */
#define BACNET_NETWORK_PORTS_MAX 1
struct object_data Object_List[BACNET_NETWORK_PORTS_MAX];
/* instance number - can be overridden */
#ifndef BACNET_NETWORK_PORT_INSTANCE
#define BACNET_NETWORK_PORT_INSTANCE 1
#endif
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Network_Port_Properties_Required[] = { PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_STATUS_FLAGS, PROP_RELIABILITY,
PROP_OUT_OF_SERVICE, PROP_NETWORK_TYPE, PROP_PROTOCOL_LEVEL,
PROP_NETWORK_NUMBER, PROP_NETWORK_NUMBER_QUALITY, PROP_CHANGES_PENDING,
PROP_APDU_LENGTH, PROP_LINK_SPEED, -1 };
static const int Network_Port_Properties_Optional[] = { PROP_MAC_ADDRESS,
PROP_MAX_MASTER, PROP_MAX_INFO_FRAMES, -1 };
static const int Network_Port_Properties_Proprietary[] = { -1 };
/**
* Returns the list of required, optional, and proprietary properties.
* Used by ReadPropertyMultiple service.
*
* @param object_instance - object-instance number of the object
* @param pRequired - pointer to list of int terminated by -1, of
* BACnet required properties for this object.
* @param pOptional - pointer to list of int terminated by -1, of
* BACnet optkional properties for this object.
* @param pProprietary - pointer to list of int terminated by -1, of
* BACnet proprietary properties for this object.
*/
void Network_Port_Property_List(uint32_t object_instance,
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
(void)object_instance;
if (pRequired) {
*pRequired = Network_Port_Properties_Required;
}
if (pOptional) {
*pOptional = Network_Port_Properties_Optional;
}
if (pProprietary) {
*pProprietary = Network_Port_Properties_Proprietary;
}
return;
}
/**
* Returns the list of required, optional, and proprietary properties.
* Used by ReadPropertyMultiple service.
*
* @param pRequired - pointer to list of int terminated by -1, of
* BACnet required properties for this object.
* @param pOptional - pointer to list of int terminated by -1, of
* BACnet optkional properties for this object.
* @param pProprietary - pointer to list of int terminated by -1, of
* BACnet proprietary properties for this object.
*/
void Network_Port_Property_Lists(
const int **pRequired, const int **pOptional, const int **pProprietary)
{
Network_Port_Property_List(
BACNET_NETWORK_PORT_INSTANCE, pRequired, pOptional, pProprietary);
}
/**
* For a given object instance-number, loads the object-name into
* a characterstring. Note that the object name must be unique
* within this device.
*
* @param object_instance - object-instance number of the object
* @param object_name - holds the object-name retrieved
*
* @return true if object-name was retrieved
*/
bool Network_Port_Object_Name(
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
{
bool status = false;
if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
status = characterstring_init_ansi(object_name, "NP-1");
}
return status;
}
/**
* Determines if a given Network Port instance is valid
*
* @param object_instance - object-instance number of the object
*
* @return true if the instance is valid, and false if not
*/
bool Network_Port_Valid_Instance(uint32_t object_instance)
{
if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
return true;
}
return false;
}
/**
* Determines the number of Network Port objects
*
* @return Number of Network Port objects
*/
unsigned Network_Port_Count(void)
{
return BACNET_NETWORK_PORTS_MAX;
}
/**
* Determines the object instance-number for a given 0..N index
* of Network Port objects where N is Network_Port_Count().
*
* @param index - 0..BACNET_NETWORK_PORTS_MAX value
*
* @return object instance-number for the given index, or BACNET_MAX_INSTANCE
* for an invalid index.
*/
uint32_t Network_Port_Index_To_Instance(unsigned index)
{
if (index < BACNET_NETWORK_PORTS_MAX) {
return BACNET_NETWORK_PORT_INSTANCE;
}
return BACNET_MAX_INSTANCE;
}
/**
* For a given object instance-number, determines a 0..N index
* of Network Port objects where N is Network_Port_Count().
*
* @param object_instance - object-instance number of the object
*
* @return index for the given instance-number, or BACNET_NETWORK_PORTS_MAX
* if not valid.
*/
unsigned Network_Port_Instance_To_Index(uint32_t object_instance)
{
if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
return 0;
}
return BACNET_NETWORK_PORTS_MAX;
}
/**
* For a given object instance-number, returns the out-of-service
* property value
*
* @param object_instance - object-instance number of the object
*
* @return out-of-service property value
*/
bool Network_Port_Out_Of_Service(uint32_t object_instance)
{
(void)object_instance;
return false;
}
/**
* For a given object instance-number, gets the reliability.
*
* @param object_instance - object-instance number of the object
*
* @return reliability value
*/
BACNET_RELIABILITY Network_Port_Reliability(uint32_t object_instance)
{
(void)object_instance;
return RELIABILITY_NO_FAULT_DETECTED;
}
/**
* For a given object instance-number, gets the BACnet Network Type.
*
* @param object_instance - object-instance number of the object
*
* @return BACnet network type value
*/
uint8_t Network_Port_Type(uint32_t object_instance)
{
(void)object_instance;
return PORT_TYPE_MSTP;
}
/**
* For a given object instance-number, gets the BACnet Network Number.
*
* @param object_instance - object-instance number of the object
*
* @return BACnet network type value
*/
uint16_t Network_Port_Network_Number(uint32_t object_instance)
{
(void)object_instance;
/* A Network_Number of 0 indicates that the Network_Number
is not known or cannot be determined. */
return 0;
}
/**
* For a given object instance-number, gets the quality property
*
* @param object_instance - object-instance number of the object
*
* @return quality property value
*/
BACNET_PORT_QUALITY Network_Port_Quality(uint32_t object_instance)
{
(void)object_instance;
return PORT_QUALITY_CONFIGURED;
}
/**
* For a given object instance-number, loads the mac-address into
* an octet string.
*
* @param object_instance - object-instance number of the object
* @param mac_address - holds the mac-address retrieved
*
* @return true if mac-address was retrieved
*/
bool Network_Port_MAC_Address(
uint32_t object_instance, BACNET_OCTET_STRING *mac_address)
{
(void)object_instance;
Object_List[0].MAC_Address[0] = dlmstp_mac_address();
return octetstring_init(mac_address, Object_List[0].MAC_Address, 1);
}
/**
* @brief For a given object instance-number, set the mac-address and length
* @param object_instance - object-instance number of the object
* @param mac_src - holds the MAC address to be written
* @param mac_len - number of bytes in the MAC address
* @return true if object-name was set
*/
bool Network_Port_MAC_Address_Set(
uint32_t object_instance, uint8_t *mac_src, uint8_t mac_len)
{
if (mac_len == 1) {
Object_List[0].MAC_Address[0] = mac_src[0];
Object_List[0].Changes_Pending = true;
return true;
}
return false;
}
/**
* For a given object instance-number, gets the BACnet Network Number.
*
* @param object_instance - object-instance number of the object
*
* @return APDU length for this network port
*/
uint16_t Network_Port_APDU_Length(uint32_t object_instance)
{
(void)object_instance;
return MAX_APDU;
}
/**
* For a given object instance-number, gets the network communication rate
* as the number of bits per second. A value of 0 indicates an unknown
* communication rate.
*
* @param object_instance - object-instance number of the object
*
* @return Link_Speed for this network port, or 0 if unknown
*/
float Network_Port_Link_Speed(uint32_t object_instance)
{
(void)object_instance;
Object_List[0].Link_Speed = rs485_baud_rate();
return Object_List[0].Link_Speed;
}
/**
* @brief Set the device link speed (baud rate)
* @param object_instance The object instance number of the object
* @param value The new link speed value
* @return true if value was set
*/
bool Network_Port_Link_Speed_Set(uint32_t object_instance, float value)
{
bool status = false;
uint32_t baud = (uint32_t)value;
switch (baud) {
case 9600:
case 19200:
case 38400:
case 57600:
case 76800:
case 115200:
Object_List[0].Link_Speed = value;
Object_List[0].Changes_Pending = true;
status = true;
break;
}
return status;
}
/**
* @brief For a given object instance-number, returns the changes-pending flag
* @param object_instance - object-instance number of the object
* @return changes-pending property value
*/
bool Network_Port_Changes_Pending(uint32_t object_instance)
{
bool flag = false;
unsigned index = 0;
index = Network_Port_Instance_To_Index(object_instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
flag = Object_List[index].Changes_Pending;
}
return flag;
}
/**
* @brief For a given object instance-number, sets the changes-pending flag
* @param object_instance - object-instance number of the object
* @param flag - true=changes pending, false=no changes pending
* @return true if flag was set
*/
bool Network_Port_Changes_Pending_Set(uint32_t instance, bool flag)
{
unsigned index = 0;
index = Network_Port_Instance_To_Index(instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
Object_List[index].Changes_Pending = flag;
} else
return false;
return true;
}
/**
* @brief For a given object instance-number, gets the MS/TP Max_Master value
* @param object_instance - object-instance number of the object
* @return MS/TP Max_Master value
*/
uint8_t Network_Port_MSTP_Max_Master(uint32_t object_instance)
{
(void)object_instance;
Object_List[0].Max_Master = dlmstp_max_master();
return Object_List[0].Max_Master;
}
/**
* For a given object instance-number, sets the MS/TP Max_Master value
*
* @param object_instance - object-instance number of the object
* @param value - MS/TP Max_Master value 0..127
*
* @return true if values are within range and property is set.
*/
bool Network_Port_MSTP_Max_Master_Set(uint32_t object_instance, uint8_t value)
{
bool status = false;
(void)object_instance;
if (value <= dlmstp_max_master_limit()) {
Object_List[0].Max_Master = value;
Object_List[0].Changes_Pending = true;
status = true;
}
return status;
}
/**
* For a given object instance-number, gets the MS/TP Max_Info_Frames value
*
* @param object_instance - object-instance number of the object
*
* @return MS/TP Max_Info_Frames value
*/
uint8_t Network_Port_MSTP_Max_Info_Frames(uint32_t object_instance)
{
(void)object_instance;
Object_List[0].Max_Info_Frames = dlmstp_max_info_frames();
return Object_List[0].Max_Info_Frames;
}
/**
* For a given object instance-number, sets the MS/TP Max_Info_Frames value
*
* @param object_instance - object-instance number of the object
* @param value - MS/TP Max_Info_Frames value 0..255
*
* @return true if values are within range and property is set.
*/
bool Network_Port_MSTP_Max_Info_Frames_Set(
uint32_t object_instance, uint8_t value)
{
bool status = false;
(void)object_instance;
if (value <= dlmstp_max_info_frames_limit()) {
Object_List[0].Max_Info_Frames = value;
Object_List[0].Changes_Pending = true;
status = true;
}
return status;
}
/**
* ReadProperty handler for this object. For the given ReadProperty
* data, the application_data is loaded or the error flags are set.
*
* @param rpdata - BACNET_READ_PROPERTY_DATA data, including
* requested data and space for the reply, or error response.
*
* @return number of APDU bytes in the response, or
* BACNET_STATUS_ERROR on error.
*/
int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0;
BACNET_BIT_STRING bit_string;
BACNET_OCTET_STRING octet_string;
BACNET_CHARACTER_STRING char_string;
uint8_t *apdu = NULL;
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_NETWORK_PORT, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Network_Port_Object_Name(rpdata->object_instance, &char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_NETWORK_PORT);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
if (Network_Port_Reliability(rpdata->object_instance) ==
RELIABILITY_NO_FAULT_DETECTED) {
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
} else {
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, true);
}
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
if (Network_Port_Out_Of_Service(rpdata->object_instance)) {
bitstring_set_bit(
&bit_string, STATUS_FLAG_OUT_OF_SERVICE, true);
} else {
bitstring_set_bit(
&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_RELIABILITY:
apdu_len = encode_application_enumerated(
&apdu[0], Network_Port_Reliability(rpdata->object_instance));
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(
&apdu[0], Network_Port_Out_Of_Service(rpdata->object_instance));
break;
case PROP_NETWORK_TYPE:
apdu_len = encode_application_enumerated(
&apdu[0], Network_Port_Type(rpdata->object_instance));
break;
case PROP_PROTOCOL_LEVEL:
apdu_len = encode_application_enumerated(
&apdu[0], BACNET_PROTOCOL_LEVEL_PHYSICAL);
break;
case PROP_NETWORK_NUMBER:
apdu_len = encode_application_unsigned(
&apdu[0], Network_Port_Network_Number(rpdata->object_instance));
break;
case PROP_NETWORK_NUMBER_QUALITY:
apdu_len = encode_application_enumerated(
&apdu[0], Network_Port_Quality(rpdata->object_instance));
break;
case PROP_MAC_ADDRESS:
Network_Port_MAC_Address(rpdata->object_instance, &octet_string);
apdu_len = encode_application_octet_string(&apdu[0], &octet_string);
break;
case PROP_MAX_APDU_LENGTH_ACCEPTED:
apdu_len = encode_application_unsigned(
&apdu[0], Network_Port_APDU_Length(rpdata->object_instance));
break;
case PROP_LINK_SPEED:
apdu_len = encode_application_real(
&apdu[0], Network_Port_Link_Speed(rpdata->object_instance));
break;
case PROP_CHANGES_PENDING:
apdu_len = encode_application_boolean(&apdu[0],
Network_Port_Changes_Pending(rpdata->object_instance));
break;
case PROP_APDU_LENGTH:
apdu_len = encode_application_unsigned(
&apdu[0], Network_Port_APDU_Length(rpdata->object_instance));
break;
case PROP_MAX_MASTER:
apdu_len = encode_application_unsigned(&apdu[0],
Network_Port_MSTP_Max_Master(rpdata->object_instance));
break;
case PROP_MAX_INFO_FRAMES:
apdu_len = encode_application_unsigned(&apdu[0],
Network_Port_MSTP_Max_Info_Frames(rpdata->object_instance));
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = BACNET_STATUS_ERROR;
break;
}
return apdu_len;
}
/**
* WriteProperty handler for this object. For the given WriteProperty
* data, the application_data is loaded or the error flags are set.
*
* @param wp_data - BACNET_WRITE_PROPERTY_DATA data, including
* requested data and space for the reply, or error response.
*
* @return false if an error is loaded, true if no errors
*/
bool Network_Port_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
if (!Network_Port_Valid_Instance(wp_data->object_instance)) {
wp_data->error_class = ERROR_CLASS_OBJECT;
wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
return false;
}
/* decode the some of the request */
len = bacapp_decode_application_data(
wp_data->application_data, wp_data->application_data_len, &value);
if (len < 0) {
/* error while decoding - a value larger than we can handle */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
return false;
}
if ((wp_data->object_property != PROP_LINK_SPEEDS) &&
(wp_data->object_property != PROP_IP_DNS_SERVER) &&
(wp_data->object_property != PROP_IPV6_DNS_SERVER) &&
(wp_data->object_property != PROP_EVENT_MESSAGE_TEXTS) &&
(wp_data->object_property != PROP_EVENT_MESSAGE_TEXTS_CONFIG) &&
(wp_data->object_property != PROP_TAGS) &&
(wp_data->array_index != BACNET_ARRAY_ALL)) {
/* only array properties can have array options */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
return false;
}
/* FIXME: len < application_data_len: more data? */
switch (wp_data->object_property) {
case PROP_MAX_MASTER:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
status = Network_Port_MSTP_Max_Master_Set(
wp_data->object_instance, value.type.Unsigned_Int);
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAX_INFO_FRAMES:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
status = Network_Port_MSTP_Max_Info_Frames_Set(
wp_data->object_instance, value.type.Unsigned_Int);
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
status = true;
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_LINK_SPEED:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
if (!Network_Port_Link_Speed_Set(
wp_data->object_instance, value.type.Real)) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
status = true;
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAC_ADDRESS:
if (value.tag == BACNET_APPLICATION_TAG_OCTET_STRING) {
if (!Network_Port_MAC_Address_Set(wp_data->object_instance,
value.type.Octet_String.value,
value.type.Octet_String.length)) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
status = true;
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OBJECT_IDENTIFIER:
case PROP_OBJECT_NAME:
case PROP_OBJECT_TYPE:
case PROP_STATUS_FLAGS:
case PROP_RELIABILITY:
case PROP_OUT_OF_SERVICE:
case PROP_NETWORK_TYPE:
case PROP_PROTOCOL_LEVEL:
case PROP_NETWORK_NUMBER:
case PROP_NETWORK_NUMBER_QUALITY:
case PROP_MAX_APDU_LENGTH_ACCEPTED:
case PROP_CHANGES_PENDING:
case PROP_APDU_LENGTH:
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
default:
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
break;
}
return status;
}
/**
* Initializes the Network Port object data
*/
void Network_Port_Init(void)
{
Object_List[0].Changes_Pending = false;
Object_List[0].MAC_Address[0] = dlmstp_mac_address();
Object_List[0].Max_Master = dlmstp_max_master();
Object_List[0].Max_Info_Frames = dlmstp_max_info_frames();
Object_List[0].Link_Speed = rs485_baud_rate();
}
+3 -3
View File
@@ -118,7 +118,7 @@ void RS485_Cleanup(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
uint32_t RS485_Get_Baud_Rate(void)
uint32_t rs485_baud_rate(void)
{
return RS485_Baud;
}
@@ -129,7 +129,7 @@ uint32_t RS485_Get_Baud_Rate(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool RS485_Set_Baud_Rate(uint32_t baud)
bool rs485_baud_rate_set(uint32_t baud)
{
bool valid = true;
@@ -266,7 +266,7 @@ int main(void)
unsigned i = 0;
uint8_t DataRegister;
RS485_Set_Baud_Rate(38400);
rs485_baud_rate_set(38400);
RS485_Initialize();
/* receive task */
for (;;) {
+2 -2
View File
@@ -49,9 +49,9 @@ extern "C" {
void RS485_Turnaround_Delay(
void);
uint32_t RS485_Get_Baud_Rate(
uint32_t rs485_baud_rate(
void);
bool RS485_Set_Baud_Rate(
bool rs485_baud_rate_set(
uint32_t baud);
#ifdef __cplusplus
+2
View File
@@ -91,6 +91,7 @@ HALSRC = main.c \
bacnet.c \
bname.c \
device.c \
netport.c \
ai.c \
av.c \
bi.c \
@@ -218,6 +219,7 @@ BFLAGS += -DBACAPP_OBJECT_ID
BFLAGS += -DBACAPP_UNSIGNED
BFLAGS += -DBACAPP_ENUMERATED
BFLAGS += -DBACAPP_CHARACTER_STRING
BFLAGS += -DBACAPP_OCTET_STRING
BFLAGS += -DWRITE_PROPERTY
## Compile options for C files
+4
View File
@@ -266,6 +266,7 @@
<state>BACAPP_UNSIGNED</state>
<state>BACAPP_ENUMERATED</state>
<state>BACAPP_CHARACTER_STRING</state>
<state>BACAPP_OCTET_STRING</state>
<state>WRITE_PROPERTY</state>
</option>
<option>
@@ -1331,6 +1332,7 @@
<state>BACAPP_UNSIGNED</state>
<state>BACAPP_ENUMERATED</state>
<state>BACAPP_CHARACTER_STRING</state>
<state>BACAPP_OCTET_STRING</state>
<state>WRITE_PROPERTY</state>
</option>
<option>
@@ -2396,6 +2398,7 @@
<state>BACAPP_UNSIGNED</state>
<state>BACAPP_ENUMERATED</state>
<state>BACAPP_CHARACTER_STRING</state>
<state>BACAPP_OCTET_STRING</state>
<state>WRITE_PROPERTY</state>
</option>
<option>
@@ -3461,6 +3464,7 @@
<state>BACAPP_UNSIGNED</state>
<state>BACAPP_ENUMERATED</state>
<state>BACAPP_CHARACTER_STRING</state>
<state>BACAPP_OCTET_STRING</state>
<state>WRITE_PROPERTY</state>
</option>
<option>
+2 -1
View File
@@ -1,7 +1,7 @@
<!DOCTYPE CrossStudio_Project_File>
<solution Name="bacnet" version="2">
<project Name="bacnet">
<configuration Name="Common" Platform="AVR" Target="ATmega644P" avr_architecture="V2E" avr_debug_interface="JTAG" avr_flash_size="128K" build_use_hardware_multiplier="Yes" c_preprocessor_definitions="BACDL_MSTP;MAX_APDU=128;MAX_TSM_TRANSACTIONS=0;MAX_CHARACTER_STRING_BYTES=64;MAX_OCTET_STRING_BYTES=64;BACAPP_BOOLEAN;BACAPP_REAL;BACAPP_OBJECT_ID;BACAPP_UNSIGNED;BACAPP_ENUMERATED;BACAPP_CHARACTER_STRING;WRITE_PROPERTY" c_user_include_directories="$(ProjectDir);$(ProjectDir)/crossworks;$(ProjectDir)/../../include;$(ProjectDir)/../../src" linker_call_stack_size="1024" linker_memory_map_file="$(PackagesDir)/targets/avr/ATmega644P.xml" project_directory="" project_type="Executable"/>
<configuration Name="Common" Platform="AVR" Target="ATmega644P" avr_architecture="V2E" avr_debug_interface="JTAG" avr_flash_size="128K" build_use_hardware_multiplier="Yes" c_preprocessor_definitions="BACDL_MSTP;MAX_APDU=128;MAX_TSM_TRANSACTIONS=0;MAX_CHARACTER_STRING_BYTES=64;MAX_OCTET_STRING_BYTES=64;BACAPP_BOOLEAN;BACAPP_REAL;BACAPP_OBJECT_ID;BACAPP_UNSIGNED;BACAPP_ENUMERATED;BACAPP_CHARACTER_STRING;BACAPP_OCTET_STRING;WRITE_PROPERTY" c_user_include_directories="$(ProjectDir);$(ProjectDir)/crossworks;$(ProjectDir)/../../include;$(ProjectDir)/../../src" linker_call_stack_size="1024" linker_memory_map_file="$(PackagesDir)/targets/avr/ATmega644P.xml" project_directory="" project_type="Executable"/>
<folder Name="Source Files">
<configuration Name="Common" filter="c;h;s;asm;inc;s90"/>
<file file_name="adc.c">
@@ -14,6 +14,7 @@
<file file_name="bname.c"/>
<file file_name="bo.c"/>
<file file_name="device.c"/>
<file file_name="netport.c"/>
<file file_name="dlmstp.c"/>
<file file_name="eeprom.c"/>
<file file_name="init.c"/>
+15 -5
View File
@@ -42,6 +42,9 @@
#include "bacnet/proplist.h"
/* objects */
#include "bacnet/basic/object/device.h"
#if (BACNET_PROTOCOL_REVISION >= 17)
#include "bacnet/basic/object/netport.h"
#endif
#include "bacnet/basic/object/ai.h"
#include "bacnet/basic/object/av.h"
#include "bacnet/basic/object/bi.h"
@@ -64,11 +67,12 @@ static struct my_object_functions {
read_property_function Object_Read_Property;
write_property_function Object_Write_Property;
rpm_property_lists_function Object_RPM_List;
} Object_Table[] = { { OBJECT_DEVICE, NULL, /* don't init - recursive! */
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists },
} Object_Table[] = {
{ OBJECT_DEVICE, NULL, /* don't init - recursive! */
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists },
{ OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
Analog_Input_Object_Name, Analog_Input_Read_Property, NULL,
@@ -85,6 +89,12 @@ static struct my_object_functions {
Binary_Output_Index_To_Instance, Binary_Output_Valid_Instance,
Binary_Output_Object_Name, Binary_Output_Read_Property,
Binary_Output_Write_Property, Binary_Output_Property_Lists },
#if (BACNET_PROTOCOL_REVISION >= 17)
{ OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
Network_Port_Object_Name, Network_Port_Read_Property,
Network_Port_Write_Property, Network_Port_Property_Lists },
#endif
{ MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL } };
/* note: you really only need to define variables for
+10
View File
@@ -1412,3 +1412,13 @@ void dlmstp_get_broadcast_address(BACNET_ADDRESS *dest)
return;
}
uint8_t dlmstp_max_info_frames_limit(void)
{
return MSTP_PDU_PACKET_COUNT;
}
uint8_t dlmstp_max_master_limit(void)
{
return 127;
}
+748
View File
@@ -0,0 +1,748 @@
/**
* @file
* @author Steve Karg
* @date 2016
* @brief Network port objects, customize for your use
*
* @section DESCRIPTION
*
* The Network Port object provides access to the configuration
* and properties of network ports of a device.
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "bacnet/config.h"
#include "bacnet/basic/binding/address.h"
#include "bacnet/bacdef.h"
#include "bacnet/bacapp.h"
#include "bacnet/bacdcode.h"
#include "bacnet/npdu.h"
#include "bacnet/apdu.h"
#include "bacnet/basic/object/device.h"
/* MS/TP specific */
#include "bacnet/datalink/dlmstp.h"
#include "rs485.h"
//#include "nvdata.h"
/* me */
#include "bacnet/basic/object/netport.h"
/* our local object data */
struct object_data {
bool Changes_Pending : 1;
uint8_t MAC_Address[1];
uint8_t Max_Master;
uint8_t Max_Info_Frames;
float Link_Speed;
};
/* this object example only supports 1 instance */
#define BACNET_NETWORK_PORTS_MAX 1
struct object_data Object_List[BACNET_NETWORK_PORTS_MAX];
/* instance number - can be overridden */
#ifndef BACNET_NETWORK_PORT_INSTANCE
#define BACNET_NETWORK_PORT_INSTANCE 1
#endif
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Network_Port_Properties_Required[] = { PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_STATUS_FLAGS, PROP_RELIABILITY,
PROP_OUT_OF_SERVICE, PROP_NETWORK_TYPE, PROP_PROTOCOL_LEVEL,
PROP_NETWORK_NUMBER, PROP_NETWORK_NUMBER_QUALITY, PROP_CHANGES_PENDING,
PROP_APDU_LENGTH, PROP_LINK_SPEED, -1 };
static const int Network_Port_Properties_Optional[] = { PROP_MAC_ADDRESS,
PROP_MAX_MASTER, PROP_MAX_INFO_FRAMES, -1 };
static const int Network_Port_Properties_Proprietary[] = { -1 };
/**
* Returns the list of required, optional, and proprietary properties.
* Used by ReadPropertyMultiple service.
*
* @param object_instance - object-instance number of the object
* @param pRequired - pointer to list of int terminated by -1, of
* BACnet required properties for this object.
* @param pOptional - pointer to list of int terminated by -1, of
* BACnet optkional properties for this object.
* @param pProprietary - pointer to list of int terminated by -1, of
* BACnet proprietary properties for this object.
*/
void Network_Port_Property_List(uint32_t object_instance,
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
(void)object_instance;
if (pRequired) {
*pRequired = Network_Port_Properties_Required;
}
if (pOptional) {
*pOptional = Network_Port_Properties_Optional;
}
if (pProprietary) {
*pProprietary = Network_Port_Properties_Proprietary;
}
return;
}
/**
* Returns the list of required, optional, and proprietary properties.
* Used by ReadPropertyMultiple service.
*
* @param pRequired - pointer to list of int terminated by -1, of
* BACnet required properties for this object.
* @param pOptional - pointer to list of int terminated by -1, of
* BACnet optkional properties for this object.
* @param pProprietary - pointer to list of int terminated by -1, of
* BACnet proprietary properties for this object.
*/
void Network_Port_Property_Lists(
const int **pRequired, const int **pOptional, const int **pProprietary)
{
Network_Port_Property_List(
BACNET_NETWORK_PORT_INSTANCE, pRequired, pOptional, pProprietary);
}
/**
* For a given object instance-number, loads the object-name into
* a characterstring. Note that the object name must be unique
* within this device.
*
* @param object_instance - object-instance number of the object
* @param object_name - holds the object-name retrieved
*
* @return true if object-name was retrieved
*/
bool Network_Port_Object_Name(
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
{
bool status = false;
if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
status = characterstring_init_ansi(object_name, "NP-1");
}
return status;
}
/**
* Determines if a given Network Port instance is valid
*
* @param object_instance - object-instance number of the object
*
* @return true if the instance is valid, and false if not
*/
bool Network_Port_Valid_Instance(uint32_t object_instance)
{
if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
return true;
}
return false;
}
/**
* Determines the number of Network Port objects
*
* @return Number of Network Port objects
*/
unsigned Network_Port_Count(void)
{
return BACNET_NETWORK_PORTS_MAX;
}
/**
* Determines the object instance-number for a given 0..N index
* of Network Port objects where N is Network_Port_Count().
*
* @param index - 0..BACNET_NETWORK_PORTS_MAX value
*
* @return object instance-number for the given index, or BACNET_MAX_INSTANCE
* for an invalid index.
*/
uint32_t Network_Port_Index_To_Instance(unsigned index)
{
if (index < BACNET_NETWORK_PORTS_MAX) {
return BACNET_NETWORK_PORT_INSTANCE;
}
return BACNET_MAX_INSTANCE;
}
/**
* For a given object instance-number, determines a 0..N index
* of Network Port objects where N is Network_Port_Count().
*
* @param object_instance - object-instance number of the object
*
* @return index for the given instance-number, or BACNET_NETWORK_PORTS_MAX
* if not valid.
*/
unsigned Network_Port_Instance_To_Index(uint32_t object_instance)
{
if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
return 0;
}
return BACNET_NETWORK_PORTS_MAX;
}
/**
* For a given object instance-number, returns the out-of-service
* property value
*
* @param object_instance - object-instance number of the object
*
* @return out-of-service property value
*/
bool Network_Port_Out_Of_Service(uint32_t object_instance)
{
(void)object_instance;
return false;
}
/**
* For a given object instance-number, gets the reliability.
*
* @param object_instance - object-instance number of the object
*
* @return reliability value
*/
BACNET_RELIABILITY Network_Port_Reliability(uint32_t object_instance)
{
(void)object_instance;
return RELIABILITY_NO_FAULT_DETECTED;
}
/**
* For a given object instance-number, gets the BACnet Network Type.
*
* @param object_instance - object-instance number of the object
*
* @return BACnet network type value
*/
uint8_t Network_Port_Type(uint32_t object_instance)
{
(void)object_instance;
return PORT_TYPE_MSTP;
}
/**
* For a given object instance-number, gets the BACnet Network Number.
*
* @param object_instance - object-instance number of the object
*
* @return BACnet network type value
*/
uint16_t Network_Port_Network_Number(uint32_t object_instance)
{
(void)object_instance;
/* A Network_Number of 0 indicates that the Network_Number
is not known or cannot be determined. */
return 0;
}
/**
* For a given object instance-number, gets the quality property
*
* @param object_instance - object-instance number of the object
*
* @return quality property value
*/
BACNET_PORT_QUALITY Network_Port_Quality(uint32_t object_instance)
{
(void)object_instance;
return PORT_QUALITY_CONFIGURED;
}
/**
* For a given object instance-number, loads the mac-address into
* an octet string.
*
* @param object_instance - object-instance number of the object
* @param mac_address - holds the mac-address retrieved
*
* @return true if mac-address was retrieved
*/
bool Network_Port_MAC_Address(
uint32_t object_instance, BACNET_OCTET_STRING *mac_address)
{
(void)object_instance;
Object_List[0].MAC_Address[0] = dlmstp_mac_address();
return octetstring_init(mac_address, Object_List[0].MAC_Address, 1);
}
/**
* @brief For a given object instance-number, set the mac-address and length
* @param object_instance - object-instance number of the object
* @param mac_src - holds the MAC address to be written
* @param mac_len - number of bytes in the MAC address
* @return true if object-name was set
*/
bool Network_Port_MAC_Address_Set(
uint32_t object_instance, uint8_t *mac_src, uint8_t mac_len)
{
if (mac_len == 1) {
Object_List[0].MAC_Address[0] = mac_src[0];
Object_List[0].Changes_Pending = true;
return true;
}
return false;
}
/**
* For a given object instance-number, gets the BACnet Network Number.
*
* @param object_instance - object-instance number of the object
*
* @return APDU length for this network port
*/
uint16_t Network_Port_APDU_Length(uint32_t object_instance)
{
(void)object_instance;
return MAX_APDU;
}
/**
* For a given object instance-number, gets the network communication rate
* as the number of bits per second. A value of 0 indicates an unknown
* communication rate.
*
* @param object_instance - object-instance number of the object
*
* @return Link_Speed for this network port, or 0 if unknown
*/
float Network_Port_Link_Speed(uint32_t object_instance)
{
(void)object_instance;
Object_List[0].Link_Speed = rs485_baud_rate();
return Object_List[0].Link_Speed;
}
/**
* @brief Set the device link speed (baud rate)
* @param object_instance The object instance number of the object
* @param value The new link speed value
* @return true if value was set
*/
bool Network_Port_Link_Speed_Set(uint32_t object_instance, float value)
{
bool status = false;
uint32_t baud = (uint32_t)value;
switch (baud) {
case 9600:
case 19200:
case 38400:
case 57600:
case 76800:
case 115200:
Object_List[0].Link_Speed = value;
Object_List[0].Changes_Pending = true;
status = true;
break;
}
return status;
}
/**
* @brief For a given object instance-number, returns the changes-pending flag
* @param object_instance - object-instance number of the object
* @return changes-pending property value
*/
bool Network_Port_Changes_Pending(uint32_t object_instance)
{
bool flag = false;
unsigned index = 0;
index = Network_Port_Instance_To_Index(object_instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
flag = Object_List[index].Changes_Pending;
}
return flag;
}
/**
* @brief For a given object instance-number, sets the changes-pending flag
* @param object_instance - object-instance number of the object
* @param flag - true=changes pending, false=no changes pending
* @return true if flag was set
*/
bool Network_Port_Changes_Pending_Set(uint32_t instance, bool flag)
{
unsigned index = 0;
index = Network_Port_Instance_To_Index(instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
Object_List[index].Changes_Pending = flag;
} else
return false;
return true;
}
/**
* @brief For a given object instance-number, gets the MS/TP Max_Master value
* @param object_instance - object-instance number of the object
* @return MS/TP Max_Master value
*/
uint8_t Network_Port_MSTP_Max_Master(uint32_t object_instance)
{
(void)object_instance;
Object_List[0].Max_Master = dlmstp_max_master();
return Object_List[0].Max_Master;
}
/**
* For a given object instance-number, sets the MS/TP Max_Master value
*
* @param object_instance - object-instance number of the object
* @param value - MS/TP Max_Master value 0..127
*
* @return true if values are within range and property is set.
*/
bool Network_Port_MSTP_Max_Master_Set(uint32_t object_instance, uint8_t value)
{
bool status = false;
(void)object_instance;
if (value <= dlmstp_max_master_limit()) {
Object_List[0].Max_Master = value;
Object_List[0].Changes_Pending = true;
status = true;
}
return status;
}
/**
* For a given object instance-number, gets the MS/TP Max_Info_Frames value
*
* @param object_instance - object-instance number of the object
*
* @return MS/TP Max_Info_Frames value
*/
uint8_t Network_Port_MSTP_Max_Info_Frames(uint32_t object_instance)
{
(void)object_instance;
Object_List[0].Max_Info_Frames = dlmstp_max_info_frames();
return Object_List[0].Max_Info_Frames;
}
/**
* For a given object instance-number, sets the MS/TP Max_Info_Frames value
*
* @param object_instance - object-instance number of the object
* @param value - MS/TP Max_Info_Frames value 0..255
*
* @return true if values are within range and property is set.
*/
bool Network_Port_MSTP_Max_Info_Frames_Set(
uint32_t object_instance, uint8_t value)
{
bool status = false;
(void)object_instance;
if (value <= dlmstp_max_info_frames_limit()) {
Object_List[0].Max_Info_Frames = value;
Object_List[0].Changes_Pending = true;
status = true;
}
return status;
}
/**
* ReadProperty handler for this object. For the given ReadProperty
* data, the application_data is loaded or the error flags are set.
*
* @param rpdata - BACNET_READ_PROPERTY_DATA data, including
* requested data and space for the reply, or error response.
*
* @return number of APDU bytes in the response, or
* BACNET_STATUS_ERROR on error.
*/
int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0;
BACNET_BIT_STRING bit_string;
BACNET_OCTET_STRING octet_string;
BACNET_CHARACTER_STRING char_string;
uint8_t *apdu = NULL;
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_NETWORK_PORT, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Network_Port_Object_Name(rpdata->object_instance, &char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_NETWORK_PORT);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
if (Network_Port_Reliability(rpdata->object_instance) ==
RELIABILITY_NO_FAULT_DETECTED) {
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
} else {
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, true);
}
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
if (Network_Port_Out_Of_Service(rpdata->object_instance)) {
bitstring_set_bit(
&bit_string, STATUS_FLAG_OUT_OF_SERVICE, true);
} else {
bitstring_set_bit(
&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_RELIABILITY:
apdu_len = encode_application_enumerated(
&apdu[0], Network_Port_Reliability(rpdata->object_instance));
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(
&apdu[0], Network_Port_Out_Of_Service(rpdata->object_instance));
break;
case PROP_NETWORK_TYPE:
apdu_len = encode_application_enumerated(
&apdu[0], Network_Port_Type(rpdata->object_instance));
break;
case PROP_PROTOCOL_LEVEL:
apdu_len = encode_application_enumerated(
&apdu[0], BACNET_PROTOCOL_LEVEL_PHYSICAL);
break;
case PROP_NETWORK_NUMBER:
apdu_len = encode_application_unsigned(
&apdu[0], Network_Port_Network_Number(rpdata->object_instance));
break;
case PROP_NETWORK_NUMBER_QUALITY:
apdu_len = encode_application_enumerated(
&apdu[0], Network_Port_Quality(rpdata->object_instance));
break;
case PROP_MAC_ADDRESS:
Network_Port_MAC_Address(rpdata->object_instance, &octet_string);
apdu_len = encode_application_octet_string(&apdu[0], &octet_string);
break;
case PROP_MAX_APDU_LENGTH_ACCEPTED:
apdu_len = encode_application_unsigned(
&apdu[0], Network_Port_APDU_Length(rpdata->object_instance));
break;
case PROP_LINK_SPEED:
apdu_len = encode_application_real(
&apdu[0], Network_Port_Link_Speed(rpdata->object_instance));
break;
case PROP_CHANGES_PENDING:
apdu_len = encode_application_boolean(&apdu[0],
Network_Port_Changes_Pending(rpdata->object_instance));
break;
case PROP_APDU_LENGTH:
apdu_len = encode_application_unsigned(
&apdu[0], Network_Port_APDU_Length(rpdata->object_instance));
break;
case PROP_MAX_MASTER:
apdu_len = encode_application_unsigned(&apdu[0],
Network_Port_MSTP_Max_Master(rpdata->object_instance));
break;
case PROP_MAX_INFO_FRAMES:
apdu_len = encode_application_unsigned(&apdu[0],
Network_Port_MSTP_Max_Info_Frames(rpdata->object_instance));
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = BACNET_STATUS_ERROR;
break;
}
return apdu_len;
}
/**
* WriteProperty handler for this object. For the given WriteProperty
* data, the application_data is loaded or the error flags are set.
*
* @param wp_data - BACNET_WRITE_PROPERTY_DATA data, including
* requested data and space for the reply, or error response.
*
* @return false if an error is loaded, true if no errors
*/
bool Network_Port_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
if (!Network_Port_Valid_Instance(wp_data->object_instance)) {
wp_data->error_class = ERROR_CLASS_OBJECT;
wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
return false;
}
/* decode the some of the request */
len = bacapp_decode_application_data(
wp_data->application_data, wp_data->application_data_len, &value);
if (len < 0) {
/* error while decoding - a value larger than we can handle */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
return false;
}
if ((wp_data->object_property != PROP_LINK_SPEEDS) &&
(wp_data->object_property != PROP_IP_DNS_SERVER) &&
(wp_data->object_property != PROP_IPV6_DNS_SERVER) &&
(wp_data->object_property != PROP_EVENT_MESSAGE_TEXTS) &&
(wp_data->object_property != PROP_EVENT_MESSAGE_TEXTS_CONFIG) &&
(wp_data->object_property != PROP_TAGS) &&
(wp_data->array_index != BACNET_ARRAY_ALL)) {
/* only array properties can have array options */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
return false;
}
/* FIXME: len < application_data_len: more data? */
switch (wp_data->object_property) {
case PROP_MAX_MASTER:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
status = Network_Port_MSTP_Max_Master_Set(
wp_data->object_instance, value.type.Unsigned_Int);
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAX_INFO_FRAMES:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
status = Network_Port_MSTP_Max_Info_Frames_Set(
wp_data->object_instance, value.type.Unsigned_Int);
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
status = true;
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_LINK_SPEED:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
if (!Network_Port_Link_Speed_Set(
wp_data->object_instance, value.type.Real)) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
status = true;
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAC_ADDRESS:
if (value.tag == BACNET_APPLICATION_TAG_OCTET_STRING) {
if (!Network_Port_MAC_Address_Set(wp_data->object_instance,
value.type.Octet_String.value,
value.type.Octet_String.length)) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
status = true;
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OBJECT_IDENTIFIER:
case PROP_OBJECT_NAME:
case PROP_OBJECT_TYPE:
case PROP_STATUS_FLAGS:
case PROP_RELIABILITY:
case PROP_OUT_OF_SERVICE:
case PROP_NETWORK_TYPE:
case PROP_PROTOCOL_LEVEL:
case PROP_NETWORK_NUMBER:
case PROP_NETWORK_NUMBER_QUALITY:
case PROP_MAX_APDU_LENGTH_ACCEPTED:
case PROP_CHANGES_PENDING:
case PROP_APDU_LENGTH:
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
default:
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
break;
}
return status;
}
/**
* Initializes the Network Port object data
*/
void Network_Port_Init(void)
{
Object_List[0].Changes_Pending = false;
Object_List[0].MAC_Address[0] = dlmstp_mac_address();
Object_List[0].Max_Master = dlmstp_max_master();
Object_List[0].Max_Info_Frames = dlmstp_max_info_frames();
Object_List[0].Link_Speed = rs485_baud_rate();
}
+1
View File
@@ -25,6 +25,7 @@ PLATFORM_SRC = \
$(PLATFORM_DIR)/bo.c \
$(PLATFORM_DIR)/device.c \
$(PLATFORM_DIR)/dlmstp.c \
$(PLATFORM_DIR)/netport.c \
$(PLATFORM_DIR)/led.c \
$(PLATFORM_DIR)/rs485.c \
$(PLATFORM_DIR)/stm32f10x_it.c \
+3
View File
@@ -1275,6 +1275,9 @@
<file>
<name>$PROJ_DIR$\mstimer-init.c</name>
</file>
<file>
<name>$PROJ_DIR$\netport.c</name>
</file>
<file>
<name>$PROJ_DIR$\rs485.c</name>
</file>
+15 -5
View File
@@ -41,6 +41,9 @@
/* objects */
#include "bacnet/basic/object/device.h"
#include "bacnet/basic/object/bo.h"
#if (BACNET_PROTOCOL_REVISION >= 17)
#include "bacnet/basic/object/netport.h"
#endif
/* forward prototype */
int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata);
@@ -56,15 +59,22 @@ static struct my_object_functions {
read_property_function Object_Read_Property;
write_property_function Object_Write_Property;
rpm_property_lists_function Object_RPM_List;
} Object_Table[] = { { OBJECT_DEVICE, NULL, /* don't init - recursive! */
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists },
} Object_Table[] = {
{ OBJECT_DEVICE, NULL, /* don't init - recursive! */
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists },
{ OBJECT_BINARY_OUTPUT, Binary_Output_Init, Binary_Output_Count,
Binary_Output_Index_To_Instance, Binary_Output_Valid_Instance,
Binary_Output_Object_Name, Binary_Output_Read_Property,
Binary_Output_Write_Property, Binary_Output_Property_Lists },
#if (BACNET_PROTOCOL_REVISION >= 17)
{ OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
Network_Port_Object_Name, Network_Port_Read_Property,
Network_Port_Write_Property, Network_Port_Property_Lists },
#endif
{ MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL } };
/* note: you really only need to define variables for
+10
View File
@@ -1641,3 +1641,13 @@ bool dlmstp_sole_master(void)
return false;
}
uint8_t dlmstp_max_info_frames_limit(void)
{
return MSTP_PDU_PACKET_COUNT;
}
uint8_t dlmstp_max_master_limit(void)
{
return 127;
}
+748
View File
@@ -0,0 +1,748 @@
/**
* @file
* @author Steve Karg
* @date 2016
* @brief Network port objects, customize for your use
*
* @section DESCRIPTION
*
* The Network Port object provides access to the configuration
* and properties of network ports of a device.
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "bacnet/config.h"
#include "bacnet/basic/binding/address.h"
#include "bacnet/bacdef.h"
#include "bacnet/bacapp.h"
#include "bacnet/bacdcode.h"
#include "bacnet/npdu.h"
#include "bacnet/apdu.h"
#include "bacnet/basic/object/device.h"
/* MS/TP specific */
#include "bacnet/datalink/dlmstp.h"
#include "rs485.h"
//#include "nvdata.h"
/* me */
#include "bacnet/basic/object/netport.h"
/* our local object data */
struct object_data {
bool Changes_Pending : 1;
uint8_t MAC_Address[1];
uint8_t Max_Master;
uint8_t Max_Info_Frames;
float Link_Speed;
};
/* this object example only supports 1 instance */
#define BACNET_NETWORK_PORTS_MAX 1
struct object_data Object_List[BACNET_NETWORK_PORTS_MAX];
/* instance number - can be overridden */
#ifndef BACNET_NETWORK_PORT_INSTANCE
#define BACNET_NETWORK_PORT_INSTANCE 1
#endif
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Network_Port_Properties_Required[] = { PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_STATUS_FLAGS, PROP_RELIABILITY,
PROP_OUT_OF_SERVICE, PROP_NETWORK_TYPE, PROP_PROTOCOL_LEVEL,
PROP_NETWORK_NUMBER, PROP_NETWORK_NUMBER_QUALITY, PROP_CHANGES_PENDING,
PROP_APDU_LENGTH, PROP_LINK_SPEED, -1 };
static const int Network_Port_Properties_Optional[] = { PROP_MAC_ADDRESS,
PROP_MAX_MASTER, PROP_MAX_INFO_FRAMES, -1 };
static const int Network_Port_Properties_Proprietary[] = { -1 };
/**
* Returns the list of required, optional, and proprietary properties.
* Used by ReadPropertyMultiple service.
*
* @param object_instance - object-instance number of the object
* @param pRequired - pointer to list of int terminated by -1, of
* BACnet required properties for this object.
* @param pOptional - pointer to list of int terminated by -1, of
* BACnet optkional properties for this object.
* @param pProprietary - pointer to list of int terminated by -1, of
* BACnet proprietary properties for this object.
*/
void Network_Port_Property_List(uint32_t object_instance,
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
(void)object_instance;
if (pRequired) {
*pRequired = Network_Port_Properties_Required;
}
if (pOptional) {
*pOptional = Network_Port_Properties_Optional;
}
if (pProprietary) {
*pProprietary = Network_Port_Properties_Proprietary;
}
return;
}
/**
* Returns the list of required, optional, and proprietary properties.
* Used by ReadPropertyMultiple service.
*
* @param pRequired - pointer to list of int terminated by -1, of
* BACnet required properties for this object.
* @param pOptional - pointer to list of int terminated by -1, of
* BACnet optkional properties for this object.
* @param pProprietary - pointer to list of int terminated by -1, of
* BACnet proprietary properties for this object.
*/
void Network_Port_Property_Lists(
const int **pRequired, const int **pOptional, const int **pProprietary)
{
Network_Port_Property_List(
BACNET_NETWORK_PORT_INSTANCE, pRequired, pOptional, pProprietary);
}
/**
* For a given object instance-number, loads the object-name into
* a characterstring. Note that the object name must be unique
* within this device.
*
* @param object_instance - object-instance number of the object
* @param object_name - holds the object-name retrieved
*
* @return true if object-name was retrieved
*/
bool Network_Port_Object_Name(
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
{
bool status = false;
if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
status = characterstring_init_ansi(object_name, "NP-1");
}
return status;
}
/**
* Determines if a given Network Port instance is valid
*
* @param object_instance - object-instance number of the object
*
* @return true if the instance is valid, and false if not
*/
bool Network_Port_Valid_Instance(uint32_t object_instance)
{
if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
return true;
}
return false;
}
/**
* Determines the number of Network Port objects
*
* @return Number of Network Port objects
*/
unsigned Network_Port_Count(void)
{
return BACNET_NETWORK_PORTS_MAX;
}
/**
* Determines the object instance-number for a given 0..N index
* of Network Port objects where N is Network_Port_Count().
*
* @param index - 0..BACNET_NETWORK_PORTS_MAX value
*
* @return object instance-number for the given index, or BACNET_MAX_INSTANCE
* for an invalid index.
*/
uint32_t Network_Port_Index_To_Instance(unsigned index)
{
if (index < BACNET_NETWORK_PORTS_MAX) {
return BACNET_NETWORK_PORT_INSTANCE;
}
return BACNET_MAX_INSTANCE;
}
/**
* For a given object instance-number, determines a 0..N index
* of Network Port objects where N is Network_Port_Count().
*
* @param object_instance - object-instance number of the object
*
* @return index for the given instance-number, or BACNET_NETWORK_PORTS_MAX
* if not valid.
*/
unsigned Network_Port_Instance_To_Index(uint32_t object_instance)
{
if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
return 0;
}
return BACNET_NETWORK_PORTS_MAX;
}
/**
* For a given object instance-number, returns the out-of-service
* property value
*
* @param object_instance - object-instance number of the object
*
* @return out-of-service property value
*/
bool Network_Port_Out_Of_Service(uint32_t object_instance)
{
(void)object_instance;
return false;
}
/**
* For a given object instance-number, gets the reliability.
*
* @param object_instance - object-instance number of the object
*
* @return reliability value
*/
BACNET_RELIABILITY Network_Port_Reliability(uint32_t object_instance)
{
(void)object_instance;
return RELIABILITY_NO_FAULT_DETECTED;
}
/**
* For a given object instance-number, gets the BACnet Network Type.
*
* @param object_instance - object-instance number of the object
*
* @return BACnet network type value
*/
uint8_t Network_Port_Type(uint32_t object_instance)
{
(void)object_instance;
return PORT_TYPE_MSTP;
}
/**
* For a given object instance-number, gets the BACnet Network Number.
*
* @param object_instance - object-instance number of the object
*
* @return BACnet network type value
*/
uint16_t Network_Port_Network_Number(uint32_t object_instance)
{
(void)object_instance;
/* A Network_Number of 0 indicates that the Network_Number
is not known or cannot be determined. */
return 0;
}
/**
* For a given object instance-number, gets the quality property
*
* @param object_instance - object-instance number of the object
*
* @return quality property value
*/
BACNET_PORT_QUALITY Network_Port_Quality(uint32_t object_instance)
{
(void)object_instance;
return PORT_QUALITY_CONFIGURED;
}
/**
* For a given object instance-number, loads the mac-address into
* an octet string.
*
* @param object_instance - object-instance number of the object
* @param mac_address - holds the mac-address retrieved
*
* @return true if mac-address was retrieved
*/
bool Network_Port_MAC_Address(
uint32_t object_instance, BACNET_OCTET_STRING *mac_address)
{
(void)object_instance;
Object_List[0].MAC_Address[0] = dlmstp_mac_address();
return octetstring_init(mac_address, Object_List[0].MAC_Address, 1);
}
/**
* @brief For a given object instance-number, set the mac-address and length
* @param object_instance - object-instance number of the object
* @param mac_src - holds the MAC address to be written
* @param mac_len - number of bytes in the MAC address
* @return true if object-name was set
*/
bool Network_Port_MAC_Address_Set(
uint32_t object_instance, uint8_t *mac_src, uint8_t mac_len)
{
if (mac_len == 1) {
Object_List[0].MAC_Address[0] = mac_src[0];
Object_List[0].Changes_Pending = true;
return true;
}
return false;
}
/**
* For a given object instance-number, gets the BACnet Network Number.
*
* @param object_instance - object-instance number of the object
*
* @return APDU length for this network port
*/
uint16_t Network_Port_APDU_Length(uint32_t object_instance)
{
(void)object_instance;
return MAX_APDU;
}
/**
* For a given object instance-number, gets the network communication rate
* as the number of bits per second. A value of 0 indicates an unknown
* communication rate.
*
* @param object_instance - object-instance number of the object
*
* @return Link_Speed for this network port, or 0 if unknown
*/
float Network_Port_Link_Speed(uint32_t object_instance)
{
(void)object_instance;
Object_List[0].Link_Speed = rs485_baud_rate();
return Object_List[0].Link_Speed;
}
/**
* @brief Set the device link speed (baud rate)
* @param object_instance The object instance number of the object
* @param value The new link speed value
* @return true if value was set
*/
bool Network_Port_Link_Speed_Set(uint32_t object_instance, float value)
{
bool status = false;
uint32_t baud = (uint32_t)value;
switch (baud) {
case 9600:
case 19200:
case 38400:
case 57600:
case 76800:
case 115200:
Object_List[0].Link_Speed = value;
Object_List[0].Changes_Pending = true;
status = true;
break;
}
return status;
}
/**
* @brief For a given object instance-number, returns the changes-pending flag
* @param object_instance - object-instance number of the object
* @return changes-pending property value
*/
bool Network_Port_Changes_Pending(uint32_t object_instance)
{
bool flag = false;
unsigned index = 0;
index = Network_Port_Instance_To_Index(object_instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
flag = Object_List[index].Changes_Pending;
}
return flag;
}
/**
* @brief For a given object instance-number, sets the changes-pending flag
* @param object_instance - object-instance number of the object
* @param flag - true=changes pending, false=no changes pending
* @return true if flag was set
*/
bool Network_Port_Changes_Pending_Set(uint32_t instance, bool flag)
{
unsigned index = 0;
index = Network_Port_Instance_To_Index(instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
Object_List[index].Changes_Pending = flag;
} else
return false;
return true;
}
/**
* @brief For a given object instance-number, gets the MS/TP Max_Master value
* @param object_instance - object-instance number of the object
* @return MS/TP Max_Master value
*/
uint8_t Network_Port_MSTP_Max_Master(uint32_t object_instance)
{
(void)object_instance;
Object_List[0].Max_Master = dlmstp_max_master();
return Object_List[0].Max_Master;
}
/**
* For a given object instance-number, sets the MS/TP Max_Master value
*
* @param object_instance - object-instance number of the object
* @param value - MS/TP Max_Master value 0..127
*
* @return true if values are within range and property is set.
*/
bool Network_Port_MSTP_Max_Master_Set(uint32_t object_instance, uint8_t value)
{
bool status = false;
(void)object_instance;
if (value <= dlmstp_max_master_limit()) {
Object_List[0].Max_Master = value;
Object_List[0].Changes_Pending = true;
status = true;
}
return status;
}
/**
* For a given object instance-number, gets the MS/TP Max_Info_Frames value
*
* @param object_instance - object-instance number of the object
*
* @return MS/TP Max_Info_Frames value
*/
uint8_t Network_Port_MSTP_Max_Info_Frames(uint32_t object_instance)
{
(void)object_instance;
Object_List[0].Max_Info_Frames = dlmstp_max_info_frames();
return Object_List[0].Max_Info_Frames;
}
/**
* For a given object instance-number, sets the MS/TP Max_Info_Frames value
*
* @param object_instance - object-instance number of the object
* @param value - MS/TP Max_Info_Frames value 0..255
*
* @return true if values are within range and property is set.
*/
bool Network_Port_MSTP_Max_Info_Frames_Set(
uint32_t object_instance, uint8_t value)
{
bool status = false;
(void)object_instance;
if (value <= dlmstp_max_info_frames_limit()) {
Object_List[0].Max_Info_Frames = value;
Object_List[0].Changes_Pending = true;
status = true;
}
return status;
}
/**
* ReadProperty handler for this object. For the given ReadProperty
* data, the application_data is loaded or the error flags are set.
*
* @param rpdata - BACNET_READ_PROPERTY_DATA data, including
* requested data and space for the reply, or error response.
*
* @return number of APDU bytes in the response, or
* BACNET_STATUS_ERROR on error.
*/
int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0;
BACNET_BIT_STRING bit_string;
BACNET_OCTET_STRING octet_string;
BACNET_CHARACTER_STRING char_string;
uint8_t *apdu = NULL;
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_NETWORK_PORT, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Network_Port_Object_Name(rpdata->object_instance, &char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_NETWORK_PORT);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
if (Network_Port_Reliability(rpdata->object_instance) ==
RELIABILITY_NO_FAULT_DETECTED) {
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
} else {
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, true);
}
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
if (Network_Port_Out_Of_Service(rpdata->object_instance)) {
bitstring_set_bit(
&bit_string, STATUS_FLAG_OUT_OF_SERVICE, true);
} else {
bitstring_set_bit(
&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_RELIABILITY:
apdu_len = encode_application_enumerated(
&apdu[0], Network_Port_Reliability(rpdata->object_instance));
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(
&apdu[0], Network_Port_Out_Of_Service(rpdata->object_instance));
break;
case PROP_NETWORK_TYPE:
apdu_len = encode_application_enumerated(
&apdu[0], Network_Port_Type(rpdata->object_instance));
break;
case PROP_PROTOCOL_LEVEL:
apdu_len = encode_application_enumerated(
&apdu[0], BACNET_PROTOCOL_LEVEL_PHYSICAL);
break;
case PROP_NETWORK_NUMBER:
apdu_len = encode_application_unsigned(
&apdu[0], Network_Port_Network_Number(rpdata->object_instance));
break;
case PROP_NETWORK_NUMBER_QUALITY:
apdu_len = encode_application_enumerated(
&apdu[0], Network_Port_Quality(rpdata->object_instance));
break;
case PROP_MAC_ADDRESS:
Network_Port_MAC_Address(rpdata->object_instance, &octet_string);
apdu_len = encode_application_octet_string(&apdu[0], &octet_string);
break;
case PROP_MAX_APDU_LENGTH_ACCEPTED:
apdu_len = encode_application_unsigned(
&apdu[0], Network_Port_APDU_Length(rpdata->object_instance));
break;
case PROP_LINK_SPEED:
apdu_len = encode_application_real(
&apdu[0], Network_Port_Link_Speed(rpdata->object_instance));
break;
case PROP_CHANGES_PENDING:
apdu_len = encode_application_boolean(&apdu[0],
Network_Port_Changes_Pending(rpdata->object_instance));
break;
case PROP_APDU_LENGTH:
apdu_len = encode_application_unsigned(
&apdu[0], Network_Port_APDU_Length(rpdata->object_instance));
break;
case PROP_MAX_MASTER:
apdu_len = encode_application_unsigned(&apdu[0],
Network_Port_MSTP_Max_Master(rpdata->object_instance));
break;
case PROP_MAX_INFO_FRAMES:
apdu_len = encode_application_unsigned(&apdu[0],
Network_Port_MSTP_Max_Info_Frames(rpdata->object_instance));
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = BACNET_STATUS_ERROR;
break;
}
return apdu_len;
}
/**
* WriteProperty handler for this object. For the given WriteProperty
* data, the application_data is loaded or the error flags are set.
*
* @param wp_data - BACNET_WRITE_PROPERTY_DATA data, including
* requested data and space for the reply, or error response.
*
* @return false if an error is loaded, true if no errors
*/
bool Network_Port_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
if (!Network_Port_Valid_Instance(wp_data->object_instance)) {
wp_data->error_class = ERROR_CLASS_OBJECT;
wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
return false;
}
/* decode the some of the request */
len = bacapp_decode_application_data(
wp_data->application_data, wp_data->application_data_len, &value);
if (len < 0) {
/* error while decoding - a value larger than we can handle */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
return false;
}
if ((wp_data->object_property != PROP_LINK_SPEEDS) &&
(wp_data->object_property != PROP_IP_DNS_SERVER) &&
(wp_data->object_property != PROP_IPV6_DNS_SERVER) &&
(wp_data->object_property != PROP_EVENT_MESSAGE_TEXTS) &&
(wp_data->object_property != PROP_EVENT_MESSAGE_TEXTS_CONFIG) &&
(wp_data->object_property != PROP_TAGS) &&
(wp_data->array_index != BACNET_ARRAY_ALL)) {
/* only array properties can have array options */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
return false;
}
/* FIXME: len < application_data_len: more data? */
switch (wp_data->object_property) {
case PROP_MAX_MASTER:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
status = Network_Port_MSTP_Max_Master_Set(
wp_data->object_instance, value.type.Unsigned_Int);
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAX_INFO_FRAMES:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
status = Network_Port_MSTP_Max_Info_Frames_Set(
wp_data->object_instance, value.type.Unsigned_Int);
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
status = true;
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_LINK_SPEED:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
if (!Network_Port_Link_Speed_Set(
wp_data->object_instance, value.type.Real)) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
status = true;
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAC_ADDRESS:
if (value.tag == BACNET_APPLICATION_TAG_OCTET_STRING) {
if (!Network_Port_MAC_Address_Set(wp_data->object_instance,
value.type.Octet_String.value,
value.type.Octet_String.length)) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
status = true;
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OBJECT_IDENTIFIER:
case PROP_OBJECT_NAME:
case PROP_OBJECT_TYPE:
case PROP_STATUS_FLAGS:
case PROP_RELIABILITY:
case PROP_OUT_OF_SERVICE:
case PROP_NETWORK_TYPE:
case PROP_PROTOCOL_LEVEL:
case PROP_NETWORK_NUMBER:
case PROP_NETWORK_NUMBER_QUALITY:
case PROP_MAX_APDU_LENGTH_ACCEPTED:
case PROP_CHANGES_PENDING:
case PROP_APDU_LENGTH:
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
default:
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
break;
}
return status;
}
/**
* Initializes the Network Port object data
*/
void Network_Port_Init(void)
{
Object_List[0].Changes_Pending = false;
Object_List[0].MAC_Address[0] = dlmstp_mac_address();
Object_List[0].Max_Master = dlmstp_max_master();
Object_List[0].Max_Info_Frames = dlmstp_max_info_frames();
Object_List[0].Link_Speed = rs485_baud_rate();
}
+10 -9
View File
@@ -37,7 +37,9 @@
#include "bacnet/version.h"
#include "bacnet/basic/services.h"
/* objects */
#if (BACNET_PROTOCOL_REVISION >= 17)
#include "bacnet/basic/object/netport.h"
#endif
#include "bacnet/basic/object/device.h"
/* forward prototype */
@@ -54,20 +56,19 @@ static struct my_object_functions {
read_property_function Object_Read_Property;
write_property_function Object_Write_Property;
rpm_property_lists_function Object_RPM_List;
} Object_Table[] = { { OBJECT_DEVICE, NULL, /* don't init - recursive! */
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists },
{
} Object_Table[] = {
{ OBJECT_DEVICE, NULL, /* don't init - recursive! */
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists },
#if (BACNET_PROTOCOL_REVISION >= 17)
OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
{ OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
Network_Port_Object_Name, Network_Port_Read_Property,
Network_Port_Write_Property, Network_Port_Property_Lists },
{
#endif
MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL } };
{ MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL } };
/* note: you really only need to define variables for
properties that are writable or that may change.
-92
View File
@@ -746,95 +746,3 @@ void Network_Port_Init(void)
Object_List[0].Max_Info_Frames = dlmstp_max_info_frames();
Object_List[0].Link_Speed = rs485_baud_rate();
}
#ifdef BACNET_UNIT_TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
pErrorClass = pErrorClass;
pErrorCode = pErrorCode;
return false;
}
void test_network_port(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
int test_len = 0;
BACNET_READ_PROPERTY_DATA rpdata;
/* for decode value data */
BACNET_APPLICATION_DATA_VALUE value;
const int *pRequired = NULL;
const int *pOptional = NULL;
const int *pProprietary = NULL;
unsigned count = 0;
unsigned index = 0;
Network_Port_init();
count = Network_Port_Count();
for (index = 0; index < count; index++) {
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_NETWORK_PORT;
rpdata.object_instance = Network_Port_Index_To_Instance(index);
Network_Port_Property_Lists(&pRequired, &pOptional, &pProprietary);
while ((*pRequired) != -1) {
rpdata.object_property = *pRequired;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Network_Port_Read_Property(&rpdata);
ct_test(pTest, len != 0);
test_len = bacapp_decode_application_data(rpdata.application_data,
(uint8_t)rpdata.application_data_len, &value);
ct_test(pTest, test_len >= 0);
if (test_len < 0) {
printf("<decode failed!>\n");
}
pRequired++;
}
while ((*pOptional) != -1) {
rpdata.object_property = *pOptional;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Network_Port_Read_Property(&rpdata);
ct_test(pTest, len != 0);
test_len = bacapp_decode_application_data(rpdata.application_data,
(uint8_t)rpdata.application_data_len, &value);
ct_test(pTest, test_len >= 0);
if (test_len < 0) {
printf("<decode failed!>\n");
}
pOptional++;
}
}
return;
}
#ifdef TEST_NETWORK_PORT
int main(void)
{
Test *pTest;
bool rc;
pTest = ct_create("BACnet Network Port", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, test_network_port);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif
#endif /* TEST */
+3
View File
@@ -696,6 +696,9 @@
<Compile Include="device.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="netport.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="dlmstp.c">
<SubType>compile</SubType>
<CustomCompilationSetting Condition="'$(Configuration)' == 'Debug'">
+9
View File
@@ -43,6 +43,9 @@
/* objects */
#include "bacnet/basic/object/device.h"
#include "bacnet/basic/object/ai.h"
#if (BACNET_PROTOCOL_REVISION >= 17)
#include "bacnet/basic/object/netport.h"
#endif
/* forward prototype */
int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata);
@@ -71,6 +74,12 @@ static struct my_object_functions {
Analog_Input_Object_Name, Analog_Input_Read_Property,
Analog_Input_Write_Property, Analog_Input_Property_Lists, NULL, NULL,
NULL },
#if (BACNET_PROTOCOL_REVISION >= 17)
{ OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
Network_Port_Object_Name, Network_Port_Read_Property,
Network_Port_Write_Property, Network_Port_Property_Lists },
#endif
{ MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
+10
View File
@@ -1470,3 +1470,13 @@ bool dlmstp_sole_master(void)
return false;
}
uint8_t dlmstp_max_info_frames_limit(void)
{
return MSTP_PDU_PACKET_COUNT;
}
uint8_t dlmstp_max_master_limit(void)
{
return 127;
}
+748
View File
@@ -0,0 +1,748 @@
/**
* @file
* @author Steve Karg
* @date 2016
* @brief Network port objects, customize for your use
*
* @section DESCRIPTION
*
* The Network Port object provides access to the configuration
* and properties of network ports of a device.
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "bacnet/config.h"
#include "bacnet/basic/binding/address.h"
#include "bacnet/bacdef.h"
#include "bacnet/bacapp.h"
#include "bacnet/bacdcode.h"
#include "bacnet/npdu.h"
#include "bacnet/apdu.h"
#include "bacnet/basic/object/device.h"
/* MS/TP specific */
#include "bacnet/datalink/dlmstp.h"
#include "rs485.h"
//#include "nvdata.h"
/* me */
#include "bacnet/basic/object/netport.h"
/* our local object data */
struct object_data {
bool Changes_Pending : 1;
uint8_t MAC_Address[1];
uint8_t Max_Master;
uint8_t Max_Info_Frames;
float Link_Speed;
};
/* this object example only supports 1 instance */
#define BACNET_NETWORK_PORTS_MAX 1
struct object_data Object_List[BACNET_NETWORK_PORTS_MAX];
/* instance number - can be overridden */
#ifndef BACNET_NETWORK_PORT_INSTANCE
#define BACNET_NETWORK_PORT_INSTANCE 1
#endif
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Network_Port_Properties_Required[] = { PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_STATUS_FLAGS, PROP_RELIABILITY,
PROP_OUT_OF_SERVICE, PROP_NETWORK_TYPE, PROP_PROTOCOL_LEVEL,
PROP_NETWORK_NUMBER, PROP_NETWORK_NUMBER_QUALITY, PROP_CHANGES_PENDING,
PROP_APDU_LENGTH, PROP_LINK_SPEED, -1 };
static const int Network_Port_Properties_Optional[] = { PROP_MAC_ADDRESS,
PROP_MAX_MASTER, PROP_MAX_INFO_FRAMES, -1 };
static const int Network_Port_Properties_Proprietary[] = { -1 };
/**
* Returns the list of required, optional, and proprietary properties.
* Used by ReadPropertyMultiple service.
*
* @param object_instance - object-instance number of the object
* @param pRequired - pointer to list of int terminated by -1, of
* BACnet required properties for this object.
* @param pOptional - pointer to list of int terminated by -1, of
* BACnet optkional properties for this object.
* @param pProprietary - pointer to list of int terminated by -1, of
* BACnet proprietary properties for this object.
*/
void Network_Port_Property_List(uint32_t object_instance,
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
(void)object_instance;
if (pRequired) {
*pRequired = Network_Port_Properties_Required;
}
if (pOptional) {
*pOptional = Network_Port_Properties_Optional;
}
if (pProprietary) {
*pProprietary = Network_Port_Properties_Proprietary;
}
return;
}
/**
* Returns the list of required, optional, and proprietary properties.
* Used by ReadPropertyMultiple service.
*
* @param pRequired - pointer to list of int terminated by -1, of
* BACnet required properties for this object.
* @param pOptional - pointer to list of int terminated by -1, of
* BACnet optkional properties for this object.
* @param pProprietary - pointer to list of int terminated by -1, of
* BACnet proprietary properties for this object.
*/
void Network_Port_Property_Lists(
const int **pRequired, const int **pOptional, const int **pProprietary)
{
Network_Port_Property_List(
BACNET_NETWORK_PORT_INSTANCE, pRequired, pOptional, pProprietary);
}
/**
* For a given object instance-number, loads the object-name into
* a characterstring. Note that the object name must be unique
* within this device.
*
* @param object_instance - object-instance number of the object
* @param object_name - holds the object-name retrieved
*
* @return true if object-name was retrieved
*/
bool Network_Port_Object_Name(
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
{
bool status = false;
if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
status = characterstring_init_ansi(object_name, "NP-1");
}
return status;
}
/**
* Determines if a given Network Port instance is valid
*
* @param object_instance - object-instance number of the object
*
* @return true if the instance is valid, and false if not
*/
bool Network_Port_Valid_Instance(uint32_t object_instance)
{
if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
return true;
}
return false;
}
/**
* Determines the number of Network Port objects
*
* @return Number of Network Port objects
*/
unsigned Network_Port_Count(void)
{
return BACNET_NETWORK_PORTS_MAX;
}
/**
* Determines the object instance-number for a given 0..N index
* of Network Port objects where N is Network_Port_Count().
*
* @param index - 0..BACNET_NETWORK_PORTS_MAX value
*
* @return object instance-number for the given index, or BACNET_MAX_INSTANCE
* for an invalid index.
*/
uint32_t Network_Port_Index_To_Instance(unsigned index)
{
if (index < BACNET_NETWORK_PORTS_MAX) {
return BACNET_NETWORK_PORT_INSTANCE;
}
return BACNET_MAX_INSTANCE;
}
/**
* For a given object instance-number, determines a 0..N index
* of Network Port objects where N is Network_Port_Count().
*
* @param object_instance - object-instance number of the object
*
* @return index for the given instance-number, or BACNET_NETWORK_PORTS_MAX
* if not valid.
*/
unsigned Network_Port_Instance_To_Index(uint32_t object_instance)
{
if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
return 0;
}
return BACNET_NETWORK_PORTS_MAX;
}
/**
* For a given object instance-number, returns the out-of-service
* property value
*
* @param object_instance - object-instance number of the object
*
* @return out-of-service property value
*/
bool Network_Port_Out_Of_Service(uint32_t object_instance)
{
(void)object_instance;
return false;
}
/**
* For a given object instance-number, gets the reliability.
*
* @param object_instance - object-instance number of the object
*
* @return reliability value
*/
BACNET_RELIABILITY Network_Port_Reliability(uint32_t object_instance)
{
(void)object_instance;
return RELIABILITY_NO_FAULT_DETECTED;
}
/**
* For a given object instance-number, gets the BACnet Network Type.
*
* @param object_instance - object-instance number of the object
*
* @return BACnet network type value
*/
uint8_t Network_Port_Type(uint32_t object_instance)
{
(void)object_instance;
return PORT_TYPE_MSTP;
}
/**
* For a given object instance-number, gets the BACnet Network Number.
*
* @param object_instance - object-instance number of the object
*
* @return BACnet network type value
*/
uint16_t Network_Port_Network_Number(uint32_t object_instance)
{
(void)object_instance;
/* A Network_Number of 0 indicates that the Network_Number
is not known or cannot be determined. */
return 0;
}
/**
* For a given object instance-number, gets the quality property
*
* @param object_instance - object-instance number of the object
*
* @return quality property value
*/
BACNET_PORT_QUALITY Network_Port_Quality(uint32_t object_instance)
{
(void)object_instance;
return PORT_QUALITY_CONFIGURED;
}
/**
* For a given object instance-number, loads the mac-address into
* an octet string.
*
* @param object_instance - object-instance number of the object
* @param mac_address - holds the mac-address retrieved
*
* @return true if mac-address was retrieved
*/
bool Network_Port_MAC_Address(
uint32_t object_instance, BACNET_OCTET_STRING *mac_address)
{
(void)object_instance;
Object_List[0].MAC_Address[0] = dlmstp_mac_address();
return octetstring_init(mac_address, Object_List[0].MAC_Address, 1);
}
/**
* @brief For a given object instance-number, set the mac-address and length
* @param object_instance - object-instance number of the object
* @param mac_src - holds the MAC address to be written
* @param mac_len - number of bytes in the MAC address
* @return true if object-name was set
*/
bool Network_Port_MAC_Address_Set(
uint32_t object_instance, uint8_t *mac_src, uint8_t mac_len)
{
if (mac_len == 1) {
Object_List[0].MAC_Address[0] = mac_src[0];
Object_List[0].Changes_Pending = true;
return true;
}
return false;
}
/**
* For a given object instance-number, gets the BACnet Network Number.
*
* @param object_instance - object-instance number of the object
*
* @return APDU length for this network port
*/
uint16_t Network_Port_APDU_Length(uint32_t object_instance)
{
(void)object_instance;
return MAX_APDU;
}
/**
* For a given object instance-number, gets the network communication rate
* as the number of bits per second. A value of 0 indicates an unknown
* communication rate.
*
* @param object_instance - object-instance number of the object
*
* @return Link_Speed for this network port, or 0 if unknown
*/
float Network_Port_Link_Speed(uint32_t object_instance)
{
(void)object_instance;
Object_List[0].Link_Speed = rs485_baud_rate();
return Object_List[0].Link_Speed;
}
/**
* @brief Set the device link speed (baud rate)
* @param object_instance The object instance number of the object
* @param value The new link speed value
* @return true if value was set
*/
bool Network_Port_Link_Speed_Set(uint32_t object_instance, float value)
{
bool status = false;
uint32_t baud = (uint32_t)value;
switch (baud) {
case 9600:
case 19200:
case 38400:
case 57600:
case 76800:
case 115200:
Object_List[0].Link_Speed = value;
Object_List[0].Changes_Pending = true;
status = true;
break;
}
return status;
}
/**
* @brief For a given object instance-number, returns the changes-pending flag
* @param object_instance - object-instance number of the object
* @return changes-pending property value
*/
bool Network_Port_Changes_Pending(uint32_t object_instance)
{
bool flag = false;
unsigned index = 0;
index = Network_Port_Instance_To_Index(object_instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
flag = Object_List[index].Changes_Pending;
}
return flag;
}
/**
* @brief For a given object instance-number, sets the changes-pending flag
* @param object_instance - object-instance number of the object
* @param flag - true=changes pending, false=no changes pending
* @return true if flag was set
*/
bool Network_Port_Changes_Pending_Set(uint32_t instance, bool flag)
{
unsigned index = 0;
index = Network_Port_Instance_To_Index(instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
Object_List[index].Changes_Pending = flag;
} else
return false;
return true;
}
/**
* @brief For a given object instance-number, gets the MS/TP Max_Master value
* @param object_instance - object-instance number of the object
* @return MS/TP Max_Master value
*/
uint8_t Network_Port_MSTP_Max_Master(uint32_t object_instance)
{
(void)object_instance;
Object_List[0].Max_Master = dlmstp_max_master();
return Object_List[0].Max_Master;
}
/**
* For a given object instance-number, sets the MS/TP Max_Master value
*
* @param object_instance - object-instance number of the object
* @param value - MS/TP Max_Master value 0..127
*
* @return true if values are within range and property is set.
*/
bool Network_Port_MSTP_Max_Master_Set(uint32_t object_instance, uint8_t value)
{
bool status = false;
(void)object_instance;
if (value <= dlmstp_max_master_limit()) {
Object_List[0].Max_Master = value;
Object_List[0].Changes_Pending = true;
status = true;
}
return status;
}
/**
* For a given object instance-number, gets the MS/TP Max_Info_Frames value
*
* @param object_instance - object-instance number of the object
*
* @return MS/TP Max_Info_Frames value
*/
uint8_t Network_Port_MSTP_Max_Info_Frames(uint32_t object_instance)
{
(void)object_instance;
Object_List[0].Max_Info_Frames = dlmstp_max_info_frames();
return Object_List[0].Max_Info_Frames;
}
/**
* For a given object instance-number, sets the MS/TP Max_Info_Frames value
*
* @param object_instance - object-instance number of the object
* @param value - MS/TP Max_Info_Frames value 0..255
*
* @return true if values are within range and property is set.
*/
bool Network_Port_MSTP_Max_Info_Frames_Set(
uint32_t object_instance, uint8_t value)
{
bool status = false;
(void)object_instance;
if (value <= dlmstp_max_info_frames_limit()) {
Object_List[0].Max_Info_Frames = value;
Object_List[0].Changes_Pending = true;
status = true;
}
return status;
}
/**
* ReadProperty handler for this object. For the given ReadProperty
* data, the application_data is loaded or the error flags are set.
*
* @param rpdata - BACNET_READ_PROPERTY_DATA data, including
* requested data and space for the reply, or error response.
*
* @return number of APDU bytes in the response, or
* BACNET_STATUS_ERROR on error.
*/
int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0;
BACNET_BIT_STRING bit_string;
BACNET_OCTET_STRING octet_string;
BACNET_CHARACTER_STRING char_string;
uint8_t *apdu = NULL;
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_NETWORK_PORT, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Network_Port_Object_Name(rpdata->object_instance, &char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_NETWORK_PORT);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
if (Network_Port_Reliability(rpdata->object_instance) ==
RELIABILITY_NO_FAULT_DETECTED) {
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
} else {
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, true);
}
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
if (Network_Port_Out_Of_Service(rpdata->object_instance)) {
bitstring_set_bit(
&bit_string, STATUS_FLAG_OUT_OF_SERVICE, true);
} else {
bitstring_set_bit(
&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_RELIABILITY:
apdu_len = encode_application_enumerated(
&apdu[0], Network_Port_Reliability(rpdata->object_instance));
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(
&apdu[0], Network_Port_Out_Of_Service(rpdata->object_instance));
break;
case PROP_NETWORK_TYPE:
apdu_len = encode_application_enumerated(
&apdu[0], Network_Port_Type(rpdata->object_instance));
break;
case PROP_PROTOCOL_LEVEL:
apdu_len = encode_application_enumerated(
&apdu[0], BACNET_PROTOCOL_LEVEL_PHYSICAL);
break;
case PROP_NETWORK_NUMBER:
apdu_len = encode_application_unsigned(
&apdu[0], Network_Port_Network_Number(rpdata->object_instance));
break;
case PROP_NETWORK_NUMBER_QUALITY:
apdu_len = encode_application_enumerated(
&apdu[0], Network_Port_Quality(rpdata->object_instance));
break;
case PROP_MAC_ADDRESS:
Network_Port_MAC_Address(rpdata->object_instance, &octet_string);
apdu_len = encode_application_octet_string(&apdu[0], &octet_string);
break;
case PROP_MAX_APDU_LENGTH_ACCEPTED:
apdu_len = encode_application_unsigned(
&apdu[0], Network_Port_APDU_Length(rpdata->object_instance));
break;
case PROP_LINK_SPEED:
apdu_len = encode_application_real(
&apdu[0], Network_Port_Link_Speed(rpdata->object_instance));
break;
case PROP_CHANGES_PENDING:
apdu_len = encode_application_boolean(&apdu[0],
Network_Port_Changes_Pending(rpdata->object_instance));
break;
case PROP_APDU_LENGTH:
apdu_len = encode_application_unsigned(
&apdu[0], Network_Port_APDU_Length(rpdata->object_instance));
break;
case PROP_MAX_MASTER:
apdu_len = encode_application_unsigned(&apdu[0],
Network_Port_MSTP_Max_Master(rpdata->object_instance));
break;
case PROP_MAX_INFO_FRAMES:
apdu_len = encode_application_unsigned(&apdu[0],
Network_Port_MSTP_Max_Info_Frames(rpdata->object_instance));
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = BACNET_STATUS_ERROR;
break;
}
return apdu_len;
}
/**
* WriteProperty handler for this object. For the given WriteProperty
* data, the application_data is loaded or the error flags are set.
*
* @param wp_data - BACNET_WRITE_PROPERTY_DATA data, including
* requested data and space for the reply, or error response.
*
* @return false if an error is loaded, true if no errors
*/
bool Network_Port_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
if (!Network_Port_Valid_Instance(wp_data->object_instance)) {
wp_data->error_class = ERROR_CLASS_OBJECT;
wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
return false;
}
/* decode the some of the request */
len = bacapp_decode_application_data(
wp_data->application_data, wp_data->application_data_len, &value);
if (len < 0) {
/* error while decoding - a value larger than we can handle */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
return false;
}
if ((wp_data->object_property != PROP_LINK_SPEEDS) &&
(wp_data->object_property != PROP_IP_DNS_SERVER) &&
(wp_data->object_property != PROP_IPV6_DNS_SERVER) &&
(wp_data->object_property != PROP_EVENT_MESSAGE_TEXTS) &&
(wp_data->object_property != PROP_EVENT_MESSAGE_TEXTS_CONFIG) &&
(wp_data->object_property != PROP_TAGS) &&
(wp_data->array_index != BACNET_ARRAY_ALL)) {
/* only array properties can have array options */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
return false;
}
/* FIXME: len < application_data_len: more data? */
switch (wp_data->object_property) {
case PROP_MAX_MASTER:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
status = Network_Port_MSTP_Max_Master_Set(
wp_data->object_instance, value.type.Unsigned_Int);
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAX_INFO_FRAMES:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
status = Network_Port_MSTP_Max_Info_Frames_Set(
wp_data->object_instance, value.type.Unsigned_Int);
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
status = true;
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_LINK_SPEED:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
if (!Network_Port_Link_Speed_Set(
wp_data->object_instance, value.type.Real)) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
status = true;
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAC_ADDRESS:
if (value.tag == BACNET_APPLICATION_TAG_OCTET_STRING) {
if (!Network_Port_MAC_Address_Set(wp_data->object_instance,
value.type.Octet_String.value,
value.type.Octet_String.length)) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
status = true;
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OBJECT_IDENTIFIER:
case PROP_OBJECT_NAME:
case PROP_OBJECT_TYPE:
case PROP_STATUS_FLAGS:
case PROP_RELIABILITY:
case PROP_OUT_OF_SERVICE:
case PROP_NETWORK_TYPE:
case PROP_PROTOCOL_LEVEL:
case PROP_NETWORK_NUMBER:
case PROP_NETWORK_NUMBER_QUALITY:
case PROP_MAX_APDU_LENGTH_ACCEPTED:
case PROP_CHANGES_PENDING:
case PROP_APDU_LENGTH:
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
default:
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
break;
}
return status;
}
/**
* Initializes the Network Port object data
*/
void Network_Port_Init(void)
{
Object_List[0].Changes_Pending = false;
Object_List[0].MAC_Address[0] = dlmstp_mac_address();
Object_List[0].Max_Master = dlmstp_max_master();
Object_List[0].Max_Info_Frames = dlmstp_max_info_frames();
Object_List[0].Link_Speed = rs485_baud_rate();
}
+4 -1
View File
@@ -40,6 +40,7 @@
#include "bacnet/basic/binding/address.h"
#include "bacnet/bacdef.h"
#include "bacnet/bacapp.h"
#include "bacnet/bacint.h"
#include "bacnet/bacdcode.h"
#include "bacnet/npdu.h"
#include "bacnet/apdu.h"
@@ -599,7 +600,9 @@ bool Network_Port_MAC_Address(
case PORT_TYPE_BIP:
memcpy(
&ip_mac[0], &Object_List[index].Network.IPv4.IP_Address, 4);
memcpy(&ip_mac[4], &Object_List[index].Network.IPv4.Port, 2);
/* convert port from host-byte-order to network-byte-order */
encode_unsigned16(&ip_mac[4],
&Object_List[index].Network.IPv4.Port);
mac = &ip_mac[0];
mac_len = sizeof(ip_mac);
break;
+33 -8
View File
@@ -39,6 +39,9 @@
#include "bacnet/rp.h"
/* basic objects, services, TSM, and datalink */
#include "bacnet/basic/object/device.h"
#if (BACNET_PROTOCOL_REVISION >= 17)
#include "bacnet/basic/object/netport.h"
#endif
#include "bacnet/basic/tsm/tsm.h"
#include "bacnet/basic/services.h"
#include "bacnet/datalink/datalink.h"
@@ -112,16 +115,37 @@ void handler_read_property(uint8_t *service_request,
fprintf(stderr, "RP: Bad Encoding.\n");
#endif
} else {
/* Test for case of indefinite Device object instance */
/* When the object-type in the Object Identifier parameter
contains the value DEVICE and the instance in the 'Object
Identifier' parameter contains the value 4194303, the responding
BACnet-user shall treat the Object Identifier as if it correctly
matched the local Device object. This allows the device instance
of a device that does not generate I-Am messages to be
determined. */
if ((rpdata.object_type == OBJECT_DEVICE) &&
(rpdata.object_instance == BACNET_MAX_INSTANCE)) {
rpdata.object_instance = Device_Object_Instance_Number();
}
#if (BACNET_PROTOCOL_REVISION >= 17)
/* When the object-type in the Object Identifier parameter
contains the value NETWORK_PORT and the instance in the 'Object
Identifier' parameter contains the value 4194303, the responding
BACnet-user shall treat the Object Identifier as if it correctly
matched the local Network Port object representing the network
port through which the request was received. This allows the
network port instance of the network port that was used to
receive the request to be determined. */
if ((rpdata.object_type == OBJECT_NETWORK_PORT) &&
(rpdata.object_instance == BACNET_MAX_INSTANCE)) {
rpdata.object_instance = Network_Port_Index_To_Instance(0);
}
#endif
apdu_len = rp_ack_encode_apdu_init(
&Handler_Transmit_Buffer[npdu_len], service_data->invoke_id, &rpdata);
&Handler_Transmit_Buffer[npdu_len], service_data->invoke_id,
&rpdata);
/* configure our storage */
rpdata.application_data = &Handler_Transmit_Buffer[npdu_len + apdu_len];
rpdata.application_data =
&Handler_Transmit_Buffer[npdu_len + apdu_len];
rpdata.application_data_len =
sizeof(Handler_Transmit_Buffer) - (npdu_len + apdu_len);
len = Device_Read_Property(&rpdata);
@@ -131,10 +155,11 @@ void handler_read_property(uint8_t *service_request,
&Handler_Transmit_Buffer[npdu_len + apdu_len]);
apdu_len += len;
if (apdu_len > service_data->max_resp) {
/* too big for the sender - send an abort
* Setting of error code needed here as read property processing may
* have overriden the default set at start */
rpdata.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
/* too big for the sender - send an abort!
Setting of error code needed here as read property
processing may have overriden the default set at start */
rpdata.error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
len = BACNET_STATUS_ABORT;
#if PRINT_ENABLED
fprintf(stderr, "RP: Message too large.\n");
+18
View File
@@ -41,6 +41,9 @@
#include "bacnet/rpm.h"
/* basic objects, services, TSM, and datalink */
#include "bacnet/basic/object/device.h"
#if (BACNET_PROTOCOL_REVISION >= 17)
#include "bacnet/basic/object/netport.h"
#endif
#include "bacnet/basic/tsm/tsm.h"
#include "bacnet/basic/services.h"
#include "bacnet/datalink/datalink.h"
@@ -239,6 +242,21 @@ void handler_read_property_multiple(uint8_t *service_request,
(rpmdata.object_instance == BACNET_MAX_INSTANCE)) {
rpmdata.object_instance = Device_Object_Instance_Number();
}
#if (BACNET_PROTOCOL_REVISION >= 17)
/* When the object-type in the Object Identifier parameter
contains the value NETWORK_PORT and the instance in the
'Object Identifier' parameter contains the value 4194303,
the responding BACnet-user shall treat the Object Identifier
as if it correctly matched the local Network Port object
representing the network port through which the request was
received. This allows the network port instance of the
network port that was used to receive the request to be
determined. */
if ((rpmdata.object_type == OBJECT_NETWORK_PORT) &&
(rpmdata.object_instance == BACNET_MAX_INSTANCE)) {
rpmdata.object_instance = Network_Port_Index_To_Instance(0);
}
#endif
/* Stick this object id into the reply - if it will fit */
len = rpm_ack_encode_apdu_object_begin(&Temp_Buf[0], &rpmdata);