Skip to content

Commit a3f7496

Browse files
committed
[WIP] improving shell to get/set values
1 parent 89bfd87 commit a3f7496

File tree

3 files changed

+133
-4
lines changed

3 files changed

+133
-4
lines changed

west.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ manifest:
4141
revision: master
4242
- name: zephyr
4343
path: zephyr
44-
revision: v3.7.0
44+
revision: v3.7.1
4545
remote: zephyrproject-rtos
4646
west-commands: scripts/west-commands.yml
4747
import:

zephyr/samples/profiles/b-ld/sample.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ sample:
44
common:
55
platform_allow:
66
- nucleo_f429zi
7+
- rpi_pico
8+
- adafruit_grand_central_m4_express
79
build_only: true
810

911
tests:

zephyr/subsys/bacnet_settings/bacnet_shell.c

Lines changed: 130 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <zephyr/shell/shell.h>
1212
#include <bacnet_settings/bacnet_storage.h>
1313
#include <bacnet/bactext.h>
14+
#include <bacnet/proplist.h>
1415
#include <bacnet/wp.h>
1516

1617
static const char Storage_Base_Name[] = CONFIG_BACNET_STORAGE_BASE_NAME;
@@ -29,6 +30,7 @@ static int cmd_key(BACNET_STORAGE_KEY *key, const struct shell *sh, size_t argc,
2930
uint32_t property_id = 77;
3031
uint32_t array_index = BACNET_STORAGE_ARRAY_INDEX_NONE;
3132
long value = 0;
33+
unsigned long unsigned_value = 0;
3234
int found_index = 0;
3335

3436
if (argc < 3) {
@@ -46,12 +48,31 @@ static int cmd_key(BACNET_STORAGE_KEY *key, const struct shell *sh, size_t argc,
4648
return -EINVAL;
4749
}
4850
object_type = (uint16_t)value;
49-
value = strtoul(argv[2], NULL, 0);
50-
if (value > 4194303) {
51+
if (!bacnet_storage_strtoul(argv[2], &unsigned_value)) {
52+
shell_error(sh, "Invalid object-instance: %s.", argv[2]);
53+
return -EINVAL;
54+
}
55+
if (unsigned_value > 4194303) {
5156
shell_error(sh, "Invalid object-instance: %s. Must be 0-4194303.", argv[2]);
5257
return -EINVAL;
5358
}
54-
object_instance = (uint32_t)value;
59+
object_instance = (uint32_t)unsigned_value;
60+
/* property can have @ to denote priority or array */
61+
char *at_ptr = strchr(argv[3], '@');
62+
if (at_ptr) {
63+
if (!bacnet_storage_strtoul(at_ptr + 1, &unsigned_value)) {
64+
shell_error(sh, "Invalid array-index: \"%s\"", at_ptr);
65+
return -EINVAL;
66+
}
67+
if (unsigned_value > UINT32_MAX) {
68+
shell_error(sh, "Invalid array-index: \"%s\". Must be 0-4294967295.",
69+
at_ptr);
70+
return -EINVAL;
71+
}
72+
array_index = (uint32_t)unsigned_value;
73+
/* null terminate the string at the @ symbol */
74+
*at_ptr = 0;
75+
}
5576
if (bactext_property_strtol(argv[3], &found_index)) {
5677
value = found_index;
5778
} else {
@@ -69,6 +90,111 @@ static int cmd_key(BACNET_STORAGE_KEY *key, const struct shell *sh, size_t argc,
6990
return 0;
7091
}
7192

93+
/**
94+
* @brief Get or set a string using BACnet storage subsystem
95+
* @param sh Shell
96+
* @param argc Number of arguments
97+
* @param argv Argument list
98+
* @return 0 on success, negative on failure
99+
*/
100+
static int cmd_value(const struct shell *sh, size_t argc, char **argv)
101+
{
102+
char key_name[BACNET_STORAGE_KEY_SIZE_MAX + 1] = {0};
103+
uint8_t data[BACNET_STORAGE_VALUE_SIZE_MAX + 1] = {0};
104+
BACNET_STORAGE_KEY key = {0};
105+
int rc;
106+
unsigned enumerated_value = 0;
107+
bool status = false;
108+
bool null_value = false;
109+
BACNET_APPLICATION_DATA_VALUE value = {0};
110+
BACNET_OBJECT_PROPERTY_VALUE object_value = {0};
111+
char value_name[80] = {0};
112+
char *value_string = NULL;
113+
uint8_t value_tag;
114+
int len;
115+
116+
rc = cmd_key(&key, sh, argc, argv);
117+
if (rc < 0) {
118+
return rc;
119+
}
120+
/* convert the key to a string for the shell to print */
121+
(void)bacnet_storage_key_encode(key_name, sizeof(key_name), &key);
122+
if (argc > 4) {
123+
value_string = argv[4];
124+
if (property_list_commandable_member(key.object_type, key.property_id)) {
125+
/* check for case insensitive NULL string */
126+
if (bacnet_strnicmp(value_string, "NULL", 4) == 0) {
127+
null_value = true;
128+
}
129+
}
130+
/* convert the string value into a tagged union value */
131+
if (null_value) {
132+
value.tag = BACNET_APPLICATION_TAG_NULL;
133+
status = true;
134+
} else {
135+
value_tag = bacapp_known_property_tag(key.object_type, key.property_id);
136+
/* check for known property types */
137+
if (value_tag == BACNET_APPLICATION_TAG_ENUMERATED) {
138+
status = bactext_object_property_strtoul(
139+
(BACNET_OBJECT_TYPE)key.object_type,
140+
(BACNET_PROPERTY_ID)key.property_id, value_string,
141+
&enumerated_value);
142+
if (status) {
143+
value.tag = BACNET_APPLICATION_TAG_ENUMERATED;
144+
value.type.Enumerated = (uint32_t)enumerated_value;
145+
}
146+
} else {
147+
status = bacapp_parse_application_data(value_tag, value_string,
148+
&value);
149+
}
150+
}
151+
if (status) {
152+
shell_print(sh, "Parsed %s = %s as tag=%u", key_name, value_string,
153+
value.tag);
154+
len = bacapp_encode_application_data(NULL, &value);
155+
if (len <= 0) {
156+
return false;
157+
} else if (len > sizeof(data)) {
158+
return false;
159+
}
160+
len = bacapp_encode_application_data(data, &value);
161+
rc = bacnet_storage_set(&key, data, len);
162+
if (rc == 0) {
163+
shell_print(sh, "Set %s = %s", key_name, value_string);
164+
} else {
165+
shell_error(sh, "Unable to set %s = %s", key_name, value_string);
166+
return -EINVAL;
167+
}
168+
} else {
169+
shell_error(sh, "Unable to parse value for %s = %s", key_name,
170+
value_string);
171+
return -EINVAL;
172+
}
173+
} else {
174+
rc = bacnet_storage_get(&key, data, sizeof(data));
175+
if (rc < 0) {
176+
shell_error(sh, "Unable to get %s", key_name);
177+
return -EINVAL;
178+
}
179+
/* convert to printable value */
180+
len = bacapp_decode_known_array_property(data, rc, &value, key.object_type,
181+
key.property_id, key.array_index);
182+
if (len < 0) {
183+
shell_error(sh, "Unable to decode value for %s", key_name);
184+
return -EINVAL;
185+
}
186+
object_value.object_type = key.object_type;
187+
object_value.object_instance = key.object_instance;
188+
object_value.object_property = key.property_id;
189+
object_value.array_index = key.array_index;
190+
object_value.value = &value;
191+
bacapp_snprintf_value(value_name, sizeof(value_name), &object_value);
192+
shell_print(sh, "Get %s = %s", key_name, value_name);
193+
}
194+
195+
return 0;
196+
}
197+
72198
/**
73199
* @brief Get or set a string using BACnet storage subsystem
74200
* @param sh Shell
@@ -200,6 +326,7 @@ static int cmd_list(const struct shell *sh, size_t argc, char **argv)
200326

201327
SHELL_STATIC_SUBCMD_SET_CREATE(
202328
sub_bacnet_settings_cmds, SHELL_CMD(list, NULL, "list BACnet storage strings", cmd_list),
329+
SHELL_CMD(value, NULL, "get or set BACnet storage value", cmd_value),
203330
SHELL_CMD(string, NULL, "get or set BACnet storage string", cmd_string),
204331
SHELL_CMD(delete, NULL, "delete BACnet storage string", cmd_delete), SHELL_SUBCMD_SET_END);
205332

0 commit comments

Comments
 (0)