mirror of
https://dev.iopsys.eu/system/sysmngr.git
synced 2025-12-10 08:14:38 +01:00
Update TR-181 temperature monitoring to use sysfs
This commit is contained in:
parent
2643356bde
commit
3b5dd192b5
3 changed files with 484 additions and 80 deletions
|
|
@ -296,7 +296,7 @@ DMOBJ tDeviceInfoObj[] = {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SYSMNGR_TEMPERATURE_STATUS
|
#ifdef SYSMNGR_TEMPERATURE_STATUS
|
||||||
{"TemperatureStatus", &DMREAD, NULL, NULL, "file:/etc/sysmngr/temperature.sh", NULL, NULL, NULL, tDeviceInfoTemperatureStatusObj, tDeviceInfoTemperatureStatusParams, NULL, BBFDM_BOTH},
|
{"TemperatureStatus", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceInfoTemperatureStatusObj, tDeviceInfoTemperatureStatusParams, NULL, BBFDM_BOTH},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SYSMNGR_VENDOR_EXTENSIONS
|
#ifdef SYSMNGR_VENDOR_EXTENSIONS
|
||||||
|
|
|
||||||
|
|
@ -10,53 +10,419 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libbbfdm-api/dmcommon.h"
|
#include "libbbfdm-api/dmcommon.h"
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <linux/limits.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#define TEMPERATURE_SCRIPT "/etc/sysmngr/temperature.sh"
|
#define HWMON_PATH "/sys/class/hwmon"
|
||||||
#define TEMPERATURE_STATUS_CMD TEMPERATURE_SCRIPT " status"
|
#define THERMAL_PATH "/sys/class/thermal"
|
||||||
|
|
||||||
static void get_temperature_status(json_object **temp_status)
|
static int read_sysfs_int(const char *path, int *value)
|
||||||
{
|
{
|
||||||
char res[1024] = {0};
|
char buf[64] = {0};
|
||||||
|
char *endptr;
|
||||||
|
long val;
|
||||||
|
|
||||||
if (temp_status == NULL)
|
if (dm_read_sysfs_file(path, buf, sizeof(buf)) < 0)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
*temp_status = NULL;
|
errno = 0;
|
||||||
if (run_cmd(TEMPERATURE_STATUS_CMD, res, sizeof(res)) != 0)
|
val = strtol(buf, &endptr, 10);
|
||||||
return;
|
if (errno != 0 || endptr == buf || val > INT_MAX || val < INT_MIN)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (DM_STRLEN(res) != 0) {
|
*value = (int)val;
|
||||||
remove_new_line(res);
|
return 0;
|
||||||
*temp_status = json_tokener_parse(res);
|
}
|
||||||
|
|
||||||
|
static int read_sysfs_string(const char *path, char *buf, size_t buf_size)
|
||||||
|
{
|
||||||
|
if (dm_read_sysfs_file(path, buf, buf_size) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Remove trailing newline */
|
||||||
|
size_t len = strlen(buf);
|
||||||
|
if (len > 0 && buf[len - 1] == '\n')
|
||||||
|
buf[len - 1] = '\0';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_sysfs_int(const char *path, int value)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
// cppcheck-suppress cert-MSC24-C
|
||||||
|
f = fopen(path, "w");
|
||||||
|
if (!f)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = fprintf(f, "%d\n", value);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return (ret > 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void derive_alarm_path(const char *temp_input_path, const char *alarm_type, char *alarm_path, size_t alarm_path_size)
|
||||||
|
{
|
||||||
|
char *last_underscore;
|
||||||
|
char base_path[512];
|
||||||
|
|
||||||
|
/* Copy the input path */
|
||||||
|
snprintf(base_path, sizeof(base_path), "%s", temp_input_path);
|
||||||
|
|
||||||
|
/* Find last underscore (before "input") and replace with alarm type */
|
||||||
|
last_underscore = strrchr(base_path, '_');
|
||||||
|
if (last_underscore) {
|
||||||
|
*last_underscore = '\0';
|
||||||
|
snprintf(alarm_path, alarm_path_size, "%s_%s", base_path, alarm_type);
|
||||||
|
} else {
|
||||||
|
alarm_path[0] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int write_alarm_value(const char *sysfs_path, int trip_point_num, const char *hwmon_alarm_type, int value_millidegrees)
|
||||||
|
{
|
||||||
|
char alarm_path[512];
|
||||||
|
|
||||||
|
/* WiFi sensors don't have sysfs paths */
|
||||||
|
if (!sysfs_path || sysfs_path[0] == '\0')
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* For thermal zones: try trip_point_X_temp */
|
||||||
|
if (strstr(sysfs_path, "thermal_zone")) {
|
||||||
|
char *last_slash = strrchr(sysfs_path, '/');
|
||||||
|
if (last_slash) {
|
||||||
|
char zone_dir[480]; /* Leave room for suffix in alarm_path */
|
||||||
|
size_t dir_len = last_slash - sysfs_path;
|
||||||
|
if (dir_len >= sizeof(zone_dir))
|
||||||
|
dir_len = sizeof(zone_dir) - 1;
|
||||||
|
snprintf(zone_dir, dir_len + 1, "%s", sysfs_path);
|
||||||
|
snprintf(alarm_path, sizeof(alarm_path), "%s/trip_point_%d_temp", zone_dir, trip_point_num);
|
||||||
|
if (write_sysfs_int(alarm_path, value_millidegrees) == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For hwmon: try temp*_<alarm_type> */
|
||||||
|
derive_alarm_path(sysfs_path, hwmon_alarm_type, alarm_path, sizeof(alarm_path));
|
||||||
|
if (write_sysfs_int(alarm_path, value_millidegrees) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_alarm_value(const char *sysfs_path, int trip_point_num, const char *hwmon_alarm_type, int *value_millidegrees)
|
||||||
|
{
|
||||||
|
char alarm_path[512];
|
||||||
|
|
||||||
|
/* WiFi sensors don't have sysfs paths */
|
||||||
|
if (!sysfs_path || sysfs_path[0] == '\0')
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* For thermal zones: try trip_point_X_temp */
|
||||||
|
if (strstr(sysfs_path, "thermal_zone")) {
|
||||||
|
char *last_slash = strrchr(sysfs_path, '/');
|
||||||
|
if (last_slash) {
|
||||||
|
char zone_dir[480]; /* Leave room for suffix in alarm_path */
|
||||||
|
size_t dir_len = last_slash - sysfs_path;
|
||||||
|
if (dir_len >= sizeof(zone_dir))
|
||||||
|
dir_len = sizeof(zone_dir) - 1;
|
||||||
|
snprintf(zone_dir, dir_len + 1, "%s", sysfs_path);
|
||||||
|
snprintf(alarm_path, sizeof(alarm_path), "%s/trip_point_%d_temp", zone_dir, trip_point_num);
|
||||||
|
if (read_sysfs_int(alarm_path, value_millidegrees) == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For hwmon: try temp*_<alarm_type> */
|
||||||
|
derive_alarm_path(sysfs_path, hwmon_alarm_type, alarm_path, sizeof(alarm_path));
|
||||||
|
if (read_sysfs_int(alarm_path, value_millidegrees) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scan_hwmon_sensors(json_object *sensors_array)
|
||||||
|
{
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent *entry;
|
||||||
|
|
||||||
|
dir = opendir(HWMON_PATH);
|
||||||
|
if (!dir)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
if (entry->d_name[0] == '.')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
char hwmon_dir[280]; /* HWMON_PATH (17) + "/" + d_name (255) + null */
|
||||||
|
char real_path[512];
|
||||||
|
snprintf(hwmon_dir, sizeof(hwmon_dir), "%s/%s", HWMON_PATH, entry->d_name);
|
||||||
|
|
||||||
|
/* Resolve symlink to check if this is a thermal zone hwmon interface */
|
||||||
|
if (realpath(hwmon_dir, real_path) != NULL) {
|
||||||
|
/* Skip if this hwmon device belongs to a thermal zone */
|
||||||
|
/* Thermal zones create hwmon interfaces under /sys/devices/virtual/thermal/thermal_zoneX/hwmonY */
|
||||||
|
if (strstr(real_path, "/thermal/thermal_zone") != NULL)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scan for tempX_input files */
|
||||||
|
for (int i = 1; i <= 10; i++) {
|
||||||
|
char temp_path[512];
|
||||||
|
char label_path[512];
|
||||||
|
char name_path[512];
|
||||||
|
char name[280] = {0}; /* d_name (255) + "_temp" + digit + null */
|
||||||
|
int temp_value = 0;
|
||||||
|
|
||||||
|
snprintf(temp_path, sizeof(temp_path), "%s/temp%d_input", hwmon_dir, i);
|
||||||
|
|
||||||
|
if (read_sysfs_int(temp_path, &temp_value) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Try to read sensor label first, then hwmon name */
|
||||||
|
snprintf(label_path, sizeof(label_path), "%s/temp%d_label", hwmon_dir, i);
|
||||||
|
if (read_sysfs_string(label_path, name, sizeof(name)) < 0) {
|
||||||
|
snprintf(name_path, sizeof(name_path), "%s/name", hwmon_dir);
|
||||||
|
if (read_sysfs_string(name_path, name, sizeof(name)) < 0) {
|
||||||
|
snprintf(name, sizeof(name), "%s_temp%d", entry->d_name, i);
|
||||||
|
} else {
|
||||||
|
/* Append temp index */
|
||||||
|
char suffix[32];
|
||||||
|
snprintf(suffix, sizeof(suffix), "_temp%d", i);
|
||||||
|
strncat(name, suffix, sizeof(name) - strlen(name) - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create JSON object for this sensor */
|
||||||
|
json_object *sensor = json_object_new_object();
|
||||||
|
json_object_object_add(sensor, "name", json_object_new_string(name));
|
||||||
|
json_object_object_add(sensor, "sysfs_path", json_object_new_string(temp_path));
|
||||||
|
json_object_object_add(sensor, "temperature", json_object_new_int(temp_value / 1000));
|
||||||
|
json_object_array_add(sensors_array, sensor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int interface_exists(const char *ifname)
|
||||||
|
{
|
||||||
|
char path[256];
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
/* Validate interface name to prevent path traversal */
|
||||||
|
if (!ifname || ifname[0] == '\0' || strchr(ifname, '/') || strchr(ifname, '.'))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "/sys/class/net/%s", ifname);
|
||||||
|
return (stat(path, &st) == 0 && S_ISDIR(st.st_mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scan_mwctl_sensors(json_object *sensors_array)
|
||||||
|
{
|
||||||
|
const char *interfaces[] = {"ra0", "rai0", "rax0", NULL};
|
||||||
|
char output[4096];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; interfaces[i] != NULL; i++) {
|
||||||
|
const char *ifname = interfaces[i];
|
||||||
|
FILE *fp;
|
||||||
|
int found_temp = 0;
|
||||||
|
int temp_value = 0;
|
||||||
|
char cmd[256];
|
||||||
|
|
||||||
|
if (!interface_exists(ifname))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Build command for popen - interface name is validated */
|
||||||
|
snprintf(cmd, sizeof(cmd), "/usr/sbin/mwctl %s stat 2>/dev/null", ifname);
|
||||||
|
|
||||||
|
fp = popen(cmd, "r"); // flawfinder: ignore
|
||||||
|
if (!fp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
while (fgets(output, sizeof(output), fp) != NULL) {
|
||||||
|
/* Look for "CurrentTemperature = <value>" */
|
||||||
|
if (strstr(output, "CurrentTemperature") != NULL) {
|
||||||
|
char *equals = strchr(output, '=');
|
||||||
|
if (equals) {
|
||||||
|
char *endptr;
|
||||||
|
long val = strtol(equals + 1, &endptr, 10);
|
||||||
|
if (endptr != equals + 1 && val >= INT_MIN && val <= INT_MAX) {
|
||||||
|
temp_value = (int)val;
|
||||||
|
found_temp = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pclose(fp);
|
||||||
|
|
||||||
|
if (found_temp) {
|
||||||
|
char name[256];
|
||||||
|
snprintf(name, sizeof(name), "wifi_%s", ifname);
|
||||||
|
|
||||||
|
json_object *sensor = json_object_new_object();
|
||||||
|
json_object_object_add(sensor, "name", json_object_new_string(name));
|
||||||
|
json_object_object_add(sensor, "sysfs_path", json_object_new_string(""));
|
||||||
|
json_object_object_add(sensor, "temperature", json_object_new_int(temp_value));
|
||||||
|
json_object_object_add(sensor, "wifi_interface", json_object_new_string(ifname));
|
||||||
|
json_object_object_add(sensor, "wifi_type", json_object_new_string("mwctl"));
|
||||||
|
json_object_array_add(sensors_array, sensor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scan_wlctl_sensors(json_object *sensors_array)
|
||||||
|
{
|
||||||
|
const char *interfaces[] = {"wl0", "wl1", "wl2", NULL};
|
||||||
|
char output[256];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; interfaces[i] != NULL; i++) {
|
||||||
|
const char *ifname = interfaces[i];
|
||||||
|
FILE *fp;
|
||||||
|
int temp_value = 0;
|
||||||
|
int found_temp = 0;
|
||||||
|
char cmd[256];
|
||||||
|
|
||||||
|
if (!interface_exists(ifname))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Build command for popen - interface name is validated */
|
||||||
|
snprintf(cmd, sizeof(cmd), "/usr/sbin/wlctl -i %s phy_tempsense 2>/dev/null", ifname);
|
||||||
|
|
||||||
|
fp = popen(cmd, "r"); // flawfinder: ignore
|
||||||
|
if (!fp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (fgets(output, sizeof(output), fp) != NULL) {
|
||||||
|
/* Output is typically just a number or "Temperature: <value>" */
|
||||||
|
char *endptr;
|
||||||
|
long val = strtol(output, &endptr, 10);
|
||||||
|
if (endptr != output && val > 0 && val <= INT_MAX) {
|
||||||
|
temp_value = (int)val;
|
||||||
|
found_temp = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pclose(fp);
|
||||||
|
|
||||||
|
if (found_temp) {
|
||||||
|
char name[256];
|
||||||
|
snprintf(name, sizeof(name), "wifi_%s", ifname);
|
||||||
|
|
||||||
|
json_object *sensor = json_object_new_object();
|
||||||
|
json_object_object_add(sensor, "name", json_object_new_string(name));
|
||||||
|
json_object_object_add(sensor, "sysfs_path", json_object_new_string(""));
|
||||||
|
json_object_object_add(sensor, "temperature", json_object_new_int(temp_value));
|
||||||
|
json_object_object_add(sensor, "wifi_interface", json_object_new_string(ifname));
|
||||||
|
json_object_object_add(sensor, "wifi_type", json_object_new_string("wlctl"));
|
||||||
|
json_object_array_add(sensors_array, sensor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scan_thermal_zones(json_object *sensors_array)
|
||||||
|
{
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent *entry;
|
||||||
|
|
||||||
|
dir = opendir(THERMAL_PATH);
|
||||||
|
if (!dir)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
if (strncmp(entry->d_name, "thermal_zone", 12) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
char zone_dir[280]; /* THERMAL_PATH (19) + "/" + d_name (255) + null */
|
||||||
|
char temp_path[512];
|
||||||
|
char type_path[512];
|
||||||
|
char type[128] = {0};
|
||||||
|
char name[256] = {0};
|
||||||
|
int temp_value = 0;
|
||||||
|
|
||||||
|
snprintf(zone_dir, sizeof(zone_dir), "%s/%s", THERMAL_PATH, entry->d_name);
|
||||||
|
snprintf(temp_path, sizeof(temp_path), "%s/temp", zone_dir);
|
||||||
|
snprintf(type_path, sizeof(type_path), "%s/type", zone_dir);
|
||||||
|
|
||||||
|
if (read_sysfs_int(temp_path, &temp_value) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Try to read the zone type for name */
|
||||||
|
if (read_sysfs_string(type_path, type, sizeof(type)) == 0 && type[0] != '\0') {
|
||||||
|
snprintf(name, sizeof(name), "%s", type);
|
||||||
|
} else {
|
||||||
|
snprintf(name, sizeof(name), "%s", entry->d_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create JSON object for this sensor */
|
||||||
|
json_object *sensor = json_object_new_object();
|
||||||
|
json_object_object_add(sensor, "name", json_object_new_string(name));
|
||||||
|
json_object_object_add(sensor, "sysfs_path", json_object_new_string(temp_path));
|
||||||
|
json_object_object_add(sensor, "temperature", json_object_new_int(temp_value / 1000));
|
||||||
|
json_object_array_add(sensors_array, sensor);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void discover_sensors(json_object **sensors_data)
|
||||||
|
{
|
||||||
|
*sensors_data = json_object_new_array();
|
||||||
|
|
||||||
|
/* Scan hwmon sensors */
|
||||||
|
scan_hwmon_sensors(*sensors_data);
|
||||||
|
|
||||||
|
/* Scan thermal zones */
|
||||||
|
scan_thermal_zones(*sensors_data);
|
||||||
|
|
||||||
|
/* Scan WiFi sensors via mwctl (MediaTek) */
|
||||||
|
scan_mwctl_sensors(*sensors_data);
|
||||||
|
|
||||||
|
/* Scan WiFi sensors via wlctl (Broadcom) */
|
||||||
|
scan_wlctl_sensors(*sensors_data);
|
||||||
|
}
|
||||||
|
|
||||||
static int browseTemperatureSensor(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
|
static int browseTemperatureSensor(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
|
||||||
{
|
{
|
||||||
json_object *temp_status = NULL;
|
json_object *sensors_data = NULL;
|
||||||
struct dm_data data = {0};
|
struct dm_data data = {0};
|
||||||
|
int instance_id = 0;
|
||||||
|
|
||||||
get_temperature_status(&temp_status);
|
discover_sensors(&sensors_data);
|
||||||
if (temp_status) { /* cppcheck-suppress knownConditionTrueFalse */
|
|
||||||
int id = 0, iter = 0;
|
|
||||||
json_object *arrobj = NULL, *tobj = NULL;
|
|
||||||
|
|
||||||
dmjson_foreach_obj_in_array(temp_status, arrobj, tobj, iter, 1, "status") {
|
if (sensors_data) {
|
||||||
char *inst;
|
int array_len = json_object_array_length(sensors_data);
|
||||||
|
|
||||||
data.json_object = tobj;
|
for (int i = 0; i < array_len; i++) {
|
||||||
|
json_object *sensor_obj = json_object_array_get_idx(sensors_data, i);
|
||||||
|
if (!sensor_obj)
|
||||||
|
continue;
|
||||||
|
|
||||||
inst = handle_instance_without_section(dmctx, parent_node, ++id);
|
data.json_object = sensor_obj;
|
||||||
|
|
||||||
|
char *inst = handle_instance_without_section(dmctx, parent_node, ++instance_id);
|
||||||
if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&data, inst) == DM_STOP)
|
if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&data, inst) == DM_STOP)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
json_object_put(temp_status);
|
json_object_put(sensors_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* GET/SET PARAMETER FUNCTIONS
|
||||||
|
*************************************************************/
|
||||||
|
|
||||||
static int get_TemperatureStatus_numentries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
static int get_TemperatureStatus_numentries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||||
{
|
{
|
||||||
int cnt = get_number_of_entries(ctx, data, instance, browseTemperatureSensor);
|
int cnt = get_number_of_entries(ctx, data, instance, browseTemperatureSensor);
|
||||||
|
|
@ -112,6 +478,98 @@ static int get_TemperatureSensor_value(char *refparam, struct dmctx *ctx, void *
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int set_alarm_value_common(struct dmctx *ctx, void *data, char *value, int action, int trip_point_num, const char *hwmon_alarm_type)
|
||||||
|
{
|
||||||
|
json_object *obj = ((struct dm_data *)data)->json_object;
|
||||||
|
const char *sysfs_path;
|
||||||
|
int alarm_value_celsius;
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case VALUECHECK:
|
||||||
|
if (bbfdm_validate_string(ctx, value, -1, -1, NULL, NULL))
|
||||||
|
return FAULT_9007;
|
||||||
|
{
|
||||||
|
char *endptr;
|
||||||
|
long val = strtol(value, &endptr, 10);
|
||||||
|
if (endptr == value || val < -274 || val > INT_MAX)
|
||||||
|
return FAULT_9007;
|
||||||
|
alarm_value_celsius = (int)val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VALUESET:
|
||||||
|
sysfs_path = dmjson_get_value(obj, 1, "sysfs_path");
|
||||||
|
if (!sysfs_path || sysfs_path[0] == '\0')
|
||||||
|
return FAULT_9002;
|
||||||
|
|
||||||
|
{
|
||||||
|
char *endptr;
|
||||||
|
long val = strtol(value, &endptr, 10);
|
||||||
|
if (endptr == value || val < INT_MIN || val > INT_MAX)
|
||||||
|
return FAULT_9002;
|
||||||
|
alarm_value_celsius = (int)val;
|
||||||
|
}
|
||||||
|
if (alarm_value_celsius == -274) {
|
||||||
|
/* -274 means disable/unconfigure - skip writing */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_alarm_value(sysfs_path, trip_point_num, hwmon_alarm_type, alarm_value_celsius * 1000) != 0)
|
||||||
|
return FAULT_9002;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_TemperatureSensor_low_alarm_value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||||
|
{
|
||||||
|
json_object *obj = ((struct dm_data *)data)->json_object;
|
||||||
|
const char *sysfs_path = dmjson_get_value(obj, 1, "sysfs_path");
|
||||||
|
int alarm_value;
|
||||||
|
|
||||||
|
*value = dmstrdup("-274"); /* Default: not configured */
|
||||||
|
|
||||||
|
if (!sysfs_path || sysfs_path[0] == '\0')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* trip_point_1_temp for thermal zones, temp*_crit for hwmon */
|
||||||
|
if (read_alarm_value(sysfs_path, 1, "crit", &alarm_value) == 0) {
|
||||||
|
dmasprintf(value, "%d", alarm_value / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_TemperatureSensor_low_alarm_value(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||||
|
{
|
||||||
|
/* trip_point_1_temp for thermal zones, temp*_crit for hwmon */
|
||||||
|
return set_alarm_value_common(ctx, data, value, action, 1, "crit");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_TemperatureSensor_high_alarm_value(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||||
|
{
|
||||||
|
json_object *obj = ((struct dm_data *)data)->json_object;
|
||||||
|
const char *sysfs_path = dmjson_get_value(obj, 1, "sysfs_path");
|
||||||
|
int alarm_value;
|
||||||
|
|
||||||
|
*value = dmstrdup("-274"); /* Default: not configured */
|
||||||
|
|
||||||
|
if (!sysfs_path || sysfs_path[0] == '\0')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* trip_point_0_temp for thermal zones, temp*_max for hwmon */
|
||||||
|
if (read_alarm_value(sysfs_path, 0, "max", &alarm_value) == 0) {
|
||||||
|
dmasprintf(value, "%d", alarm_value / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_TemperatureSensor_high_alarm_value(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||||
|
{
|
||||||
|
/* trip_point_0_temp for thermal zones, temp*_max for hwmon */
|
||||||
|
return set_alarm_value_common(ctx, data, value, action, 0, "max");
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************************************************************
|
/******************************************************************************************************************************
|
||||||
* OBJ & PARAM DEFINITION
|
* OBJ & PARAM DEFINITION
|
||||||
*******************************************************************************************************************************/
|
*******************************************************************************************************************************/
|
||||||
|
|
@ -120,10 +578,12 @@ static DMLEAF tTemperatureStatusTemperatureSensorParams[] = {
|
||||||
{"Alias", &DMWRITE, DMT_STRING, get_TemperatureSensor_alias, set_TemperatureSensor_alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
|
{"Alias", &DMWRITE, DMT_STRING, get_TemperatureSensor_alias, set_TemperatureSensor_alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
|
||||||
{"Name", &DMREAD, DMT_STRING, get_TemperatureSensor_name, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
|
{"Name", &DMREAD, DMT_STRING, get_TemperatureSensor_name, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE},
|
||||||
{"Value", &DMREAD, DMT_INT, get_TemperatureSensor_value, NULL, BBFDM_BOTH},
|
{"Value", &DMREAD, DMT_INT, get_TemperatureSensor_value, NULL, BBFDM_BOTH},
|
||||||
|
{"LowAlarmValue", &DMWRITE, DMT_INT, get_TemperatureSensor_low_alarm_value, set_TemperatureSensor_low_alarm_value, BBFDM_BOTH},
|
||||||
|
{"HighAlarmValue", &DMWRITE, DMT_INT, get_TemperatureSensor_high_alarm_value, set_TemperatureSensor_high_alarm_value, BBFDM_BOTH},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* *** Device.DeviceInfo.TemperatureTemperatureStatus; ubus call "bbf.temp status" *** */
|
/* *** Device.DeviceInfo.TemperatureStatus *** */
|
||||||
DMOBJ tDeviceInfoTemperatureStatusObj[] = {
|
DMOBJ tDeviceInfoTemperatureStatusObj[] = {
|
||||||
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/
|
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/
|
||||||
{"TemperatureSensor", &DMREAD, NULL, NULL, NULL, browseTemperatureSensor, NULL, NULL, NULL, tTemperatureStatusTemperatureSensorParams, NULL, BBFDM_BOTH},
|
{"TemperatureSensor", &DMREAD, NULL, NULL, NULL, browseTemperatureSensor, NULL, NULL, NULL, tTemperatureStatusTemperatureSensorParams, NULL, BBFDM_BOTH},
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
. /usr/share/libubox/jshn.sh
|
|
||||||
. /lib/functions.sh
|
|
||||||
|
|
||||||
function get_wlan_temperature()
|
|
||||||
{
|
|
||||||
:
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_sfp_temperature()
|
|
||||||
{
|
|
||||||
json_add_object
|
|
||||||
json_add_string "name" "sfp"
|
|
||||||
json_add_int "temperature" "-274"
|
|
||||||
json_close_object
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_cpu_temperature()
|
|
||||||
{
|
|
||||||
json_add_object
|
|
||||||
json_add_string "name" "cpu"
|
|
||||||
json_add_int "temperature" "-274"
|
|
||||||
json_close_object
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_temperature_status()
|
|
||||||
{
|
|
||||||
local hasWifi="$(db -q get hw.board.hasWifi)"
|
|
||||||
local hasSfp="$(db -q get hw.board.hasSfp)"
|
|
||||||
|
|
||||||
json_init
|
|
||||||
json_add_array "status"
|
|
||||||
get_cpu_temperature
|
|
||||||
[ "$hasSfp" = "1" ] && get_sfp_temperature
|
|
||||||
[ "$hasWifi" = "1" ] && get_wlan_temperature
|
|
||||||
json_close_array
|
|
||||||
|
|
||||||
json_dump
|
|
||||||
}
|
|
||||||
|
|
||||||
function dump_invalid()
|
|
||||||
{
|
|
||||||
json_init
|
|
||||||
json_add_string "fault" "invalid request"
|
|
||||||
json_dump
|
|
||||||
}
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
status)
|
|
||||||
get_temperature_status
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
dump_invalid
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
Loading…
Add table
Reference in a new issue