UPS: apcupsd clean sources
[tomato.git] / release / src / router / apcupsd / src / cgi / upsimage.c
blob8a8f28203629fcbf21542ab5455142b5b0d15df4
1 /*
2 * upsimage - cgi program to create graphical ups information reports
4 * Original Author: Russell Kroll <rkroll@exploits.org>
6 * When used together, upsstats and upsimage create interesting looking web
7 * pages with graphical representations of the battery capacity, utility
8 * voltage, and UPS load.
10 * This program utilizes the gd graphics library for snappy IMG generation.
11 * I highly recommend this package for anyone doing similar graphics
12 * "on the fly" in C.
14 * This binary needs to be installed some place where upsstats can find it.
16 * Modified: Jonathan Benson <jbenson@technologist.com>
17 * 19/6/98 to suit apcupsd
18 * 23/6/98 added more graphs and menu options
20 * Modified by Kern Sibbald to include additional graphs as well as
21 * to adapt the graphs to varing conditions (voltage, ...). Also,
22 * consolidate a lot of code into subroutines.
24 * Modified by Riccardo Facchetti to support both GIF and PNG formats.
28 #include "apc.h"
30 #if !defined(SYS_IMGFMT_PNG) && !defined(SYS_IMGFMT_GIF) && !defined(IMGFMT_GIF)
31 # error "A graphic file format must be defined to compile this program."
32 #endif
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
38 #include "cgiconfig.h"
39 #include "cgilib.h"
41 static char mycmd[16] = "";
42 static char upsval[16] = "";
43 static char upsval2[16] = "";
44 static char upsval3[16] = "";
46 static int green, black, white, grey, darkgrey, red;
48 static void allocate_colors(gdImagePtr im)
50 black = gdImageColorAllocate (im, 0, 0, 0);
51 green = gdImageColorAllocate (im, 0, 255, 0);
52 white = gdImageColorAllocate (im, 255, 255, 255);
53 grey = gdImageColorAllocate (im, 200, 200, 200);
54 darkgrey = gdImageColorAllocate (im, 50, 50, 50);
55 red = gdImageColorAllocate (im, 255, 0, 0);
58 static void DrawTickLines(gdImagePtr im)
60 gdImageLine (im, 50, 60, 150, 60, darkgrey);
61 gdImageLine (im, 50, 120, 150, 120, darkgrey);
62 gdImageLine (im, 50, 180, 150, 180, darkgrey);
63 gdImageLine (im, 50, 240, 150, 240, darkgrey);
64 gdImageLine (im, 50, 300, 150, 300, darkgrey);
67 static void DrawText(gdImagePtr im, int min, int step)
69 int next;
70 char text[10];
72 next = min;
73 (void) snprintf(text, sizeof(text), "%d", next);
74 gdImageString(im, gdFontLarge, 0, 295, (unsigned char *)text, black);
76 next += step;
77 (void) snprintf(text, sizeof(text), "%d", next);
78 gdImageString(im, gdFontLarge, 0, 235, (unsigned char *)text, black);
80 next += step;
81 (void) snprintf(text, sizeof(text), "%d", next);
82 gdImageString(im, gdFontLarge, 0, 175, (unsigned char *)text, black);
84 next += step;
85 (void) snprintf(text, sizeof(text), "%d", next);
86 gdImageString(im, gdFontLarge, 0, 115, (unsigned char *)text, black);
88 next += step;
89 (void) snprintf(text, sizeof(text), "%d", next);
90 gdImageString(im, gdFontLarge, 0, 55, (unsigned char *)text, black);
92 next += step;
93 (void) snprintf(text, sizeof(text), "%d", next);
94 gdImageString(im, gdFontLarge, 0, 0, (unsigned char *)text, black);
97 static gdImagePtr InitImage(void)
99 gdImagePtr im;
101 im = gdImageCreate(150, 350);
102 allocate_colors(im);
103 gdImageColorTransparent (im, grey);
104 gdImageFilledRectangle (im, 0, 0, 150, 350, grey);
105 gdImageFilledRectangle (im, 50, 0, 150, 300, green);
107 return im;
111 void parsearg(const char *var, const char *value)
113 if (strcmp(var, "display") == 0) {
114 strncpy (mycmd, value, sizeof(mycmd));
115 mycmd[sizeof(mycmd) - 1] = '\0';
117 } else if (strcmp(var, "value") == 0) {
118 strncpy (upsval, value, sizeof(upsval));
119 upsval[sizeof(upsval) - 1] = '\0';
121 } else if (strcmp(var, "value2") == 0) {
122 strncpy (upsval2, value, sizeof(upsval2));
123 upsval2[sizeof(upsval2) - 1] = '\0';
125 } else if (strcmp(var, "value3") == 0) {
126 strncpy (upsval3, value, sizeof(upsval3));
127 upsval3[sizeof(upsval3) - 1] = '\0';
132 static void imgheader (void)
134 #ifdef SYS_IMGFMT_PNG
135 puts ("Content-Type: image/png");
136 #else
137 puts ("Content-Type: image/gif");
138 #endif
140 * Since this image is generated based on the parameters passed in
141 * the URL, caching is acceptable. No need for Cache-Control.
143 puts ("");
146 static void TermImage(gdImagePtr im)
148 DrawTickLines(im);
149 imgheader();
150 #ifdef SYS_IMGFMT_PNG
151 gdImagePng (im, stdout);
152 #else
153 gdImageGif (im, stdout);
154 #endif
155 gdImageDestroy (im);
158 static void drawbattcap(const char *battcaps, const char *minbchgs)
160 gdImagePtr im;
161 char batttxt[16];
162 int battpos;
163 double battcap;
164 int minbchgpos;
165 double minbchg;
167 battcap = strtod(battcaps, NULL);
168 minbchg = strtod(minbchgs, NULL);
170 im = InitImage();
172 DrawText(im, 0, 20);
174 minbchgpos = (int)(300 - (minbchg * 3));
175 gdImageFilledRectangle(im, 50, minbchgpos, 150, 300, red);
177 battpos = (int)(300 - (battcap * 3));
178 gdImageFilledRectangle(im, 75, battpos, 125, 300, black);
180 (void) snprintf(batttxt, sizeof(batttxt), "%.1f %%", battcap);
181 gdImageString(im, gdFontLarge, 70, 320, (unsigned char *)batttxt, black);
183 TermImage(im);
186 static void drawbattvolt(const char *battvolts, const char *nombattvs)
188 gdImagePtr im;
189 char batttxt[16];
190 int battpos;
191 int hipos, lowpos;
192 double battvolt;
193 double nombattv;
194 double hip, lowp; /* hi and low red line conditions */
195 int minv, maxv, deltav;
197 im = InitImage();
199 battvolt = strtod(battvolts, NULL);
200 nombattv = strtod(nombattvs, NULL);
202 /* NOTE, if you tweek minv and maxv, ensure that the difference
203 * is evenly divisible by 5 or the scales will be wrong!!!
205 switch ((int)nombattv) {
206 case 12:
207 minv = 3;
208 maxv = 18;
209 hip = 12 + 3; /* high redline -- guess */
210 lowp = 12 - 3; /* low redline -- guess */
211 break;
212 case 24:
213 minv = 15;
214 maxv = 30;
215 hip = 24 + 5;
216 lowp = 24 - 5;
217 break;
218 case 48:
219 minv = 30;
220 maxv = 60;
221 hip = 48 + 7;
222 lowp = 48 - 7;
223 break;
224 default:
225 minv = 0;
226 maxv = (int)(battvolt/10 + 1) * 10;
227 hip = battvolt + 5;
228 lowp = battvolt - 5;
229 break;
231 deltav = maxv - minv;
233 DrawText(im, minv, (deltav)/5);
236 /* Do proper scaling of battery voltage and redline positions */
237 battpos = (int)(300 - (((battvolt - minv) / deltav ) * 300));
238 hipos = (int)( 300 - (((hip - minv) / deltav) * 300) );
239 lowpos = (int)( 300 - (((lowp - minv) / deltav) * 300) );
241 gdImageFilledRectangle (im, 50, 0, 150, hipos, red);
242 gdImageFilledRectangle (im, 50, lowpos, 150, 300, red);
245 gdImageFilledRectangle (im, 75, battpos, 125, 300, black);
247 (void) snprintf (batttxt, sizeof(batttxt), "%.1f VDC", battvolt);
248 gdImageString(im, gdFontLarge, 70, 320, (unsigned char *)batttxt, black);
250 TermImage(im);
253 #if 0
254 static void noimage (void)
256 gdImagePtr im;
258 im = gdImageCreate (150, 350);
260 allocate_colors(im);
262 gdImageColorTransparent (im, grey);
264 gdImageFilledRectangle (im, 0, 0, 150, 300, grey);
266 gdImageString (im, gdFontLarge, 0, 0, (unsigned char *)"Data not available", black);
268 imgheader();
269 #ifdef SYS_IMGFMT_PNG
270 gdImagePng (im, stdout);
271 #else
272 gdImageGif (im, stdout);
273 #endif
274 gdImageDestroy (im);
276 #endif
278 static void drawupsload(const char *upsloads)
280 gdImagePtr im;
281 char loadtxt[16];
282 int loadpos;
283 double upsload;
285 upsload = strtod(upsloads, NULL);
287 im = InitImage();
289 DrawText(im, 0, 25);
291 gdImageFilledRectangle (im, 50, 0, 150, 60, red);
292 gdImageFilledRectangle (im, 50, 60, 150, 300, green);
294 loadpos = (int)(300 - ((upsload / 125) * 300));
295 gdImageFilledRectangle(im, 75, loadpos, 125, 300, black);
297 (void) snprintf(loadtxt, sizeof(loadtxt), "%.1f %%", upsload);
298 gdImageString(im, gdFontLarge, 70, 320, (unsigned char *)loadtxt, black);
300 TermImage(im);
304 * Input Voltage */
305 static void drawutility (const char *utilitys, const char *translos,
306 const char *transhis)
308 gdImagePtr im;
309 char utiltxt[16];
310 int utilpos, translopos, transhipos;
311 double utility, translo, transhi;
312 int minv, deltav;
314 utility = strtod(utilitys, NULL);
315 translo = strtod(translos, NULL);
316 transhi = strtod(transhis, NULL);
318 im = InitImage();
320 if (utility > 180) { /* Europe 230V */
321 minv = 200;
322 deltav = 75;
323 } else if (utility > 110) { /* US 110-120 V */
324 minv = 90;
325 deltav = 50;
326 } else if (utility > 95) { /* Japan 100V */
327 minv = 80;
328 deltav = 50;
329 } else { /* No voltage */
330 minv = 0;
331 deltav = 50;
334 DrawText(im, minv, deltav/5);
335 utilpos = (int)(300 - (((utility - minv) / deltav) * 300) );
336 translopos = (int)(300 - (((translo - minv) / deltav) * 300) );
337 transhipos = (int)(300 - (((transhi - minv) / deltav) * 300) );
339 gdImageFilledRectangle(im, 50, 0, 150, transhipos, red);
340 gdImageFilledRectangle(im, 50, translopos, 150, 300, red);
342 gdImageFilledRectangle (im, 75, utilpos, 125, 300, black);
344 (void) snprintf (utiltxt, sizeof(utiltxt), "%.1f VAC", utility);
345 gdImageString (im, gdFontLarge, 65, 320, (unsigned char *)utiltxt, black);
347 TermImage(im);
351 * Output Voltage
353 static void drawupsout (const char *upsouts)
355 gdImagePtr im;
356 char utiltxt[16];
357 int uoutpos;
358 double upsout;
359 int minv, deltav;
361 upsout = strtod(upsouts, NULL);
363 im = InitImage();
365 if (upsout > 180) {
366 minv = 200;
367 deltav = 75;
368 } else if (upsout > 110) {
369 minv = 90;
370 deltav = 50;
371 } else if (upsout > 95) {
372 minv = 80;
373 deltav = 50;
374 } else {
375 minv = 0;
376 deltav = 50;
379 DrawText(im, minv, deltav/5);
380 uoutpos = (int)(300 - (((upsout - minv) / deltav) * 300) );
382 gdImageFilledRectangle(im, 75, uoutpos, 125, 300, black);
384 (void) snprintf(utiltxt, sizeof(utiltxt), "%.1f VAC", upsout);
385 gdImageString(im, gdFontLarge, 65, 320, (unsigned char *)utiltxt, black);
387 TermImage(im);
390 static void drawruntime (const char *upsrunts, const char *lowbatts)
392 gdImagePtr im;
393 char utiltxt[16];
394 int uoutpos, lowbattpos;
395 double upsrunt;
396 double lowbatt;
397 int step, maxt;
399 upsrunt = strtod(upsrunts, NULL);
400 lowbatt = strtod(lowbatts, NULL);
402 im = InitImage();
404 step = (int)(upsrunt + 4) / 5;
405 if (step <= 0)
406 step = 1; /* make sure we have a positive step */
407 DrawText(im, 0, step);
409 maxt = step * 5;
410 uoutpos = 300 - (int)(upsrunt * 300 ) / maxt;
411 lowbattpos = 300 - (int)(lowbatt * 300) / maxt;
413 gdImageFilledRectangle(im, 50, lowbattpos, 150, 300, red);
415 gdImageFilledRectangle(im, 75, uoutpos, 125, 300, black);
417 (void) snprintf(utiltxt, sizeof(utiltxt), "%.1f mins", upsrunt);
418 gdImageString(im, gdFontLarge, 65, 320, (unsigned char *)utiltxt, black);
420 TermImage(im);
424 int main (int argc, char **argv)
426 #ifdef WIN32
427 setmode(fileno(stdout), O_BINARY);
428 #endif
430 (void) extractcgiargs();
432 if (strcmp(mycmd, "upsload") == 0) {
433 drawupsload(upsval);
435 } else if (strcmp(mycmd, "battcap") == 0) {
436 drawbattcap(upsval, upsval2);
438 } else if (strcmp(mycmd, "battvolt") == 0) {
439 drawbattvolt(upsval, upsval2);
441 } else if (strcmp(mycmd, "utility") == 0) {
442 drawutility(upsval, upsval2, upsval3);
444 } else if (strcmp(mycmd, "outputv") == 0) {
445 drawupsout(upsval);
447 } else if (strcmp(mycmd, "runtime") == 0) {
448 drawruntime(upsval, upsval2);
450 } else {
451 puts("Status: 400 Bad request");
452 puts("Content-Type: text/plain; charset=utf-8\n");
453 puts("400 Bad request");
454 exit(EXIT_FAILURE);
456 exit(EXIT_SUCCESS);