diff options
Diffstat (limited to 'mfi-mqtt/reporting.c')
-rw-r--r-- | mfi-mqtt/reporting.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/mfi-mqtt/reporting.c b/mfi-mqtt/reporting.c new file mode 100644 index 0000000..7b4131a --- /dev/null +++ b/mfi-mqtt/reporting.c | |||
@@ -0,0 +1,143 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | #include <unistd.h> | ||
5 | #include <stdbool.h> | ||
6 | #include <json-c/json.h> | ||
7 | |||
8 | #include <net/if.h> | ||
9 | #include <sys/socket.h> | ||
10 | #include <sys/ioctl.h> | ||
11 | #include <arpa/inet.h> | ||
12 | |||
13 | #include "reporting.h" | ||
14 | |||
15 | power_statistics * init_power_statistics(int relay_num) { | ||
16 | power_statistics *stats = malloc(sizeof(power_statistics)); | ||
17 | stats->relay_num = relay_num; | ||
18 | stats->engaged = calloc(strlen("false") + 1, sizeof(char)); | ||
19 | return stats; | ||
20 | } | ||
21 | |||
22 | void free_power_statistics(power_statistics *stats) { | ||
23 | free(stats->engaged); | ||
24 | free(stats); | ||
25 | } | ||
26 | |||
27 | bool power_statistics_is_engaged(power_statistics *stats) { | ||
28 | return strcmp(stats->engaged, "on") == 0; | ||
29 | } | ||
30 | |||
31 | int power_statistics_load_from_file(power_statistics *stats) { | ||
32 | FILE *fp; | ||
33 | char filename[12]; | ||
34 | |||
35 | snprintf(filename, 12, "/dev/power%d", stats->relay_num); | ||
36 | |||
37 | fp = fopen(filename, "r"); | ||
38 | if (!fp) { | ||
39 | return 1; | ||
40 | } | ||
41 | |||
42 | if (fscanf(fp, "%s %f\n %f\n %f\n %f\n %f\n", | ||
43 | stats->engaged, | ||
44 | &stats->active_power, | ||
45 | &stats->energy_sum, | ||
46 | &stats->current_rms, | ||
47 | &stats->voltage_rms, | ||
48 | &stats->power_factor) != 6) { | ||
49 | fclose(fp); | ||
50 | return 1; | ||
51 | } | ||
52 | |||
53 | fclose(fp); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | int get_output_count() { | ||
58 | return access("/dev/power8", F_OK) != -1 ? 8 : 3; | ||
59 | } | ||
60 | |||
61 | int get_stats_all_outputs(power_statistics ***out_stats) { | ||
62 | int i; | ||
63 | int output_count; | ||
64 | power_statistics *stat; | ||
65 | power_statistics **stats; | ||
66 | |||
67 | output_count = get_output_count(); | ||
68 | stats = malloc(sizeof(power_statistics *) * (output_count + 1)); | ||
69 | |||
70 | for (i = output_count; i > 0; i--) { | ||
71 | stat = init_power_statistics(i); | ||
72 | |||
73 | if (power_statistics_load_from_file(stat)) { | ||
74 | continue; | ||
75 | } | ||
76 | |||
77 | stats[i] = stat; | ||
78 | } | ||
79 | |||
80 | *out_stats = stats; | ||
81 | |||
82 | return output_count; | ||
83 | } | ||
84 | |||
85 | json_object * format_power_satistics_output_json(power_statistics *stats) { | ||
86 | json_object *top_object; | ||
87 | |||
88 | top_object = json_object_new_object(); | ||
89 | json_object_object_add(top_object, "output", json_object_new_int(stats->relay_num)); | ||
90 | json_object_object_add(top_object, "engaged", json_object_new_boolean(power_statistics_is_engaged(stats))); | ||
91 | json_object_object_add(top_object, "active_power", json_object_new_double(stats->active_power)); | ||
92 | json_object_object_add(top_object, "energy_sum", json_object_new_double(stats->energy_sum)); | ||
93 | json_object_object_add(top_object, "current_rms", json_object_new_double(stats->current_rms)); | ||
94 | json_object_object_add(top_object, "voltage_rms", json_object_new_double(stats->voltage_rms)); | ||
95 | json_object_object_add(top_object, "power_factor", json_object_new_double(stats->power_factor)); | ||
96 | |||
97 | return top_object; | ||
98 | } | ||
99 | |||
100 | char * format_report_all_outputs(power_statistics **stats, int report_count) { | ||
101 | int i; | ||
102 | char *output; | ||
103 | char hostname[256]; | ||
104 | char ip_address[15]; | ||
105 | const char *tmp; | ||
106 | json_object *top_object, *report_array; | ||
107 | |||
108 | memset(hostname, 0, sizeof(hostname)); | ||
109 | gethostname(hostname, 255); | ||
110 | |||
111 | memset(ip_address, 0, sizeof(ip_address)); | ||
112 | get_primary_ip_address(ip_address); | ||
113 | |||
114 | report_array = json_object_new_array(); | ||
115 | top_object = json_object_new_object(); | ||
116 | json_object_object_add(top_object, "hostname", json_object_new_string(hostname)); | ||
117 | json_object_object_add(top_object, "ip_address", json_object_new_string(ip_address)); | ||
118 | json_object_object_add(top_object, "reports", report_array); | ||
119 | |||
120 | for (i = report_count; i > 0; i--) { | ||
121 | json_object_array_add(report_array, format_power_satistics_output_json(stats[i])); | ||
122 | free_power_statistics(stats[i]); | ||
123 | } | ||
124 | |||
125 | tmp = json_object_to_json_string_ext(top_object, JSON_C_TO_STRING_PLAIN); | ||
126 | output = strdup(tmp); | ||
127 | json_object_put(top_object); | ||
128 | |||
129 | return output; | ||
130 | } | ||
131 | |||
132 | void get_primary_ip_address(char ip_address[15]) | ||
133 | { | ||
134 | int fd; | ||
135 | struct ifreq ifr; | ||
136 | |||
137 | fd = socket(AF_INET, SOCK_DGRAM, 0); | ||
138 | memcpy(ifr.ifr_name, "ath0", IFNAMSIZ-1); | ||
139 | ioctl(fd, SIOCGIFADDR, &ifr); | ||
140 | close(fd); | ||
141 | |||
142 | strncpy(ip_address, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr), 15); | ||
143 | } | ||