1 /*
2  * Copyright (c) 2024 Analog Devices, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(app_device, LOG_LEVEL_DBG);
9 
10 #include <zephyr/kernel.h>
11 #include <zephyr/drivers/sensor.h>
12 #include <zephyr/drivers/led.h>
13 #include <zephyr/random/random.h>
14 
15 #include "device.h"
16 
17 #define SENSOR_CHAN     SENSOR_CHAN_AMBIENT_TEMP
18 #define SENSOR_UNIT     "Celsius"
19 
20 /* Devices */
21 static const struct device *sensor = DEVICE_DT_GET_OR_NULL(DT_ALIAS(ambient_temp0));
22 static const struct device *leds = DEVICE_DT_GET_OR_NULL(DT_INST(0, gpio_leds));
23 
24 /* Command handlers */
led_on_handler(void)25 static void led_on_handler(void)
26 {
27 	device_write_led(LED_USER, LED_ON);
28 }
29 
led_off_handler(void)30 static void led_off_handler(void)
31 {
32 	device_write_led(LED_USER, LED_OFF);
33 }
34 
35 /* Supported device commands */
36 struct device_cmd device_commands[] = {
37 	{"led_on", led_on_handler},
38 	{"led_off", led_off_handler}
39 };
40 
41 const size_t num_device_commands = ARRAY_SIZE(device_commands);
42 
43 /* Command dispatcher */
device_command_handler(uint8_t * command)44 void device_command_handler(uint8_t *command)
45 {
46 	for (int i = 0; i < num_device_commands; i++) {
47 		if (strcmp(command, device_commands[i].command) == 0) {
48 			LOG_INF("Executing device command: %s", device_commands[i].command);
49 			return device_commands[i].handler();
50 		}
51 	}
52 	LOG_ERR("Unknown command: %s", command);
53 }
54 
device_read_sensor(struct sensor_sample * sample)55 int device_read_sensor(struct sensor_sample *sample)
56 {
57 	int rc;
58 	struct sensor_value sensor_val;
59 
60 	/* Read sample only if a real sensor device is present
61 	 * otherwise return a dummy value
62 	 */
63 	if (sensor == NULL) {
64 		sample->unit = SENSOR_UNIT;
65 		sample->value = 20.0 + (double)sys_rand32_get() / UINT32_MAX * 5.0;
66 		return 0;
67 	}
68 
69 	rc = sensor_sample_fetch(sensor);
70 	if (rc) {
71 		LOG_ERR("Failed to fetch sensor sample [%d]", rc);
72 		return rc;
73 	}
74 
75 	rc = sensor_channel_get(sensor, SENSOR_CHAN, &sensor_val);
76 	if (rc) {
77 		LOG_ERR("Failed to get sensor channel [%d]", rc);
78 		return rc;
79 	}
80 
81 	sample->unit = SENSOR_UNIT;
82 	sample->value = sensor_value_to_double(&sensor_val);
83 	return rc;
84 }
85 
device_write_led(enum led_id led_idx,enum led_state state)86 int device_write_led(enum led_id led_idx, enum led_state state)
87 {
88 	int rc;
89 
90 	switch (state) {
91 	case LED_OFF:
92 		if (leds == NULL) {
93 			LOG_INF("LED %d OFF", led_idx);
94 			break;
95 		}
96 		led_off(leds, led_idx);
97 		break;
98 	case LED_ON:
99 		if (leds == NULL) {
100 			LOG_INF("LED %d ON", led_idx);
101 			break;
102 		}
103 		led_on(leds, led_idx);
104 		break;
105 	default:
106 		LOG_ERR("Invalid LED state setting");
107 		rc = -EINVAL;
108 		break;
109 	}
110 
111 	return rc;
112 }
113 
devices_ready(void)114 bool devices_ready(void)
115 {
116 	bool rc = true;
117 
118 	/* Check readiness only if a real sensor device is present */
119 	if (sensor != NULL) {
120 		if (!device_is_ready(sensor)) {
121 			LOG_ERR("Device %s is not ready", sensor->name);
122 			rc = false;
123 		} else {
124 			LOG_INF("Device %s is ready", sensor->name);
125 		}
126 	}
127 
128 	if (leds != NULL) {
129 		if (!device_is_ready(leds)) {
130 			LOG_ERR("Device %s is not ready", leds->name);
131 			rc = false;
132 		} else {
133 			LOG_INF("Device %s is ready", leds->name);
134 		}
135 	}
136 
137 	return rc;
138 }
139