From f24c6147c6ab65d62e9f1c361df18e8bc2e80008 Mon Sep 17 00:00:00 2001 From: abelino Date: Fri, 4 Oct 2024 23:58:32 -0700 Subject: [PATCH] Add support for updating a routed multistate-input value --- lib/bacnet/gateway/object.ex | 23 +++++++++++++++++++++++ src/bacnet.c | 22 ++++++++++++++++++++++ src/protocol/decode_call.c | 29 ++++++++++++++++++++++++----- src/protocol/decode_call.h | 7 +++++++ 4 files changed, 76 insertions(+), 5 deletions(-) diff --git a/lib/bacnet/gateway/object.ex b/lib/bacnet/gateway/object.ex index e115989..71656db 100644 --- a/lib/bacnet/gateway/object.ex +++ b/lib/bacnet/gateway/object.ex @@ -79,4 +79,27 @@ defmodule BACNet.Gateway.Object do GenServer.call(pid, request) end + + @doc """ + Sets the present value of an existing multistate input object. + + ## Parameters + + - `pid`: The PID of the GenServer managing the BACnet communication. + - `device_id`: The ID of the BACnet device containing the object. + - `object_id`: The unique ID of the multistate input object to update. + - `value`: The new present value to be set for the multistate input. + """ + @spec set_multistate_input_present_value( + pid :: pid, + device_id :: integer, + object_id :: integer, + value :: non_neg_integer + ) :: :ok | {:error, term} + def set_multistate_input_present_value(pid, device_id, object_id, value) do + request = + {:set_routed_multistate_input_value, device_id, object_id, value} + + GenServer.call(pid, request) + end end diff --git a/src/bacnet.c b/src/bacnet.c index 22d5cf8..7853f30 100644 --- a/src/bacnet.c +++ b/src/bacnet.c @@ -34,12 +34,16 @@ handle_set_routed_analog_input_value(set_routed_analog_input_value_t* params); static int handle_create_routed_multistate_input(create_routed_multistate_input_t* params); +static int +handle_set_routed_multistate_value(set_routed_multistate_input_value_t* params); + static call_handler_t CALL_HANDLERS_BY_TYPE[] = { (call_handler_t)handle_create_gateway, (call_handler_t)handle_create_routed_device, (call_handler_t)handle_create_routed_analog_input, (call_handler_t)handle_set_routed_analog_input_value, (call_handler_t)handle_create_routed_multistate_input, + (call_handler_t)handle_set_routed_multistate_value, }; /** @@ -464,3 +468,21 @@ handle_create_routed_multistate_input(create_routed_multistate_input_t* params) return 0; } + +static int +handle_set_routed_multistate_value(set_routed_multistate_input_value_t* params) +{ + uint32_t device_index = + Routed_Device_Instance_To_Index(params->device_bacnet_id); + + Get_Routed_Device_Object(device_index); + + Routed_Multistate_Input_Present_Value_Set( + params->object_bacnet_id, + params->value + ); + + Get_Routed_Device_Object(0); + + return 0; +} diff --git a/src/protocol/decode_call.c b/src/protocol/decode_call.c index 1208173..332dd4f 100644 --- a/src/protocol/decode_call.c +++ b/src/protocol/decode_call.c @@ -5,11 +5,12 @@ #include "protocol/enum.h" const enum_tuple_t BACNET_CALL_ATOMS[] = { - {"create_gateway", 0}, - {"create_routed_device", 1}, - {"create_routed_analog_input", 2}, - {"set_routed_analog_input_value", 3}, - {"create_routed_multistate_input", 4}, + {"create_gateway", 0}, + {"create_routed_device", 1}, + {"create_routed_analog_input", 2}, + {"set_routed_analog_input_value", 3}, + {"create_routed_multistate_input", 4}, + {"set_routed_multistate_input_value", 5}, }; const size_t BACNET_CALL_SIZE_LOOKUP[] = { @@ -18,6 +19,7 @@ const size_t BACNET_CALL_SIZE_LOOKUP[] = { sizeof(create_routed_analog_input_t), sizeof(set_routed_analog_input_value_t), sizeof(create_routed_multistate_input_t), + sizeof(set_routed_multistate_input_value_t), }; static int decode_call_type(char* buffer, int* index, uint8_t* type); @@ -264,6 +266,20 @@ decode_create_routed_multistate_input( return is_invalid ? -1 : 0; } +static int +decode_set_routed_multistate_input_value( + char* buffer, + int* index, + set_routed_multistate_input_value_t* data) +{ + bool is_invalid = + ei_decode_ulong(buffer, index, (unsigned long*)&data->device_bacnet_id) + || ei_decode_ulong(buffer, index, (unsigned long*)&data->object_bacnet_id) + || ei_decode_ulong(buffer, index, (unsigned long*)&data->value); + + return is_invalid ? -1 : 0; +} + static int decode_call_data(char* buffer, int* index, bacnet_call_type_t type, void* data) { @@ -283,6 +299,9 @@ decode_call_data(char* buffer, int* index, bacnet_call_type_t type, void* data) case CALL_CREATE_ROUTED_MULTISTATE_INPUT: return decode_create_routed_multistate_input(buffer, index, data); + case CALL_SET_ROUTED_MULTISTATE_INPUT_VALUE: + return decode_set_routed_multistate_input_value(buffer, index, data); + default: return -1; } diff --git a/src/protocol/decode_call.h b/src/protocol/decode_call.h index bc1abe7..102e491 100644 --- a/src/protocol/decode_call.h +++ b/src/protocol/decode_call.h @@ -9,6 +9,7 @@ typedef enum { CALL_CREATE_ROUTED_ANALOG_INPUT, CALL_SET_ROUTED_ANALOG_INPUT_VALUE, CALL_CREATE_ROUTED_MULTISTATE_INPUT, + CALL_SET_ROUTED_MULTISTATE_INPUT_VALUE, CALL_UNKNOWN = 255, } __attribute__((packed)) bacnet_call_type_t; @@ -41,6 +42,12 @@ typedef struct { size_t states_length; } create_routed_multistate_input_t; +typedef struct { + uint32_t device_bacnet_id; + uint32_t object_bacnet_id; + uint8_t value; +} set_routed_multistate_input_value_t; + int bacnet_call_malloc(bacnet_call_type_t type, void** call); int decode_bacnet_call_type(char* buffer, int* index, bacnet_call_type_t* type);