Add RGB pixel and brightness APIs, update Blinkt example (#1210)

* Added API to get the RGB pixel and brightness values from the blinkt interface.

* Fixed Channel object for Color object present-value which does not use coercion.

* Added API to the color-RGB library to convert from ASCII CSS color name to X,Y and brightness.

* Converted the Blinkt example app to use the basic-server.  Added a default color name command line option --color that accepts CSS color names. Set the color and brightness at startup.

* Added vacancy timer for lights using timer object defaulted to 30m and started at startup.
This commit is contained in:
Steve Karg
2026-01-27 07:34:32 -06:00
committed by GitHub
parent 4924a57ccc
commit 2b59aa1a99
8 changed files with 317 additions and 197 deletions
+7
View File
@@ -32,6 +32,11 @@ The git repositories are hosted at the following sites:
### Added
* Added API to get the RGB pixel and brightness values from the blinkt
interface. Added API to the color-RGB library to convert from ASCII
CSS color name to X,Y and brightness. Added a default color name command
line option. Set the color and brightness at startup. Changed the Blinkt
example app to use the basic-server framework. (#1210)
* Added enumeration text lookup for BACnetAuthenticationStatus,
BACnetAuthorizationMode, BACnetAccessCredentialDisable,
BACnetAccessCredentialDisableReason, BACnetAccessUserType,
@@ -108,6 +113,8 @@ The git repositories are hosted at the following sites:
### Fixed
* Fixed Channel object for Color object present-value which does not
use coercion. (#1210)
* Fixed lighting output object lighting-command last-on-value to only
be updated with the last value of the Present_Value property that
was greater than or equal to 1.0%, keeping in mind that the Present_Value
+38 -3
View File
@@ -1,6 +1,8 @@
###############################################################################
# Makefile for Project - BACnet Blinkt!
# sudo apt install libpigpio-dev libpigpiod-if-dev pigpiod
# note: start pigpio daemon with the command 'sudo pigpiod'
# note: Blinkt! pigpio library is not supported on Raspberry Pi 5 at this time
###############################################################################
## General Flags
@@ -8,13 +10,46 @@ TARGET = bacblinkt
# BACnet objects that are used with this app
BACNET_OBJECT_DIR = $(BACNET_SRC_DIR)/bacnet/basic/object
SRC = main.c blinkt.c device.c \
$(BACNET_OBJECT_DIR)/netport.c \
BACNET_SERVER_DIR = $(BACNET_SRC_DIR)/bacnet/basic/server
SRC = main.c blinkt.c \
$(BACNET_SERVER_DIR)/bacnet_basic.c \
$(BACNET_SERVER_DIR)/bacnet_device.c \
$(BACNET_SERVER_DIR)/bacnet_port.c \
$(BACNET_SERVER_DIR)/bacnet_port_ipv4.c \
$(BACNET_SERVER_DIR)/bacnet_port_ipv6.c \
$(BACNET_SERVER_DIR)/bacnet_port_mstp.c \
$(BACNET_OBJECT_DIR)/ai.c \
$(BACNET_OBJECT_DIR)/ao.c \
$(BACNET_OBJECT_DIR)/av.c \
$(BACNET_OBJECT_DIR)/auditlog.c \
$(BACNET_OBJECT_DIR)/bacfile.c \
$(BACNET_OBJECT_DIR)/bi.c \
$(BACNET_OBJECT_DIR)/bitstring_value.c \
$(BACNET_OBJECT_DIR)/blo.c \
$(BACNET_OBJECT_DIR)/bo.c \
$(BACNET_OBJECT_DIR)/bv.c \
$(BACNET_OBJECT_DIR)/calendar.c \
$(BACNET_OBJECT_DIR)/channel.c \
$(BACNET_OBJECT_DIR)/color_object.c \
$(BACNET_OBJECT_DIR)/color_temperature.c \
$(BACNET_OBJECT_DIR)/command.c \
$(BACNET_OBJECT_DIR)/csv.c \
$(BACNET_OBJECT_DIR)/iv.c \
$(BACNET_OBJECT_DIR)/lc.c \
$(BACNET_OBJECT_DIR)/lo.c
$(BACNET_OBJECT_DIR)/lo.c \
$(BACNET_OBJECT_DIR)/loop.c \
$(BACNET_OBJECT_DIR)/lsp.c \
$(BACNET_OBJECT_DIR)/lsz.c \
$(BACNET_OBJECT_DIR)/ms-input.c \
$(BACNET_OBJECT_DIR)/mso.c \
$(BACNET_OBJECT_DIR)/msv.c \
$(BACNET_OBJECT_DIR)/nc.c \
$(BACNET_OBJECT_DIR)/netport.c \
$(BACNET_OBJECT_DIR)/osv.c \
$(BACNET_OBJECT_DIR)/program.c \
$(BACNET_OBJECT_DIR)/structured_view.c \
$(BACNET_OBJECT_DIR)/timer.c \
$(BACNET_OBJECT_DIR)/time_value.c
CFLAGS += -DMAX_TSM_TRANSACTIONS=1
+37
View File
@@ -69,6 +69,29 @@ void blinkt_set_pixel(uint8_t led, uint8_t r, uint8_t g, uint8_t b)
Blinkt_LED[led] = blinkt_rgbb(r, g, b, Blinkt_LED[led] & 0x1F);
}
/**
* @brief Get the current RGB color of one LED
* @param led index 0..#BLINKT_NUM_LEDS
* @param r pointer to store the red component (0..255), may be NULL
* @param g pointer to store the green component (0..255), may be NULL
* @param b pointer to store the blue component (0..255), may be NULL
*/
void blinkt_get_pixel(uint8_t led, uint8_t *r, uint8_t *g, uint8_t *b)
{
if (led >= BLINKT_NUM_LEDS) {
return;
}
if (r) {
*r = (Blinkt_LED[led] >> 24) & 0xFF;
}
if (g) {
*g = (Blinkt_LED[led] >> 16) & 0xFF;
}
if (b) {
*b = (Blinkt_LED[led] >> 8) & 0xFF;
}
}
/**
* @brief Set one LED to specific intensity
* @param led index 0..#BLINKT_NUM_LEDS
@@ -83,6 +106,20 @@ void blinkt_set_pixel_brightness(uint8_t led, uint8_t brightness)
Blinkt_LED[led] = (Blinkt_LED[led] & 0xFFFFFF00) | (brightness & 0x1F);
}
/**
* @brief Get the brightness of one LED
* @param led index 0..#BLINKT_NUM_LEDS
* @return brightness intensity from 0..31, 0=OFF, 1=dimmest, 31=brightest
*/
uint8_t blinkt_get_pixel_brightness(uint8_t led)
{
if (led >= BLINKT_NUM_LEDS) {
return 0;
}
return Blinkt_LED[led] & 0x1F;
}
/**
* @brief Set one LED to RGB color and brightness
* @param led index 0..#BLINKT_NUM_LEDS
+5
View File
@@ -9,8 +9,13 @@
void blinkt_clear(void);
void blinkt_set_pixel_uint32(uint8_t led, uint32_t color);
void blinkt_set_pixel(uint8_t led, uint8_t r, uint8_t g, uint8_t b);
void blinkt_get_pixel(uint8_t led, uint8_t *r, uint8_t *g, uint8_t *b);
uint8_t blinkt_get_pixel_brightness(uint8_t led);
void blinkt_set_pixel_brightness(uint8_t led, uint8_t brightness);
uint32_t blinkt_rgbb(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness);
uint32_t blinkt_rgb(uint8_t r, uint8_t g, uint8_t b);
void blinkt_stop(void);
+192 -181
View File
@@ -14,104 +14,50 @@
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/bactext.h"
#include "bacnet/version.h"
#include "bacnet/bacdcode.h"
#include "bacnet/npdu.h"
#include "bacnet/apdu.h"
#include "bacnet/iam.h"
#include "bacnet/dcc.h"
#include "bacnet/getevent.h"
#include "bacnet/lighting.h"
/* demo services */
#include "bacnet/basic/binding/address.h"
#include "bacnet/basic/services.h"
#include "bacnet/basic/services.h"
#include "bacnet/datalink/dlenv.h"
#include "bacnet/basic/tsm/tsm.h"
#include "bacnet/datalink/datalink.h"
#include "bacnet/basic/sys/mstimer.h"
/* BACnet System API */
#include "bacnet/basic/sys/color_rgb.h"
#include "bacnet/basic/sys/debug.h"
#include "bacnet/basic/sys/filename.h"
#include "bacnet/basic/sys/linear.h"
#include "bacnet/basic/tsm/tsm.h"
#include "bacnet/version.h"
/* include the device object */
#include "bacnet/basic/sys/mstimer.h"
/* BACnet basic server & services API */
#include "bacnet/basic/server/bacnet_basic.h"
#include "bacnet/basic/server/bacnet_port.h"
#include "bacnet/basic/services.h"
/* BACnet basic datalink API */
#include "bacnet/datalink/dlenv.h"
#include "bacnet/datalink/datalink.h"
/* BACnet basic object */
#include "bacnet/basic/object/device.h"
#include "bacnet/basic/object/bacfile.h"
#include "bacnet/basic/object/lo.h"
#include "bacnet/basic/object/channel.h"
#include "bacnet/basic/object/color_object.h"
#include "bacnet/basic/object/color_temperature.h"
#include "bacnet/basic/object/timer.h"
/* local includes */
#include "bacport.h"
#include "blinkt.h"
/* (Doxygen note: The next two lines pull all the following Javadoc
* into the ServerDemo module.) */
/** @addtogroup ServerDemo */
/*@{*/
/** Buffer used for receiving */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
/* current version of the BACnet stack */
static const char *BACnet_Version = BACNET_VERSION_TEXT;
/* task timer for various BACnet timeouts */
static struct mstimer BACnet_Task_Timer;
/* task timer for TSM timeouts */
static struct mstimer BACnet_TSM_Timer;
/* task timer for address binding timeouts */
static struct mstimer BACnet_Address_Timer;
/* task timer for object functionality */
static struct mstimer BACnet_Object_Timer;
/* some device customization */
static const char *Device_Name = "Blinkt! Server";
static uint32_t Device_ID = 260001;
/* task timer for Blinkt! RGB LED display */
static struct mstimer Blinkt_Task;
/* flag to enable the Blinkt! test */
static bool Blinkt_Test = false;
/* observer for WriteGroup notifications */
static BACNET_WRITE_GROUP_NOTIFICATION Write_Group_Notification;
/** Initialize the handlers we will utilize.
* @see Device_Init, apdu_set_unconfirmed_handler, apdu_set_confirmed_handler
*/
static void Init_Service_Handlers(void)
{
Device_Init(NULL);
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_HAS, handler_who_has);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
/* set the handler for all the services we don't implement */
/* It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler(handler_unrecognized_service);
/* Set the handlers for any confirmed services that we support. */
/* We must implement read property - it's required! */
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_READ_PROPERTY, handler_read_property);
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_READ_PROP_MULTIPLE, handler_read_property_multiple);
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_WRITE_PROPERTY, handler_write_property);
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE, handler_write_property_multiple);
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_READ_RANGE, handler_read_range);
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_REINITIALIZE_DEVICE, handler_reinitialize_device);
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION, handler_timesync_utc);
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION, handler_timesync);
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_SUBSCRIBE_COV, handler_cov_subscribe);
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_WRITE_GROUP, handler_write_group);
/* handle communication so we can shutup when asked */
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
handler_device_communication_control);
/* configure the cyclic timers */
mstimer_set(&BACnet_Task_Timer, 1000UL);
mstimer_set(&BACnet_TSM_Timer, 50UL);
mstimer_set(&BACnet_Address_Timer, 60UL * 1000UL);
mstimer_set(&BACnet_Object_Timer, 100UL);
}
/* object instances */
static uint32_t Light_Channel_Instance = 1;
static uint32_t Color_Channel_Instance = 2;
static uint32_t CCT_Channel_Instance = 3;
static uint32_t Vacancy_Timer_Instance = 1;
static unsigned Default_Priority = 16;
/**
* Clean up the Blinkt! interface
*/
@@ -209,30 +155,63 @@ static void Color_Write_Value_Handler(
/**
* @brief Create the objects and configure the callbacks for BACnet objects
*/
static void bacnet_output_init(void)
static void BACnet_Object_Table_Init(void *context)
{
unsigned i = 0;
uint8_t led_max;
uint32_t object_instance = 0, member_element = 0;
uint32_t object_instance = 0, member_element = 0, device_instance = 0;
BACNET_COLOR_COMMAND command = { 0 };
BACNET_OBJECT_ID object_id;
uint32_t light_channel_instance = 1;
uint32_t color_channel_instance = 2;
uint32_t temp_channel_instance = 3;
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE member;
BACNET_OBJECT_ID object_id = { 0 };
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE member = { 0 };
BACNET_TIMER_STATE_CHANGE_VALUE timer_transition = { 0 };
Channel_Create(light_channel_instance);
Channel_Name_Set(light_channel_instance, "Lights");
Channel_Number_Set(light_channel_instance, 1);
Channel_Control_Groups_Element_Set(light_channel_instance, 1, 1);
Channel_Create(color_channel_instance);
Channel_Name_Set(color_channel_instance, "Colors");
Channel_Number_Set(color_channel_instance, 2);
Channel_Control_Groups_Element_Set(color_channel_instance, 1, 2);
Channel_Create(temp_channel_instance);
Channel_Name_Set(temp_channel_instance, "Color-Temperatures");
Channel_Number_Set(temp_channel_instance, 3);
Channel_Control_Groups_Element_Set(temp_channel_instance, 1, 3);
(void)context;
device_instance = Device_Object_Instance_Number();
/* create the objects */
Channel_Create(Light_Channel_Instance);
Channel_Name_Set(Light_Channel_Instance, "Lights");
Channel_Number_Set(Light_Channel_Instance, 1);
Channel_Control_Groups_Element_Set(Light_Channel_Instance, 1, 1);
Channel_Create(Color_Channel_Instance);
Channel_Name_Set(Color_Channel_Instance, "Colors");
Channel_Number_Set(Color_Channel_Instance, 2);
Channel_Control_Groups_Element_Set(Color_Channel_Instance, 1, 2);
Channel_Create(CCT_Channel_Instance);
Channel_Name_Set(CCT_Channel_Instance, "Color-Temperatures");
Channel_Number_Set(CCT_Channel_Instance, 3);
Channel_Control_Groups_Element_Set(CCT_Channel_Instance, 1, 3);
/* timer to automatically turn off the lights */
Timer_Create(Vacancy_Timer_Instance);
Timer_Name_Set(Vacancy_Timer_Instance, "Vacancy-Timer");
Timer_Default_Timeout_Set(Vacancy_Timer_Instance, 30UL * 60UL * 1000UL);
/* to running */
timer_transition.next = NULL;
timer_transition.tag = BACNET_APPLICATION_TAG_REAL;
timer_transition.type.Real = BACNET_LIGHTING_SPECIAL_VALUE_RESTORE_ON;
Timer_State_Change_Value_Set(
Vacancy_Timer_Instance, TIMER_TRANSITION_IDLE_TO_RUNNING,
&timer_transition);
Timer_State_Change_Value_Set(
Vacancy_Timer_Instance, TIMER_TRANSITION_RUNNING_TO_RUNNING,
&timer_transition);
Timer_State_Change_Value_Set(
Vacancy_Timer_Instance, TIMER_TRANSITION_EXPIRED_TO_RUNNING,
&timer_transition);
/* to expired */
timer_transition.next = NULL;
timer_transition.tag = BACNET_APPLICATION_TAG_REAL;
timer_transition.type.Real = BACNET_LIGHTING_SPECIAL_VALUE_WARN_RELINQUISH;
Timer_State_Change_Value_Set(
Vacancy_Timer_Instance, TIMER_TRANSITION_RUNNING_TO_EXPIRED,
&timer_transition);
member.objectIdentifier.type = OBJECT_CHANNEL;
member.objectIdentifier.instance = Light_Channel_Instance;
member.propertyIdentifier = PROP_PRESENT_VALUE;
member.arrayIndex = BACNET_ARRAY_ALL;
member.deviceIdentifier.type = OBJECT_DEVICE;
member.deviceIdentifier.instance = device_instance;
Timer_Reference_List_Member_Element_Add(Vacancy_Timer_Instance, &member);
Timer_Priority_For_Writing_Set(Vacancy_Timer_Instance, Default_Priority);
/* configure outputs and bindings */
led_max = blinkt_led_count();
for (i = 0; i < led_max; i++) {
@@ -255,9 +234,9 @@ static void bacnet_output_init(void)
member.propertyIdentifier = PROP_PRESENT_VALUE;
member.arrayIndex = BACNET_ARRAY_ALL;
member.deviceIdentifier.type = OBJECT_DEVICE;
member.deviceIdentifier.instance = Device_Object_Instance_Number();
member.deviceIdentifier.instance = device_instance;
Channel_Reference_List_Member_Element_Set(
color_channel_instance, member_element, &member);
Color_Channel_Instance, member_element, &member);
/* color temperature */
Color_Temperature_Create(object_instance);
@@ -273,9 +252,9 @@ static void bacnet_output_init(void)
member.propertyIdentifier = PROP_PRESENT_VALUE;
member.arrayIndex = BACNET_ARRAY_ALL;
member.deviceIdentifier.type = OBJECT_DEVICE;
member.deviceIdentifier.instance = Device_Object_Instance_Number();
member.deviceIdentifier.instance = device_instance;
Channel_Reference_List_Member_Element_Set(
temp_channel_instance, member_element, &member);
CCT_Channel_Instance, member_element, &member);
/* lighting output */
Lighting_Output_Create(object_instance);
@@ -291,10 +270,11 @@ static void bacnet_output_init(void)
member.propertyIdentifier = PROP_PRESENT_VALUE;
member.arrayIndex = BACNET_ARRAY_ALL;
member.deviceIdentifier.type = OBJECT_DEVICE;
member.deviceIdentifier.instance = Device_Object_Instance_Number();
member.deviceIdentifier.instance = device_instance;
Channel_Reference_List_Member_Element_Set(
light_channel_instance, member_element, &member);
Light_Channel_Instance, member_element, &member);
}
/* enable the callbacks for control */
Color_Write_Present_Value_Callback_Set(Color_Write_Value_Handler);
Color_Temperature_Write_Present_Value_Callback_Set(
Color_Temperature_Write_Value_Handler);
@@ -302,6 +282,59 @@ static void bacnet_output_init(void)
Lighting_Output_Write_Value_Handler);
Write_Group_Notification.callback = Channel_Write_Group;
handler_write_group_notification_add(&Write_Group_Notification);
/* LEDs run at 0.1s intervals */
bacnet_basic_task_object_timer_set(100);
mstimer_set(&Blinkt_Task, 100);
}
/**
* @brief BACnet object value initialization
* @param color_name - color name string
*/
static void BACnet_Object_Value_Init(const char *color_name)
{
BACNET_CHANNEL_VALUE value = { 0 };
float x_coordinate = 1.0f, y_coordinate = 1.0f;
uint8_t brightness = 0;
/* update the lighting-output and color-temperature */
if (color_rgb_xy_from_ascii(
&x_coordinate, &y_coordinate, &brightness, color_name)) {
printf(
"Initial color: %s x=%.2f y=%.2f brightness=%u/255\n", color_name,
x_coordinate, y_coordinate, (unsigned)brightness);
/* Set the Color */
value.tag = BACNET_APPLICATION_TAG_XY_COLOR;
value.type.XY_Color.x_coordinate = x_coordinate;
value.type.XY_Color.y_coordinate = y_coordinate;
Channel_Present_Value_Set(Color_Channel_Instance, 16, &value);
/* Set the Brightness */
value.tag = BACNET_APPLICATION_TAG_REAL;
value.type.Real =
linear_interpolate(0.0f, brightness, 255.0f, 0.0f, 100.0f);
Channel_Present_Value_Set(
Light_Channel_Instance, Default_Priority, &value);
/* start the vacancy timer */
Timer_Running_Set(Vacancy_Timer_Instance, true);
} else {
printf("Initial color: %s unknown\n", color_name);
}
}
static void BACnet_Object_Task(void *context)
{
(void)context;
/* input/process/output */
if (Blinkt_Test) {
blinkt_test_task();
}
if (mstimer_expired(&Blinkt_Task)) {
mstimer_restart(&Blinkt_Task);
/* run at the same interval as the BACnet basic objects */
if (!Blinkt_Test) {
blinkt_show();
}
}
}
/**
@@ -329,6 +362,10 @@ static void print_help(const char *filename)
"try and bind with this device using Who-Is and\n"
"I-Am services.\n");
printf("\n");
printf(
"--color:\n"
"Default CSS color name from W3C, such as black, red, green, etc.\n");
printf("\n");
printf("--test:\n"
"Test the Blinkt! RGB LEDs with a cycling pattern.\n");
printf("\n");
@@ -339,29 +376,17 @@ static void print_help(const char *filename)
}
/** Main function of server demo.
*
* @see Device_Set_Object_Instance_Number, dlenv_init, Send_I_Am,
* datalink_receive, npdu_handler,
* dcc_timer_seconds, datalink_maintenance_timer,
* handler_cov_task,
* tsm_timer_milliseconds
*
* @param argc [in] Arg count.
* @param argv [in] Takes one argument: the Device Instance #.
* @param argv [in] Argument list.
* @return 0 on success.
*/
int main(int argc, char *argv[])
{
BACNET_ADDRESS src = { 0 }; /* address where message came from */
uint16_t pdu_len = 0;
unsigned timeout_ms = 1;
unsigned long seconds = 0;
unsigned long milliseconds;
bool blinkt_test = false;
unsigned int target_args = 0;
uint32_t device_id = BACNET_MAX_INSTANCE;
int argi = 0;
const char *filename = NULL;
const char *color_name = "darkred";
filename = filename_remove_path(argv[0]);
for (argi = 1; argi < argc; argi++) {
@@ -380,92 +405,78 @@ int main(int argc, char *argv[])
return 0;
}
if (strcmp(argv[argi], "--device") == 0) {
/* allow the device ID to be set */
if (++argi < argc) {
if (!bacnet_string_to_uint32(argv[argi], &device_id)) {
fprintf(stderr, "device-instance=%s invalid\n", argv[argi]);
return 1;
}
if (device_id > BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%s invalid\n", argv[argi]);
return 1;
} else {
Device_ID = device_id;
}
}
} else if (strcmp(argv[argi], "--test") == 0) {
blinkt_test = true;
/* test the hardware */
Blinkt_Test = true;
} else if (strcmp(argv[argi], "--color") == 0) {
/* initial color */
if (++argi < argc) {
color_name = argv[argi];
} else {
fprintf(stderr, "Missing color name after --color\n");
print_usage(filename);
return 1;
}
} else {
if (target_args == 0) {
/* allow the device ID to be set */
if (!bacnet_string_to_uint32(argv[argi], &device_id)) {
fprintf(stderr, "device-instance=%s invalid\n", argv[argi]);
return 1;
}
if (device_id > BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%s invalid\n", argv[argi]);
return 1;
} else {
Device_ID = device_id;
}
target_args++;
} else if (target_args == 1) {
/* allow the device name to be set */
Device_Name = argv[argi];
target_args++;
}
}
}
if (device_id > BACNET_MAX_INSTANCE) {
fprintf(
stderr, "device=%u - not greater than %u\n", device_id,
BACNET_MAX_INSTANCE);
return 1;
}
Device_Set_Object_Instance_Number(device_id);
Device_Set_Object_Instance_Number(Device_ID);
Device_Object_Name_ANSI_Init(Device_Name);
printf(
"BACnet Raspberry Pi Blinkt! Demo\n"
"BACnet Raspberry Pi Blinkt! Demo %s\n"
"BACnet Stack Version %s\n"
"BACnet Device ID: %u\n"
"Max APDU: %d\n",
BACnet_Version, Device_Object_Instance_Number(), MAX_APDU);
/* load any static address bindings to show up
in our device bindings list */
address_init();
Init_Service_Handlers();
dlenv_init();
atexit(datalink_cleanup);
Device_Application_Software_Version(), Device_Firmware_Revision(),
Device_Object_Instance_Number(), MAX_APDU);
blinkt_init();
atexit(blinkt_cleanup);
bacnet_output_init();
/* configure the timeout values */
/* broadcast an I-Am on startup */
Send_I_Am(&Handler_Transmit_Buffer[0]);
/* loop forever */
debug_printf_stdout("Blinkt! initialized\n");
bacnet_basic_init_callback_set(BACnet_Object_Table_Init, NULL);
bacnet_basic_task_callback_set(BACnet_Object_Task, NULL);
bacnet_basic_init();
if (bacnet_port_init()) {
/* OS based apps use DLENV for environment variables */
dlenv_init();
atexit(datalink_cleanup);
}
debug_printf_stdout("Server: BACnet initialized\n");
BACnet_Object_Value_Init(color_name);
for (;;) {
/* input */
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout_ms);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
if (mstimer_expired(&BACnet_Task_Timer)) {
mstimer_reset(&BACnet_Task_Timer);
/* 1 second tasks */
dcc_timer_seconds(1);
datalink_maintenance_timer(1);
dlenv_maintenance_timer(1);
handler_cov_timer_seconds(1);
}
if (mstimer_expired(&BACnet_TSM_Timer)) {
mstimer_reset(&BACnet_TSM_Timer);
tsm_timer_milliseconds(mstimer_interval(&BACnet_TSM_Timer));
}
handler_cov_task();
if (mstimer_expired(&BACnet_Address_Timer)) {
mstimer_reset(&BACnet_Address_Timer);
/* address cache */
seconds = mstimer_interval(&BACnet_Address_Timer) / 1000;
address_cache_timer(seconds);
}
/* output/input */
if (blinkt_test) {
blinkt_test_task();
} else {
if (mstimer_expired(&BACnet_Object_Timer)) {
mstimer_reset(&BACnet_Object_Timer);
milliseconds = mstimer_interval(&BACnet_Object_Timer);
Device_Timer(milliseconds);
blinkt_show();
}
}
bacnet_basic_task();
bacnet_port_task();
}
return 0;
}
/* @} */
/* End group ServerDemo */
+4 -13
View File
@@ -662,18 +662,6 @@ bool Channel_Write_Member_Value(
wp_data->application_data_len = apdu_len;
status = true;
}
} else if (
(wp_data->object_type == OBJECT_COLOR) &&
((wp_data->object_property == PROP_PRESENT_VALUE) ||
(wp_data->object_property == PROP_DEFAULT_COLOR)) &&
(wp_data->array_index == BACNET_ARRAY_ALL)) {
apdu_len = bacnet_channel_value_coerce_data_encode(
wp_data->application_data, wp_data->application_data_len, value,
BACNET_APPLICATION_TAG_XY_COLOR);
if (apdu_len != BACNET_STATUS_ERROR) {
wp_data->application_data_len = apdu_len;
status = true;
}
} else if (
(wp_data->object_type == OBJECT_COLOR_TEMPERATURE) &&
((wp_data->object_property == PROP_PRESENT_VALUE) ||
@@ -761,8 +749,11 @@ static bool Channel_Write_Members(
}
debug_printf(
"channel[%lu].Channel_Write_Member[%u] "
"%s\n",
"%s-%u %s %s\n",
(unsigned long)object_instance, m,
bactext_object_type_name(wp_data.object_type),
wp_data.object_instance,
bactext_property_name(wp_data.object_property),
bactext_error_code_name(wp_data.error_code));
}
} else {
+27
View File
@@ -490,6 +490,33 @@ unsigned color_rgb_from_ascii(
return index;
}
/**
* @brief Convert CSS color name to CIE xy coordinates and brightness
* @param x_coordinate - return x of CIE xy 0.0..1.0
* @param y_coordinate - return y of CIE xy 0.0..1.0
* @param brightness - return brightness of the CIE xy color 0..255
* @param name - CSS color name from W3C
* @return true if color name was found, false if not found
*/
bool color_rgb_xy_from_ascii(
float *x_coordinate,
float *y_coordinate,
uint8_t *brightness,
const char *name)
{
bool status = false;
uint8_t r = 0, g = 0, b = 0;
unsigned index;
index = color_rgb_from_ascii(&r, &g, &b, name);
if (index < color_rgb_count()) {
color_rgb_to_xy(r, g, b, x_coordinate, y_coordinate, brightness);
status = true;
}
return status;
}
/**
* @brief Convert sRGB from CIE xy and brightness
* @param red - return R value of sRGB
+7
View File
@@ -59,6 +59,13 @@ BACNET_STACK_EXPORT
unsigned color_rgb_from_ascii(
uint8_t *red, uint8_t *green, uint8_t *blue, const char *name);
BACNET_STACK_EXPORT
bool color_rgb_xy_from_ascii(
float *x_coordinate,
float *y_coordinate,
uint8_t *brightness,
const char *name);
BACNET_STACK_EXPORT
const char *color_rgb_from_index(
unsigned target_index, uint8_t *red, uint8_t *green, uint8_t *blue);
BACNET_STACK_EXPORT