Cosmetic changes to comments.
Print on output every change of Event_State for analog-value objects. Added write_property_function for analog-input objects. Created descriptor for analog-input objects. Possible to write Present_Value for analog-inputs when Out_Of_Service is true.
This commit is contained in:
@@ -97,7 +97,7 @@ void handler_write_property_multiple(
|
||||
decode_len = 0;
|
||||
do
|
||||
{
|
||||
/* decode Object Identifier
|
||||
/* decode Object Identifier */
|
||||
len = wpm_decode_object_id(&service_request[decode_len],
|
||||
service_len - decode_len, &wp_data);
|
||||
if (len > 0)
|
||||
@@ -105,13 +105,13 @@ void handler_write_property_multiple(
|
||||
uint8_t tag_number = 0;
|
||||
|
||||
decode_len += len;
|
||||
decode_len += len;
|
||||
/* Opening tag 1 - List of Properties */
|
||||
if (decode_is_opening_tag_number(&service_request[decode_len++], 1))
|
||||
{
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
/* decode a 'Property Identifier'; (3) an optional 'Property Array Index' */
|
||||
/* (4) a 'Property Value'; and (5) an optional 'Priority'. */
|
||||
len = wpm_decode_object_property(&service_request[decode_len],
|
||||
service_len - decode_len, &wp_data);
|
||||
if (len > 0)
|
||||
@@ -120,7 +120,7 @@ void handler_write_property_multiple(
|
||||
if (Device_Write_Property(&wp_data) == false)
|
||||
{
|
||||
error = true;
|
||||
decode_len += len;
|
||||
break; /* do while (decoding List of Properties) */
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -131,23 +131,23 @@ void handler_write_property_multiple(
|
||||
wp_data.error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data.error_code = ERROR_CODE_OTHER;
|
||||
error = true;
|
||||
fprintf(stderr, "Bad Encoding!\n");
|
||||
break; /* do while (decoding List of Properties) */
|
||||
}
|
||||
|
||||
wp_data.error_code = ERROR_CODE_OTHER;
|
||||
/* Closing tag 1 - List of Properties */
|
||||
if (decode_is_closing_tag_number(&service_request[decode_len], 1))
|
||||
{
|
||||
tag_number = 1;
|
||||
decode_len++;
|
||||
}
|
||||
else
|
||||
*/
|
||||
tag_number = 0; /* it was not tag 1, decode next Property Identifier ... */
|
||||
|
||||
}
|
||||
tag_number = 1;
|
||||
while(tag_number != 1); /* end decoding List of Properties for "that" object */
|
||||
|
||||
if (error)
|
||||
else
|
||||
break; /*do while (decode service request) */
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -158,7 +158,7 @@ void handler_write_property_multiple(
|
||||
wp_data.error_class = ERROR_CLASS_OBJECT;
|
||||
wp_data.error_code = ERROR_CODE_OTHER;
|
||||
error = true;
|
||||
}
|
||||
break; /*do while (decode service request) */
|
||||
}
|
||||
}
|
||||
while(decode_len < service_len);
|
||||
|
||||
+369
-12
@@ -1,6 +1,7 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
|
||||
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
@@ -28,17 +29,22 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacenum.h"
|
||||
#include "config.h" /* the custom stuff */
|
||||
#include "handlers.h"
|
||||
#include "timestamp.h"
|
||||
#include "ai.h"
|
||||
|
||||
|
||||
#ifndef MAX_ANALOG_INPUTS
|
||||
#define MAX_ANALOG_INPUTS 4
|
||||
#endif
|
||||
|
||||
static float Present_Value[MAX_ANALOG_INPUTS];
|
||||
|
||||
ANALOG_INPUT_DESCR AI_Descr[MAX_ANALOG_INPUTS];
|
||||
|
||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||
static const int Properties_Required[] = {
|
||||
@@ -55,6 +61,18 @@ static const int Properties_Required[] = {
|
||||
|
||||
static const int Properties_Optional[] = {
|
||||
PROP_DESCRIPTION,
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
PROP_TIME_DELAY,
|
||||
PROP_NOTIFICATION_CLASS,
|
||||
PROP_HIGH_LIMIT,
|
||||
PROP_LOW_LIMIT,
|
||||
PROP_DEADBAND,
|
||||
PROP_LIMIT_ENABLE,
|
||||
PROP_EVENT_ENABLE,
|
||||
PROP_ACKED_TRANSITIONS,
|
||||
PROP_NOTIFY_TYPE,
|
||||
PROP_EVENT_TIME_STAMPS,
|
||||
#endif
|
||||
-1
|
||||
};
|
||||
|
||||
@@ -80,6 +98,29 @@ void Analog_Input_Property_Lists(
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void Analog_Input_Init(
|
||||
void)
|
||||
{
|
||||
unsigned i, j;
|
||||
|
||||
for (i = 0; i < MAX_ANALOG_INPUTS; i++) {
|
||||
AI_Descr[i].Present_Value = 0.0f;
|
||||
AI_Descr[i].Out_Of_Service = false;
|
||||
AI_Descr[i].Units = UNITS_PERCENT;
|
||||
AI_Descr[i].Reliability = RELIABILITY_NO_FAULT_DETECTED;
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
AI_Descr[i].Event_State = EVENT_STATE_NORMAL;
|
||||
/* notification class not connected */
|
||||
AI_Descr[i].Notification_Class = BACNET_MAX_INSTANCE;
|
||||
/* initialize Event time stamps using wildcards */
|
||||
for (j = 0; j < MAX_BACNET_EVENT_TRANSITION; j++) {
|
||||
datetime_wildcard_set(&AI_Descr[i].Event_Time_Stamps[j]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
@@ -134,7 +175,7 @@ float Analog_Input_Present_Value(
|
||||
|
||||
index = Analog_Input_Instance_To_Index(object_instance);
|
||||
if (index < MAX_ANALOG_INPUTS) {
|
||||
value = Present_Value[index];
|
||||
value = AI_Descr[index].Present_Value;
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -148,7 +189,7 @@ void Analog_Input_Present_Value_Set(
|
||||
|
||||
index = Analog_Input_Instance_To_Index(object_instance);
|
||||
if (index < MAX_ANALOG_INPUTS) {
|
||||
Present_Value[index] = value;
|
||||
AI_Descr[index].Present_Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,15 +215,26 @@ bool Analog_Input_Object_Name(
|
||||
int Analog_Input_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
{
|
||||
int len = 0;
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
ANALOG_INPUT_DESCR *CurrentAI;
|
||||
unsigned object_index = 0;
|
||||
unsigned i = 0;
|
||||
uint8_t *apdu = NULL;
|
||||
|
||||
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
|
||||
(rpdata->application_data_len == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
object_index = Analog_Input_Instance_To_Index(rpdata->object_instance);
|
||||
if (object_index < MAX_ANALOG_INPUTS)
|
||||
CurrentAI = &AI_Descr[object_index];
|
||||
else
|
||||
return BACNET_STATUS_ERROR;
|
||||
|
||||
apdu = rpdata->application_data;
|
||||
switch ((int) rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
@@ -190,39 +242,168 @@ int Analog_Input_Read_Property(
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
|
||||
rpdata->object_instance);
|
||||
break;
|
||||
|
||||
case PROP_OBJECT_NAME:
|
||||
case PROP_DESCRIPTION:
|
||||
Analog_Input_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_ANALOG_INPUT);
|
||||
break;
|
||||
|
||||
case PROP_PRESENT_VALUE:
|
||||
apdu_len =
|
||||
encode_application_real(&apdu[0],
|
||||
Analog_Input_Present_Value(rpdata->object_instance));
|
||||
break;
|
||||
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM,
|
||||
CurrentAI->Event_State ? true : false);
|
||||
#else
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
||||
#endif
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, CurrentAI->Out_Of_Service);
|
||||
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
|
||||
case PROP_EVENT_STATE:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
apdu_len = encode_application_enumerated(&apdu[0],
|
||||
CurrentAI->Event_State);
|
||||
#else
|
||||
apdu_len = encode_application_enumerated(&apdu[0],
|
||||
EVENT_STATE_NORMAL);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PROP_RELIABILITY:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], CurrentAI->Reliability);
|
||||
break;
|
||||
|
||||
case PROP_OUT_OF_SERVICE:
|
||||
apdu_len = encode_application_boolean(&apdu[0], false);
|
||||
apdu_len = encode_application_boolean(&apdu[0], CurrentAI->Out_Of_Service);
|
||||
break;
|
||||
|
||||
case PROP_UNITS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
|
||||
apdu_len = encode_application_enumerated(&apdu[0], CurrentAI->Units);
|
||||
break;
|
||||
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
case PROP_TIME_DELAY:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], CurrentAI->Time_Delay);
|
||||
break;
|
||||
|
||||
case PROP_NOTIFICATION_CLASS:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], CurrentAI->Notification_Class);
|
||||
break;
|
||||
|
||||
case PROP_HIGH_LIMIT:
|
||||
apdu_len = encode_application_real(&apdu[0], CurrentAI->High_Limit);
|
||||
break;
|
||||
|
||||
case PROP_LOW_LIMIT:
|
||||
apdu_len = encode_application_real(&apdu[0], CurrentAI->Low_Limit);
|
||||
break;
|
||||
|
||||
case PROP_DEADBAND:
|
||||
apdu_len = encode_application_real(&apdu[0], CurrentAI->Deadband);
|
||||
break;
|
||||
|
||||
case PROP_LIMIT_ENABLE:
|
||||
bitstring_init(&bit_string);
|
||||
bitstring_set_bit(&bit_string, 0,
|
||||
(CurrentAI->Limit_Enable & EVENT_LOW_LIMIT_ENABLE ) ? true : false );
|
||||
bitstring_set_bit(&bit_string, 1,
|
||||
(CurrentAI->Limit_Enable & EVENT_HIGH_LIMIT_ENABLE) ? true : false );
|
||||
|
||||
apdu_len = encode_application_bitstring(&apdu[0],&bit_string);
|
||||
break;
|
||||
|
||||
case PROP_EVENT_ENABLE:
|
||||
bitstring_init(&bit_string);
|
||||
bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL,
|
||||
(CurrentAI->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) ? true : false );
|
||||
bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT,
|
||||
(CurrentAI->Event_Enable & EVENT_ENABLE_TO_FAULT ) ? true : false );
|
||||
bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL,
|
||||
(CurrentAI->Event_Enable & EVENT_ENABLE_TO_NORMAL ) ? true : false );
|
||||
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
|
||||
case PROP_ACKED_TRANSITIONS:
|
||||
bitstring_init(&bit_string);
|
||||
bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL, true);
|
||||
bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT, true);
|
||||
bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL, true);
|
||||
|
||||
/* Fixme: finish it */
|
||||
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
|
||||
case PROP_NOTIFY_TYPE:
|
||||
apdu_len = encode_application_enumerated(&apdu[0],
|
||||
CurrentAI->Notify_Type ? NOTIFY_EVENT : NOTIFY_ALARM);
|
||||
break;
|
||||
|
||||
case PROP_EVENT_TIME_STAMPS:
|
||||
/* Array element zero is the number of elements in the array */
|
||||
if (rpdata->array_index == 0)
|
||||
apdu_len = encode_application_unsigned(&apdu[0],
|
||||
MAX_BACNET_EVENT_TRANSITION);
|
||||
/* if no index was specified, then try to encode the entire list */
|
||||
/* into one packet. */
|
||||
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
|
||||
for (i = 0; i < MAX_BACNET_EVENT_TRANSITION; i++) {;
|
||||
len = encode_opening_tag(&apdu[apdu_len],
|
||||
TIME_STAMP_DATETIME);
|
||||
len += encode_application_date(&apdu[apdu_len + len],
|
||||
&CurrentAI->Event_Time_Stamps[i].date);
|
||||
len += encode_application_time(&apdu[apdu_len + len],
|
||||
&CurrentAI->Event_Time_Stamps[i].time);
|
||||
len += encode_closing_tag(&apdu[apdu_len + len],
|
||||
TIME_STAMP_DATETIME);
|
||||
|
||||
/* add it if we have room */
|
||||
if ((apdu_len + len) < MAX_APDU)
|
||||
apdu_len += len;
|
||||
else {
|
||||
rpdata->error_class = ERROR_CLASS_SERVICES;
|
||||
rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rpdata->array_index <= MAX_BACNET_EVENT_TRANSITION) {
|
||||
apdu_len = encode_opening_tag(&apdu[apdu_len],
|
||||
TIME_STAMP_DATETIME);
|
||||
apdu_len += encode_application_date(&apdu[apdu_len],
|
||||
&CurrentAI->Event_Time_Stamps[rpdata->array_index].date);
|
||||
apdu_len += encode_application_time(&apdu[apdu_len],
|
||||
&CurrentAI->Event_Time_Stamps[rpdata->array_index].time);
|
||||
apdu_len += encode_closing_tag(&apdu[apdu_len],
|
||||
TIME_STAMP_DATETIME);
|
||||
}
|
||||
else {
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 9997:
|
||||
/* test case for real encoding-decoding unsigned value correctly */
|
||||
apdu_len = encode_application_real(&apdu[0], 90.510F);
|
||||
@@ -242,20 +423,196 @@ int Analog_Input_Read_Property(
|
||||
break;
|
||||
}
|
||||
/* only array properties can have array options */
|
||||
if ((apdu_len >= 0) && (rpdata->array_index != BACNET_ARRAY_ALL)) {
|
||||
if ((apdu_len >= 0) &&
|
||||
(rpdata->object_property != PROP_EVENT_TIME_STAMPS) &&
|
||||
(rpdata->array_index != BACNET_ARRAY_ALL)) {
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
||||
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
void Analog_Input_Init(
|
||||
void)
|
||||
/* returns true if successful */
|
||||
bool Analog_Input_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
ANALOG_INPUT_DESCR *CurrentAI;
|
||||
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
/* FIXME: len < application_data_len: more data? */
|
||||
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;
|
||||
}
|
||||
|
||||
object_index = Analog_Input_Instance_To_Index(wp_data->object_instance);
|
||||
if (object_index < MAX_ANALOG_INPUTS)
|
||||
CurrentAI = &AI_Descr[object_index];
|
||||
else
|
||||
return false;
|
||||
|
||||
switch (wp_data->object_property) {
|
||||
case PROP_PRESENT_VALUE:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_REAL,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
|
||||
if (status) {
|
||||
if (CurrentAI->Out_Of_Service == true) {
|
||||
Analog_Input_Present_Value_Set(wp_data->object_instance,
|
||||
value.type.Real);
|
||||
}
|
||||
else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_OUT_OF_SERVICE:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
if (status) {
|
||||
CurrentAI->Out_Of_Service = value.type.Boolean;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_UNITS:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
if (status) {
|
||||
CurrentAI->Units = value.type.Enumerated;
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
case PROP_TIME_DELAY:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
|
||||
if (status) {
|
||||
CurrentAI->Time_Delay = value.type.Unsigned_Int;
|
||||
CurrentAI->Remaining_Time_Delay = CurrentAI->Time_Delay;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_NOTIFICATION_CLASS:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
|
||||
if (status) {
|
||||
CurrentAI->Notification_Class = value.type.Unsigned_Int;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_HIGH_LIMIT:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_REAL,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
|
||||
if (status) {
|
||||
CurrentAI->High_Limit = value.type.Real;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_LOW_LIMIT:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_REAL,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
|
||||
if (status) {
|
||||
CurrentAI->Low_Limit = value.type.Real;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_DEADBAND:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_REAL,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
|
||||
if (status) {
|
||||
CurrentAI->Deadband = value.type.Real;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_LIMIT_ENABLE:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BIT_STRING,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
|
||||
if (status) {
|
||||
if(value.type.Bit_String.bits_used == 2) {
|
||||
CurrentAI->Limit_Enable = value.type.Bit_String.value[0];
|
||||
}
|
||||
else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_EVENT_ENABLE:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BIT_STRING,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
|
||||
if (status) {
|
||||
if(value.type.Bit_String.bits_used == 3) {
|
||||
CurrentAI->Event_Enable = value.type.Bit_String.value[0];
|
||||
}
|
||||
else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_NOTIFY_TYPE:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
|
||||
if (status) {
|
||||
if(value.type.Bit_String.bits_used > NOTIFY_EVENT) {
|
||||
CurrentAI->Event_Enable = value.type.Enumerated;
|
||||
}
|
||||
else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
|
||||
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
@@ -34,6 +35,32 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct analog_input_descr {
|
||||
uint8_t Event_State : 3;
|
||||
float Present_Value;
|
||||
BACNET_RELIABILITY Reliability;
|
||||
bool Out_Of_Service;
|
||||
uint8_t Units;
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
uint32_t Time_Delay;
|
||||
uint32_t Notification_Class;
|
||||
float High_Limit;
|
||||
float Low_Limit;
|
||||
float Deadband;
|
||||
uint8_t Limit_Enable : 2;
|
||||
uint8_t Event_Enable : 3;
|
||||
uint8_t Acked_Transitions : 3;
|
||||
uint8_t Notify_Type : 1;
|
||||
BACNET_DATE_TIME Event_Time_Stamps[MAX_BACNET_EVENT_TRANSITION];
|
||||
/* time to generate event notification */
|
||||
uint32_t Remaining_Time_Delay;
|
||||
#endif
|
||||
} ANALOG_INPUT_DESCR;
|
||||
|
||||
|
||||
|
||||
|
||||
void Analog_Input_Property_Lists(
|
||||
const int **pRequired,
|
||||
const int **pOptional,
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "bacdcode.h"
|
||||
#include "bacenum.h"
|
||||
#include "bacapp.h"
|
||||
#include "bactext.h"
|
||||
#include "config.h" /* the custom stuff */
|
||||
#include "wp.h"
|
||||
#include "rp.h"
|
||||
@@ -435,7 +436,7 @@ int Analog_Value_Read_Property(
|
||||
bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT, true);
|
||||
bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL, true);
|
||||
|
||||
/*/ Fixme: finish it */
|
||||
/* Fixme: finish it */
|
||||
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
@@ -877,6 +878,12 @@ void Analog_Value_Intrinsic_Reporting(uint32_t object_instance)
|
||||
break;
|
||||
} /* switch (ToState) */
|
||||
|
||||
#if defined(PRINT_ENABLED)
|
||||
fprintf(stderr, "Event_State for (Analog-Value,%d) goes from %s to %s.\n",
|
||||
object_instance, bactext_event_state_name(FromState),
|
||||
bactext_event_state_name(ToState));
|
||||
|
||||
#endif /* defined(PRINT_ENABLED) */
|
||||
|
||||
/* Event Object Identifier */
|
||||
event_data.eventObjectIdentifier.type = OBJECT_ANALOG_VALUE;
|
||||
|
||||
@@ -92,7 +92,7 @@ static object_functions_t Object_Table[] = {
|
||||
OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
|
||||
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
|
||||
Analog_Input_Object_Name, Analog_Input_Read_Property,
|
||||
NULL, Analog_Input_Property_Lists,
|
||||
Analog_Input_Write_Property, Analog_Input_Property_Lists,
|
||||
NULL, NULL, NULL, NULL}, {
|
||||
OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count,
|
||||
Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance,
|
||||
@@ -1485,7 +1485,7 @@ bool Device_Encode_Value_List(
|
||||
}
|
||||
|
||||
|
||||
void Device_local_reporting(uint32_t milliseconds)
|
||||
void Device_local_reporting(void)
|
||||
{
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
struct object_functions *pObject;
|
||||
|
||||
@@ -337,7 +337,7 @@ extern "C" {
|
||||
bool Device_Write_Property_Local(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data);
|
||||
|
||||
void Device_local_reporting(uint32_t milliseconds);
|
||||
void Device_local_reporting(void);
|
||||
|
||||
/* Prototypes for Routing functionality in the Device Object.
|
||||
* Enable by defining BAC_ROUTING in config.h and including gw_device.c
|
||||
|
||||
+861
-889
File diff suppressed because it is too large
Load Diff
@@ -121,4 +121,4 @@ typedef struct Notification_Class_info {
|
||||
Notification_Class_Write_Property, Notification_Class_Property_Lists, \
|
||||
NULL, NULL, NULL
|
||||
|
||||
#endif /* NC_H
|
||||
#endif /* NC_H */
|
||||
|
||||
@@ -206,7 +206,7 @@ int main(
|
||||
tsm_timer_milliseconds(elapsed_milliseconds);
|
||||
trend_log_timer(elapsed_seconds);
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
Device_local_reporting(elapsed_seconds * 1000);
|
||||
Device_local_reporting();
|
||||
#endif
|
||||
}
|
||||
/* scan cache address */
|
||||
|
||||
Reference in New Issue
Block a user