Plan 9 from Bell Labs’s /usr/web/sources/contrib/nemo/sys/src/cmd/x10/power.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>

enum {
	Hitmout	= 60 * 60,	// power off time out (secs)
	Lotmout = 60,		// lights off
	Ival	= 5,		// check interval (secs)

	// power states
	Sunknown = 0,
	Sidle,	// no who, no pwr
	Son,	// who, pwr
	Stmout,	// pwr timing out
	Nstates,
};

typedef struct Cmd Cmd;
typedef struct State State;
typedef int (*Statef)(Cmd* c, State* s);

struct State {
	vlong	gonetime;
	int	who;
	int	lastwho;
	vlong	now;
};

struct Cmd {
	vlong	gonetime;
	char*	file;
	int	state;
	int	last;
	int	tmout;
	Statef	func[Nstates];
};



int
getx10(char* f)
{
	int	fd;
	char	buf[10];
	int	n;

	fd = open(f, OREAD);
	if (fd < 0)
		return -1;
	n = read(fd, buf, sizeof(buf)-1);
	if (n < 0){
		close(fd);
		return -1;
	}
	buf[n] = 0;
	close(fd);
	if (strcmp(buf, "on") == 0)
		return 1;
	else
		return 0;
}

void
setx10(char* f, char* to)
{
	int	fd;
	int	n;

	if (f == nil)
		return;
	fd = open(f, OWRITE);
	if (fd < 0){
		fprint(2, "%s: error: %s -> %s: %r\n", argv0, f, to);
		syslog(0, "x10a", "%s: open error: %s -> %s: %r\n", argv0, f, to);
		return;
	}
	n = write(fd, to, strlen(to));
	close(fd);
	if (n < 0)
		syslog(0, "x10a", "%s: write error: %s -> %s: %r\n", argv0, f, to);
}

static void
switchdev(char* file, char* what, int tmout)
{
	if (tmout > 0){
		syslog(0, "x10a", "%s: switching %s"
			" %s in %d minutes", argv0, what, file, tmout/60);
	} else {
		syslog(0, "x10a", "%s: switching %s %s now", argv0, what, file);
		setx10(file, what);
		sleep(1000);
	}
}

void
setvol(char* file, int val)
{
	int	fd;
	fd = open(file, OWRITE);
	if (fd < 0)
		return;
		syslog(0, "x10a", "%s: adjusting %s to %d", argv0, file, val);
	fprint(fd, "audio out %d\n", val);
	close(fd);
}

int
getvol(char* file)
{
	char	buf[100];
	int	fd;
	int	n;
	int	l;

	fd = open(file, OREAD);
	if (fd < 0)
		return -1;
	n = read(fd, buf, sizeof(buf)-1);
	close(fd);
	if (n < 0)
		return -1;
	buf[n] = 0;
	l = strlen("audio out ");
	if (strncmp(buf, "audio out ", l) != 0)
		return 70;
	return atoi(buf + l);
}

	

static int 
terminit(Cmd* c, State* s)
{
	if (s->who){
		switchdev(c->file, "on", 0);
		return Son;
	} else {
		s->gonetime = s->now;
		switchdev(c->file, "off", c->tmout);
		return Stmout;
	}
}

static int 
volinit(Cmd* c, State* s)
{
	if (c->last < 0)
		c->last = getvol(c->file);
	if (s->who){
		return Son;
	} else {
		return Stmout;
	}
}

static int 
nvolinit(Cmd* c, State* s)
{
	c->last = getvol(c->file);
	if (s->who){
		if (c->last > 40)
			setvol(c->file, 40);
		return Son;
	} else {
		if (c->last > 0)
			setvol(c->file, c->last);
		return Sidle;
	}
}


static int 
termidle(Cmd* c, State* s)
{
	if (s->who && !s->lastwho){
		switchdev(c->file, "on", 0);
		return Son;
	} else
		return Sidle;
}

static int 
volidle(Cmd* c, State* s)
{
	if (c->last < 0)
		c->last = 70;
	if (s->who && !s->lastwho){
		setvol(c->file, c->last);
		return Son;
	} else
		return Sidle;
}

static int 
nvolidle(Cmd* c, State* s)
{
	if (s->who && !s->lastwho){
		c->last = getvol(c->file);
		if (c->last == 0){
			sleep(1000);
			c->last = getvol(c->file);
		}
		if (c->last > 70)
			setvol(c->file, 70);
		return Son;
	} else
		return Sidle;
}

static int 
termon(Cmd* c, State* s)
{
	if (!s->who && s->lastwho){
		switchdev(c->file, "off", c->tmout);
		return Stmout;
	} else
		return Son;
}

static int 
volon(Cmd* c, State* s)
{
	if (!s->who && s->lastwho){
		c->last = getvol(c->file);
		return Stmout;
	} else
		return Son;
}

static int 
nvolon(Cmd* c, State* s)
{
	if (!s->who && s->lastwho){
		if (c->last == 0){
			c->last = getvol(c->file);
		}
		if (c->last > 0)
			setvol(c->file, c->last);
		return Sidle;
	} else
		return Son;
}

static int 
termtmout(Cmd* c, State* s)
{
	if (s->who && !s->lastwho){
		switchdev(c->file, "on", 0);
		return Son;
	} else if (s->gonetime > 0 && s->now - s->gonetime >= c->tmout){
		switchdev(c->file, "off", 0);
		c->gonetime = 0;	// no more power offs until he cames
		return Sidle;
	} else
		return Stmout;
}

static int 
voltmout(Cmd* c, State* s)
{
	if (s->who && !s->lastwho){
		if (c->last == 0)
			c->last = 70;
		setvol(c->file, c->last);
		return Son;
	} else if (s->gonetime > 0 && s->now - s->gonetime >= c->tmout){
		c->last = getvol(c->file);
		setvol(c->file, 0);
		s->gonetime = 0;	// no mutes until he cames
		return Sidle;
	} else
		return Stmout;
}

Cmd	tcmd = {
	0LL, nil, Sunknown, -1, Hitmout, {terminit,	termidle,	termon,	termtmout}
};
Cmd	lcmd = {
	0LL, nil, Sunknown, -1, Lotmout, {terminit,	termidle,	termon,	termtmout}
};
Cmd	vcmd = {
	0LL, nil, Sunknown, -1, Lotmout, {volinit,	volidle,	volon,	voltmout}
};
Cmd	ncmd = {
	0LL, nil, Sunknown, -1, Lotmout, {nvolinit,	nvolidle,	nvolon,	nil}
};

Cmd	cmds[100];
int	ncmds;

void
usage(void)
{
	fprint(2, "usage: %s "
		"[-t term] [-n vol] [-v vol] [-l light] whofile\n", argv0);
	exits("usage");
}

void
main(int argc, char* argv[])
{
	State	s;
	char*	whof;
	Cmd*	cp;
	int	i;

	ARGBEGIN{
	case 't':
		cmds[ncmds] = tcmd;
		cmds[ncmds].file = EARGF(usage());
		ncmds++;
		break;
	case 'v':
		cmds[ncmds] = vcmd;
		cmds[ncmds].file = EARGF(usage());
		ncmds++;
		break;
	case 'n':
		cmds[ncmds] = ncmd;
		cmds[ncmds].file = EARGF(usage());
		ncmds++;
		break;
	case 'l':
		cmds[ncmds] = lcmd;
		cmds[ncmds].file = EARGF(usage());
		ncmds++;
		break;
	default:
		usage();
	}ARGEND;
	if (argc != 1 || ncmds == 0)
		usage();
	whof = argv[0];

	memset(&s, 0, sizeof(s));
	for(;;){
		sleep(Ival * 1000);

		s.now = time(nil);
		s.lastwho = s.who;
		s.who = getx10(whof);
		if (s.who < 0){
			syslog(0, "x10a", "%s: can't read %s", argv0, whof);
			continue;
		}
		if (s.who != s.lastwho){
			if (s.who){
				for (i = 0; i < ncmds; i++)
					cmds[i].gonetime = 0;
				//syslog(0, "x10a", "%s: %s came", argv0, whof);
				s.gonetime = 0;
			} else {
				for (i = 0; i < ncmds; i++)
					cmds[i].gonetime = s.now;
				//syslog(0, "x10a", "%s: %s gone", argv0, whof);
				s.gonetime = s.now;
			}
		}

		for (i = 0; i < ncmds; i++){
			cp = &cmds[i];
			assert(cp->state >= 0 && cp->state < Nstates);
			cp->state = cp->func[cp->state](cp, &s);
		}
	}
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.