summaryrefslogtreecommitdiff
path: root/mfi-mqtt/reporting.c
diff options
context:
space:
mode:
Diffstat (limited to 'mfi-mqtt/reporting.c')
-rw-r--r--mfi-mqtt/reporting.c143
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
15power_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
22void free_power_statistics(power_statistics *stats) {
23 free(stats->engaged);
24 free(stats);
25}
26
27bool power_statistics_is_engaged(power_statistics *stats) {
28 return strcmp(stats->engaged, "on") == 0;
29}
30
31int 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
57int get_output_count() {
58 return access("/dev/power8", F_OK) != -1 ? 8 : 3;
59}
60
61int 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
85json_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
100char * 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
132void 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}