shack open/close monitor

das open/close-monitoring basiert auf der annahme, dass die shack-tuere nur unverschlossen ist, wenn der shack geoeffnet ist.

abstract

der server erhaelt einen cron-job der alle 2 minuten ein cgi-script auf einem webserver aufruft, das wiederum eine flag-datei schreibt. auf dem webserver wird jede minute geprueft, ob diese datei aelter als 3 minuten ist, in diesem falle wird sie geloescht.

das cgi-script gibt bei aufruf ohne parameter ein pixel als gif zurueck, das abhaengig von der existenz der flagdatei gruen (vorhanden) oder rot (fehlt) ist.

dieses pixel wird vergroessert aus der passenden wiki-seite heraus aufgerufen

weiter kann der status als text auf deutsch und english abgefragt werden

die anzeige ist somit auf 2 minuten genau

trafficabschaetzung

ein simpler http-request der form

GET /sopen/******************************** HTTP/1.0\r\nHost: shackspace.de\r\n\r\n

ergibt:

- 899 Byte/Rq.
- 647.280 KiB/d
- 20.065680 MiB/m

fuer wurschtkaes 20mb im monat hat man den status auf 2 minuten genau.

messung: exemplarischer traffic mit tcpdump beobachtet, 32 '*' in der uri

details & implementierung

in der tuerzarge ist in die oeffnung fuer den schliessriegel ein reedkontakt mit expoxidharz eingeklebt. in den schliessriegel ist ein magnet eingearbeitet. vom reedkontakt fuehrt eine zweidrahtleitung zur naechsten cat5-dose im lager. das andere ende der leitung ist mit einem cisco-consolekabel ueber einen usb-rs232-adaper mit einem rechner verbunden. benutzt werden dabei nur zwei adern, sie verbinden RTS und DSR (an sich: beliebige statusleitungen, ausgenommen RI, weil nicht durch das ciscokabel gefuehrt), wenn die tuer abgeschlossen ist. wenn die tuere offen ist, bleiben die leitungen unverbunden.

das programm /usr/local/app/shackdoor/shackdoor setzt RTS und prueft daraufhin DSR. je nach stand des schalters ergibt sich das eine oder andere ergebnis. da aufgrund der etwa 40-50 m leitungslaenge und des bei geoeffneter tuere hohen abschlusswiderstands die signalqualitaet schlecht ist, laesst sich die offene tuer nicht immer eindeutig erkennen. also findet die abfrage einfach 20 mal statt. das ging schneller, als an der verkabelung weitere schaltmittel anzubringen.

shackdoor.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
 
#define STIME 3000000
 
void SetRTS(int fd) {
	int currstat;
	ioctl(fd, TIOCMGET, &currstat);
	currstat |= TIOCM_RTS;
	ioctl(fd, TIOCMSET, &currstat);
}
 
void ResetRTS(int fd) {
	int currstat;
	ioctl(fd, TIOCMGET, &currstat);
	currstat &= ~TIOCM_RTS;
	ioctl(fd, TIOCMSET, &currstat);
}
 
void SetDTR(int fd) {
	int currstat;
	ioctl(fd, TIOCMGET, &currstat);
	currstat |= TIOCM_DTR;
	ioctl(fd, TIOCMSET, &currstat);
}
 
void ResetDTR(int fd) {
	int currstat;
	ioctl(fd, TIOCMGET, &currstat);
	currstat &= ~TIOCM_DTR;
	ioctl(fd, TIOCMSET, &currstat);
}
 
void ClearSerPins(int fd) {
	int currstat = 0;
	ioctl(fd, TIOCMSET, &currstat);
}
 
int GetRI(int fd) {
	int currstat;
	ioctl(fd, TIOCMGET, &currstat);
	return((currstat & TIOCM_RNG)?1:0);
}
 
int GetCD(int fd) {
	int currstat;
	ioctl(fd, TIOCMGET, &currstat);
	return((currstat & TIOCM_CAR)?1:0);
}
 
int GetDSR(int fd) {
	int currstat;
	ioctl(fd, TIOCMGET, &currstat);
	return((currstat & TIOCM_DSR)?1:0);
}
 
int GetCTS(int fd) {
	int currstat;
	ioctl(fd, TIOCMGET, &currstat);
	return((currstat & TIOCM_CTS)?1:0);
}
 
int GetSerStat(int fd) {
	int currstat;
	ioctl(fd, TIOCMGET, &currstat);
	return(currstat);
}
 
int main (int argc, char** argv) {
	int i, stat;
	int fd = 0;
 
	if ( argc != 2 ) {
		printf("usage: %s device\n",argv[0]);
		exit(1);
	}
	if (( fd = open(argv[1], O_RDWR | O_NDELAY )) < 0 ) {
		printf("can't open device '%s'\n",argv[1]);
		exit(2);
	}
 
	SetRTS(fd);
	stat = GetSerStat(fd);
	if ( stat & TIOCM_DSR) puts("DSR ");
	printf("\n");
 
	/* debug 
	for (;;) {
		usleep(100000);
		stat = GetSerStat(fd);
		if ( stat & TIOCM_RNG) puts("RI  ");
		if ( stat & TIOCM_CAR) puts("CAR ");
		if ( stat & TIOCM_DSR) puts("DSR ");
		if ( stat & TIOCM_CTS) puts("CTS ");
		printf("\n");
	}
	*/
	close(fd);
	return(0);
}

der tuerstatus-vserver prueft alle 2 minuten per cronjob den zustand des tuerkontakts:

/etc/cron.d/sopen-shack
0-59/2 * * * * nobody /usr/local/app/shackdoor/sopen-client 2>&1 | logger

sopen-client fragt den zustand der tuere ab und setzt bei geoeffneter tuere einen http-request an shackspace.de ab:

/usr/local/app/shackdoor/sopen-client
#!/bin/bash
 
FLAG=0
for i in {1..20} ; do 
        if [ x`/usr/local/app/shackdoor/shackdoor /dev/ttyUSB0` = xDSR ] ; then
                FLAG=$(( $FLAG + 1 )) 
        fi
done
 
if [ "$FLAG" = 0 ] ; then
         echo -e -n "GET /sopen/************ HTTP/1.0\r\nHost: shackspace.de\r\n\r\n" | nc shackspace.de 80
fi

da die erkennung der dsr-leitung nicht in jedem falle funktioniert, wird sie mehrfach abgefragt. moegliche ursache koennte evtl. die leitungslaenge sein.

auf shackspace.de

sopen ist ein CGI und wurde als /var/www/shackspace.de/htdocs/sopen abgelegt:

sopen
#!/usr/bin/perl -Tw
# Thu Nov 29 17:52:13 CET 2012, chris
# - Doku hier:
# - http://shackspace.de/wiki/doku.php?id=shack_open_close_monitor
 
use strict;
 
my $uri = "/sopen/************";
my $uri_text_de = "/sopen/text/de";
my $uri_text_en = "/sopen/text/en";
my $uri_img_png = "/sopen/img/png";
my $uri_img_gif = "/sopen/img/gif";
my $uri_imgtxt_png = "/sopen/imgtxt/en/png";
my $uri_imgtxt_gif = "/sopen/imgtxt/en/gif";
my $statfilename = "/var/run/sopen/stat";
my $trackfilenameon = "/var/run/sopen/track-on";
my $trackfilenameoff = "/var/run/sopen/track-off";
 
# strip trailing ?...
my $request_uri = (split(/\?/,$ENV{REQUEST_URI}))[0];
 
# korrekte uri setzt flag file
$request_uri eq $uri and do {
	open F,">".$statfilename or die "can't open '$statfilename': $!";
	print F time ,"\n";
	close F;
	-e $trackfilenameon or do {
		open F,">".$trackfilenameon or die "can't open '$trackfilenameon': $!";
		print F time ,"\n";
		close F;
	};
	-e $trackfilenameoff and do {
		unlink $trackfilenameoff;
	};
 
	print "Content-Type: text/plain\n\n1\n";
	exit;
};
# else if
$request_uri eq $uri_text_de and do {
	print "Content-Type: text/plain\n\n";
	-f $statfilename and do {
		print "offen\n";
	} or do { 
		print "geschlossen\n";
	};
	exit;
};
# else if
$request_uri eq $uri_text_en and do {
	print "Content-Type: text/plain\n\n";
	-f $statfilename and do {
		print "open\n";
	} or do { 
		print "closed\n";
	};
	exit;
};
# else if
$request_uri eq $uri_img_png and do {
	print "Content-Type: image/png\n\n";
	-f $statfilename and do {
		# pixel gruen
		print 
			"\211\120\116\107\15\12\32\12\0\0\0\15\111\110\104\122\0\0\0\1\0",
			"\0\0\1\1\3\0\0\0\45\333\126\312\0\0\0\4\147\101\115\101\0\0\261",
			"\217\13\374\141\5\0\0\0\3\120\114\124\105\0\377\0\64\136\300",
			"\250\0\0\0\70\164\105\130\164\123\157\146\164\167\141\162\145",
			"\0\130\126\40\126\145\162\163\151\157\156\40\63\56\61\60\141\40",
			"\40\122\145\166\72\40\61\62\57\62\71\57\71\64\40\50\120\116\107",
			"\40\160\141\164\143\150\40\61\56\62\51\335\25\56\111\0\0\0\12",
			"\111\104\101\124\170\234\143\140\0\0\0\2\0\1\110\257\244\161",
			"\0\0\0\7\164\111\115\105\7\333\13\27\7\64\73\1\135\24\55\0\0\0",
			"\0\111\105\116\104\256\102\140\202";
	} or do { 
		# pixel rot
		print
			"\211\120\116\107\15\12\32\12\0\0\0\15\111\110\104\122\0\0\0\1\0",
			"\0\0\1\1\3\0\0\0\45\333\126\312\0\0\0\4\147\101\115\101\0\0\261",
			"\217\13\374\141\5\0\0\0\3\120\114\124\105\377\0\0\31\342\11\67\0",
			"\0\0\70\164\105\130\164\123\157\146\164\167\141\162\145\0\130\126",
			"\40\126\145\162\163\151\157\156\40\63\56\61\60\141\40\40\122\145",
			"\166\72\40\61\62\57\62\71\57\71\64\40\50\120\116\107\40\160\141",
			"\164\143\150\40\61\56\62\51\335\25\56\111\0\0\0\12\111\104\101",
			"\124\170\234\143\140\0\0\0\2\0\1\110\257\244\161\0\0\0\7\164\111",
			"\115\105\7\333\13\27\7\65\17\71\362\321\331\0\0\0\0\111\105\116",
			"\104\256\102\140\202";
	};
	exit;
};
# else if
$request_uri eq $uri_imgtxt_png and do {
	print "Content-Type: image/png\n\n";
	-f $statfilename and do {
		# image text gruen
		print 
			"\211\120\116\107\15\12\32\12\0\0\0\15\111\110",
			"\104\122\0\0\0\57\0\0\0\25\10\3\0\0",
			"\0\341\30\107\125\0\0\0\140\120\114\124\105\77",
			"\277\140\7\367\13\0\376\0\5\371\11\14\362\22",
			"\23\353\35\27\347\44\25\351\40\31\345\46\33\343",
			"\52\47\327\74\41\335\63\45\331\70\50\326\76\54",
			"\322\103\61\315\113\71\305\127\73\303\132\102\274\145",
			"\110\266\157\116\260\167\122\254\176\127\247\206\130\246",
			"\206\133\243\214\136\240\220\141\235\225\144\232\231\150",
			"\226\237\157\217\252\154\222\245\160\217\253\370\234\167",
			"\162\0\0\0\355\111\104\101\124\170\332\325\222\315",
			"\162\303\40\14\204\15\210\26\203\377\222\206\70\266",
			"\43\351\375\337\62\22\156\153\174\354\55\325\1\326",
			"\322\67\73\153\15\215\375\133\65\357\312\207\344\313",
			"\355\14\230\135\200\201\242\335\376\155\134\305\307\47",
			"\63\56\101\324\225\21\171\351\144\42\2\361\41\2",
			"\107\105\356\363\301\367\230\3\164\13\5\235\246\64",
			"\314\350\105\304\276\357\223\166\264\157\347\203\167\124",
			"\264\331\344\152\110\224\347\161\27\5\241\165\3\153",
			"\363\301\47\214\145\62\261\331\61\340\111\154\103\10",
			"\255\121\376\223\362\311\277\347\217\302\17\45\206\163",
			"\160\343\126\362\113\251\221\70\14\174\261\371\376\313",
			"\7\36\12\177\45\47\274\374\57\136\24\3\51\247",
			"\371\165\13\135\305\333\165\325\235\171\272\51\26\243",
			"\246\250\363\313\361\240\265\332\117\240\155\214\23\255",
			"\120\143\70\152\175\167\340\311\25\157\175\106\246\57",
			"\70\331\112\56\106\372\351\264\47\136\267\371\136\357",
			"\355\237\362\57\123\170\25\154\160\141\302\111\0\0",
			"\0\0\111\105\116\104\256\102\140\202",
			;
		#perl -e '$/="";$c=0;for (split //,<>) { printf "\\%o",ord($_); ++$c%14 or print "\n"}' ~chris/open.png
	} or do { 
		# image text rot
		print
			"\211\120\116\107\15\12\32\12\0\0\0\15\111\110",
			"\104\122\0\0\0\100\0\0\0\25\10\3\0\0",
			"\0\301\364\30\250\0\0\0\132\120\114\124\105\377",
			"\0\0\377\13\13\377\24\24\377\31\31\377\41\41",
			"\377\53\53\377\63\63\377\73\73\377\104\104\377\112",
			"\112\377\124\124\377\133\133\377\145\145\377\153\153\377",
			"\161\161\377\203\203\377\213\213\377\220\220\377\232\232",
			"\377\243\243\377\263\263\377\274\274\377\307\307\377\313",
			"\313\377\324\324\377\334\334\377\344\344\377\353\353\377",
			"\363\363\377\374\374\46\155\212\6\0\0\1\44\111",
			"\104\101\124\170\332\355\122\111\266\204\40\14\4\34",
			"\160\150\301\131\132\250\373\137\363\47\212\266\372\372",
			"\0\177\321\265\200\172\41\103\205\104\210\37\116\344",
			"\145\116\247\114\116\203\56\263\73\223\11\103\155\104",
			"\311\107\170\355\1\274\265\150\161\65\70\115\54\173",
			"\107\326\201\261\104\342\232\133\74\226\132\327\156\242",
			"\267\303\60\25\111\351\2\251\32\103\231\126\23\51",
			"\153\121\23\112\116\120\125\315\210\341\23\57\375\302",
			"\222\244\24\135\330\15\141\346\53\361\124\317\271\350",
			"\165\44\217\304\242\70\23\24\250\357\116\45\52\261",
			"\73\51\321\143\66\331\376\246\11\112\304\76\45\354",
			"\245\3\35\131\33\156\206\27\50\324\322\167\354\55",
			"\60\50\163\224\31\372\213\202\346\256\100\343\265\335",
			"\75\266\337\316\73\156\270\103\232\46\251\74\234\324",
			"\105\201\130\75\217\57\127\347\24\326\267\342\1\204",
			"\221\222\61\163\263\370\114\150\47\75\162\161\221\340",
			"\155\323\123\231\16\206\40\111\302\152\52\33\326\204",
			"\76\330\333\272\105\313\205\115\143\114\263\21\143\27",
			"\66\135\326\150\2\174\257\342\254\111\116\76\2\141",
			"\140\135\31\61\14\362\330\3\354\304\117\325\143\225",
			"\244\172\356\246\372\302\176\370\237\370\3\237\327\25",
			"\353\351\254\364\365\0\0\0\0\111\105\116\104\256",
			"\102\140\202",
			;
		# perl -e '$/="";$c=0;for (split //,<>) { printf "\\%o",ord($_); ++$c%14 or print "\",\n\t\t\t\""}' ~chris/closed.png
	};
	exit;
};
# else if
$request_uri eq $uri_imgtxt_gif and do {
	print "Content-Type: image/gif\n\n";
	-f $statfilename and do {
		# image text gruen
		print 
			"\107\111\106\70\71\141\57\0\25\0\365\46\0\77",
			"\277\140\7\367\13\0\376\0\5\371\11\11\365\16",
			"\14\362\22\23\353\35\27\347\44\25\351\40\31\345",
			"\46\33\343\52\47\327\74\41\335\63\45\331\70\50",
			"\326\76\57\317\110\54\322\103\61\315\113\66\310\123",
			"\71\305\127\73\303\132\117\257\172\102\274\145\106\270",
			"\153\110\266\157\116\260\167\122\254\176\127\247\206\125",
			"\251\202\130\246\206\133\243\214\136\240\220\141\235\225",
			"\144\232\231\150\226\237\157\217\252\154\222\245\156\220",
			"\250\160\217\253\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\41\371\4\0\0",
			"\0\0\0\54\0\0\0\0\57\0\25\0\0\6",
			"\376\100\201\100\40\20\10\4\2\201\100\40\20\10",
			"\4\2\201\100\40\20\10\4\2\201\100\40\20\10",
			"\4\2\201\100\40\20\10\4\2\201\100\40\20\10",
			"\4\2\201\100\40\20\10\4\2\201\100\40\20\10",
			"\200\2\201\100\40\20\10\4\2\201\100\40\20\10",
			"\4\2\201\100\40\20\10\4\2\201\100\40\20\10",
			"\4\2\201\100\40\20\10\4\2\201\100\40\20\10",
			"\4\2\201\100\40\20\10\4\2\201\100\40\20\0",
			"\5\2\201\100\40\20\10\4\2\201\100\40\20\10",
			"\4\2\201\100\40\20\10\4\2\201\100\40\20\10",
			"\4\2\201\100\40\20\10\4\2\201\100\40\20\10",
			"\4\2\201\100\40\20\10\4\2\201\100\40\0\12",
			"\4\2\201\100\40\20\10\4\11\206\101\40\20\10",
			"\4\203\100\41\40\20\10\4\202\101\41\120\10\24",
			"\2\2\301\40\40\20\10\4\202\300\100\40\20\10",
			"\4\2\201\100\40\130\210\114\246\321\47\1\24\10",
			"\4\26\323\150\144\372\64\4\2\200\151\64\32\215",
			"\74\2\1\140\24\21\10\4\202\115\107\40\20\10",
			"\4\2\201\376\100\340\30\151\22\205\306\207\224\20",
			"\10\0\43\6\3\322\31\31\4\200\321\2\350\160",
			"\70\30\2\1\140\104\112\10\4\202\116\107\40\20",
			"\10\4\2\201\140\100\352\10\4\2\101\40\324\21",
			"\10\0\44\201\100\140\60\105\4\0\222\100\40\20",
			"\10\4\2\0\11\24\52\10\4\232\16\120\40\20",
			"\10\4\2\201\200\61\132\10\4\2\201\140\142\12",
			"\10\0\44\201\100\120\60\115\4\200\121\42\221\120",
			"\4\4\2\0\11\101\322\10\4\235\216\100\40\20",
			"\10\4\2\201\303\164\20\10\4\2\240\0\62\62",
			"\10\0\243\301\240\220\61\51\4\0\223\311\144\32",
			"\55\4\2\0\111\0\61\121\4\232\215\100\40\20",
			"\10\4\2\101\302\4\21\10\4\2\201\205\64\20",
			"\0\106\243\221\151\104\21\10\0\100\122\241\120\50",
			"\14\4\2\300\110\40\260\230\32\232\215\100\40\20",
			"\10\4\2\201\0\4\12\10\4\2\3\51\43\20",
			"\0\110\213\205\42\40\20\10\0\44\201\100\40\20",
			"\10\4\0\222\100\40\360\220\200\240\216\100\40\20",
			"\10\4\2\201\40\101\376\12\105\26\23\22\250\40",
			"\20\0\110\2\201\100\40\20\10\0\243\110\44\22",
			"\211\10\4\0\222\100\40\50\210\114\35\201\100\40",
			"\20\10\4\2\201\300\240\31\1\115\44\114\101\40",
			"\20\0\110\2\201\100\40\20\10\0\243\221\311\64",
			"\42\11\4\0\222\100\40\20\50\114\35\201\100\40",
			"\20\10\4\2\201\100\40\20\4\4\2\201\100\40",
			"\20\10\4\2\201\100\40\0\12\4\2\201\100\40",
			"\20\10\4\2\201\100\40\20\10\4\2\201\100\40",
			"\20\10\4\2\201\100\40\20\10\4\2\201\100\40",
			"\20\10\4\2\201\100\40\20\10\4\2\201\100\40",
			"\20\10\4\2\201\100\0\24\10\4\2\201\100\40",
			"\20\10\4\2\201\100\40\20\10\4\2\201\100\40",
			"\20\10\4\2\201\100\40\20\10\4\2\201\100\40",
			"\20\10\4\2\201\100\40\20\10\4\2\201\100\40",
			"\20\10\4\2\201\0\50\20\10\4\2\201\100\40",
			"\20\10\4\2\201\100\40\20\10\4\2\201\100\40",
			"\20\10\4\2\201\100\40\20\10\4\2\201\100\40",
			"\20\10\4\2\201\100\40\20\10\165\4\2\201\100",
			"\40\20\10\4\2\1\120\40\20\10\4\2\201\100",
			"\40\20\10\4\2\201\100\40\20\10\4\2\201\100",
			"\40\20\10\4\2\201\100\40\20\10\4\2\201\100",
			"\40\20\10\4\2\201\100\40\20\10\4\2\201\100",
			"\40\20\10\4\2\240\100\40\20\10\4\2\201\100",
			"\40\20\10\4\2\201\100\40\20\10\4\2\201\100",
			"\40\20\10\4\2\201\100\40\20\10\4\2\201\100",
			"\40\20\10\4\2\201\100\40\20\10\4\2\201\40",
			"\10\0\73",
			;
		# perl -e '$/="";$c=0;for (split //,<>) { printf "\\%o",ord($_); ++$c%14 or print "\",\n\t\t\t\""}' ~chris/open.gif
	} or do { 
		# image text rot
		print
			"\107\111\106\70\71\141\100\0\25\0\364\35\0\377",
			"\0\0\377\13\13\377\24\24\377\31\31\377\41\41",
			"\377\53\53\377\63\63\377\73\73\377\104\104\377\112",
			"\112\377\124\124\377\133\133\377\145\145\377\153\153\377",
			"\161\161\377\203\203\377\213\213\377\220\220\377\232\232",
			"\377\243\243\377\263\263\377\274\274\377\307\307\377\313",
			"\313\377\324\324\377\334\334\377\344\344\377\353\353\377",
			"\363\363\377\374\374\0\0\0\0\0\0\41\371\4",
			"\0\0\0\0\0\54\0\0\0\0\100\0\25\0",
			"\0\5\376\40\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\200\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\2\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\10\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\40\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\200\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\2\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\10\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\40\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\200\221\30",
			"\0\0\200\301\0\0\0\0\0\0\0\34\111\1",
			"\0\0\0\0\300\221\24\0\0\0\301\0\16\303",
			"\60\10\0\20\14\203\20\0\0\0\0\0\0\0",
			"\0\0\0\300\262\376\165\35\330\145\7\0\165\0",
			"\0\0\0\0\54\133\327\165\330\1\0\100\221\165",
			"\135\207\35\40\0\104\135\327\165\335\5\0\121\327",
			"\165\35\326\0\0\0\0\0\0\0\0\260\200\335",
			"\265\34\13\126\1\121\7\0\0\0\0\113\127\41",
			"\103\202\161\6\0\120\134\2\22\112\65\0\0\324",
			"\55\313\262\44\0\20\165\212\322\120\335\4\0\0",
			"\0\0\0\10\0\301\166\5\0\0\4\1\20\161",
			"\0\0\0\100\300\131\0\0\0\303\166\1\40\200",
			"\141\0\0\0\0\0\104\35\0\0\0\0\0\121",
			"\7\0\0\360\164\10\0\200\0\0\0\0\200\164",
			"\13\0\0\0\0\0\121\7\0\0\0\44\235\2",
			"\0\0\0\2\117\47\0\122\147\71\5\0\0\100",
			"\324\35\307\161\10\0\0\165\0\0\0\1\330\75",
			"\0\0\0\0\0\0\113\167\0\0\0\0\0\0",
			"\161\0\0\0\300\322\35\40\0\0\0\300\164\5",
			"\0\74\133\327\125\3\0\100\135\327\165\235\2\0",
			"\21\7\200\0\0\0\234\4\0\0\0\0\0\200",
			"\164\15\0\0\0\0\0\121\376\7\0\0\0\2",
			"\107\307\0\0\0\0\122\27\0\0\0\30\121\67",
			"\1\100\324\21\304\100\4\0\10\104\35\0\0\200",
			"\320\75\0\0\0\0\0\0\200\266\15\0\0\30",
			"\2\0\165\40\0\0\0\0\150\231\0\0\100\301",
			"\121\0\160\10\0\0\140\26\0\100\35\0\200\0",
			"\0\0\0\324\1\0\0\110\235\1\0\0\0\0",
			"\0\0\40\335\366\64\122\7\116\100\324\71\216\343",
			"\4\300\321\151\216\362\160\332\0\4\333\366\54\120",
			"\7\1\0\30\165\116\343\70\15\0\104\235\343\74",
			"\127\7\1\0\0\0\0\0\0\0\140\124\140\327",
			"\155\222\0\104\135\327\165\335\0\0\6\325\165\334",
			"\64\0\0\120\120\135\327\201\123\0\0\121\327\165",
			"\135\327\1\100\324\165\335\126\51\0\0\0\0\0",
			"\0\0\0\2\0\0\4\2\0\0\0\0\0\0",
			"\0\0\0\0\0\200\0\0\0\0\0\0\10\0",
			"\2\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\40\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\376\0\0",
			"\0\0\0\200\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\2",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\10\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\40\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\200\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\2\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\10\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\40\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\200\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\2\0\0\0\0\0\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\10\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
			"\33\0\0\0\0\0\0\0\40\0\0\0\0\0",
			"\0\0\0\0\0\0\0\0\0\0\0\0\100\10",
			"\0\73",
			;
		# perl -e '$/="";$c=0;for (split //,<>) { printf "\\%o",ord($_); ++$c%14 or print "\",\n\t\t\t\""}' ~chris/closed.gif
	};
	exit;
};
# else 
print "Content-Type: image/gif\n\n";
-f $statfilename and do {
	# pixel gruen
	print "GIF87a\001\0\001\0\200\0\0\0\377\0\0\0\0,\0\0\0\0\001\0\001\0\0\002\002D\001\0;";
	exit;
};
# else
# pixel rot
print "GIF87a\001\0\001\0\200\0\0\377\0\0\0\0\0,\0\0\0\0\001\0\001\0\0\002\002D\001\0;";

dieser cronjob wirft /var/run/sopen/stat weg, wenn die datei aelter als 3 minuten ist: /etc/cron.d/sopen:

/etc/cron.d/sopen
* * * * * www-data /usr/bin/perl -e '$s = "/var/run/sopen/stat"; [stat $s]->[9] + 180 < time and unlink $s'

run-verzeichnis angelegt:

mkdir /var/run/sopen
chown www-data:www-data /var/run/sopen

der webserver muss /sopen als cgi starten. ausserdem muss sopen als sopen.gif aufrufbar sein, da dokuwiki sonst anstelle des bildes einen link darstellt.

/etc/apache2/sites-available/20-shackspace.de.conf

ScriptAlias /sopen     /var/www/shackspace.de/htdocs/sopen
ScriptAlias /sopen.gif /var/www/shackspace.de/htdocs/sopen

apache ueber neue config informieren:

/etc/init.d/apache2 reload

im wiki wird es so eingebunden:

{{http://shackspace.de/sopen.gif?20x10}}

oder so:

{{http://shackspace.de/sopen?.gif?20x10}}

und so sieht's dann aus:

anwendung und ausgabeformate

format desc. url sample
gif pixel http://shackspace.de/sopen/img/gif
png pixel http://shackspace.de/sopen/img/png
gif grafische anzeige mit eingerendertem text http://shackspace.de/sopen/imgtxt/en/gif
png grafische anzeige mit eingerendertem text http://shackspace.de/sopen/imgtxt/en/png
ascii[0] deutscher text http://shackspace.de/sopen/text/de offen
ascii[0] english text http://shackspace.de/sopen/text/en closed

[0] als content-type wird „text/plain“ uebermittelt

(idee und drehbuch: chris)

abgeleitete anwendungen

Shackspace offen? (1x1 pixel abfragen)

Autor: Felix

Ein Kommandozeilen-Skript welches den Status des Shacks ( open/close ) anzeigt. Gut auch um persönliche Statistiken zu bauen. Dependencies sind bash, wget, awk, md5sum ( alles core-utils ). Ziel war es die Dependencies und den Footprint so gering wie möglich zu halten.

shack_offen.sh
#!/bin/bash
# author: makefu
# fetch the status from the website
CURR=` wget "http://shackspace.de/sopen.gif" -O - 2>/dev/null | md5sum | awk '{print $1}'`
# reference md5sum of a green 1x1 pixel
REF="d8ced8c4a470ea0098a2b0d7b19c06b2" 
[ "$CURR" == "$REF" ] && echo -e "shack is \e[1;32mOPEN\e[0m" && exit 0
[ "$CURR" != "$REF" ] && echo -e "shack is \e[1;31mCLOSED\e[0m" && exit 1

Shackspace offen? (String abfragen)

Autor: chf

is_shack_open.sh:

is_shack_open.sh
#!/bin/bash
status=$(
            echo -e -n "GET /sopen/text/en HTTP/1.0\r\nHost: shackspace.de\r\n\r\n" |
            nc shackspace.de 80 2>&1 |
            egrep -c "^open$"
        )
 
if [ $status -eq 1 ]; then
    echo -e "Yuhuu, doors are \e[1;32mopen\e[0m! ;-)"
else
    echo -e "Damn, it's \e[1;31mclosed\e[0m."
    exit 1
fi

und um dann gleich informiert zu werden:

while [ 1 ]; do is_shack_open.sh && zenity --info --text="Shack is open" ; sleep 1m; done

!offen im IRC

Autor: cmile

Im IRC einfach !open schreiben und auf die Antwort von Krebsbeam warten.

open.py
# jsb/plugs/common/c-lang.py
# -*- coding: utf-8 -*-
 
## jsb imports
 
from jsb.utils.exception import handle_exception
from jsb.lib.commands import cmnds
from jsb.lib.examples import examples
 
## basic imports
 
import re, urllib
import random
 
## defines
 
## isopen command
 
def handle_isopen(bot, ievent):
    mysock = urllib.urlopen("http://shackspace.de/sopen/text/de")
    ievent.reply(mysock.read())
 
cmnds.add('isopen', handle_isopen, ['OPER', 'USER', 'GUEST'])
cmnds.add('offen', handle_isopen, ['OPER', 'USER', 'GUEST'])
shack_open_close_monitor.txt · Zuletzt geändert: 2012/11/29 19:09 von 82.212.50.234