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:
@@ -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 \
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,7 +67,8 @@ 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! */
|
||||
} 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,
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
/**----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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 (;;) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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,7 +67,8 @@ 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! */
|
||||
} 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,
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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 \
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,7 +59,8 @@ 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! */
|
||||
} 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,
|
||||
@@ -65,6 +69,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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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! */
|
||||
} 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.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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'">
|
||||
|
||||
@@ -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 }
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user