Tuesday, 21 June 2016
Sunday, 5 June 2016
Technology - or, how I learned to stop worrying and spread happiness
Now seems like a pretty good time to restart this blog. I'm less than two weeks from embarking on my greatest adventure yet - moving to San Francisco - and I'm sure that, looking back, I'll want to have a better record of that time than blurry pictures and meta-referential tweets. Plus, it will hopefully provide a means of reconnection to the folks back home, and an opportunity to practice the type of writing that isn't overly concerned with bracket-placement and semi-colons.
Monday, 16 March 2015
A Community Carol
T'was the night before Sixmas, when all through the Net,
Not a download was stirring - it hadn't launched yet.
The browsers were pointed at Yahoo with care,
In hopes that Community soon would be there.
Not a download was stirring - it hadn't launched yet.
The browsers were pointed at Yahoo with care,
In hopes that Community soon would be there.
Friday, 23 January 2015
Jarvis, Mk. I Alpha
I've always been a bit of a sucker for the idea of home automation, but have never got around to investing in any of the hardware necessary to make it a reality. This evening, though, I thought it would be rather near to set a process running on my Pi that would be aware of my presence, as a "hook" on which to hang future actions should I invest in such everyday essentials as, say, Internet-connected lightbulbs.
The obvious "input" would be to switch behaviour based on whether my phone was connected to Home WiFi or not. Handily, I can set a static IP for my phone, so this can be easily ping'd.
As a first stab, I tried the following (as jarvis.py, naturally):
#!/usr/bin/env python
import subprocess
PHONE_IP = '192.168.0.6'
def isHome():
with open(subprocess.os.devnull,'w') as DEVNULL:
output = subprocess.Popen(["fping","-c","1",PHONE_IP],stdout=DEVNULL,stderr=DEVNULL,shell=False)
output.communicate()
return output.returncode == 0
def main():
wasHome = True
while True:
homeness = isHome()
if wasHome != homeness:
print 'state changed to ' + str(homeness)
wasHome = homeness
if __name__ == '__main__':
main()
This ran into a problem, though - ping, though pretty reliable, isn't guaranteed to succeed. I was getting false positives all over the place. I introduced a "buffering" system in the next iteration, as well as an actual action to be taken (emailing myself a "Welcome Home!" note, via mutt)
#!/usr/bin/env python
import subprocess
PHONE_IP = '192.168.0.6'
CACHING_LEVEL = 3
def isHome():
with open(subprocess.os.devnull,'w') as DEVNULL:
output = subprocess.Popen(["fping","-c","1",PHONE_IP],stdout=DEVNULL,stderr=DEVNULL,shell=False)
output.communicate()
return output.returncode == 0
def onHomenessChange(homeness):
if homeness:
p1 = subprocess.Popen(['echo'],stdout=subprocess.PIPE)
p2 = subprocess.Popen(['mutt','-s','Welcome home!','scubbojj@gmail.com'],stdin=p1.stdout, stdout=subprocess.PIPE)
p2.communicate()
def main():
previousHomenessState = True
cachedHomenessStates = [True]*CACHING_LEVEL
while True:
homeness = isHome()
cachedHomenessStates = cachedHomenessStates[1:] + [homeness]
if previousHomenessState != homeness and (not any(cachedHomenessStates) if previousHomenessState else all(cachedHomenessStates)):
onHomenessChange(homeness)
previousHomenessState = homeness
if __name__ == '__main__':
main()
This way, the "change" has to last for CACHING_LEVEL number of pings before it registers. If your ping is regularly blipping out for more than three consecutive attempts, well, you've probably got bigger problems on your hands.
I'm pretty proud of the if clause in main(), which checks that:
The obvious "input" would be to switch behaviour based on whether my phone was connected to Home WiFi or not. Handily, I can set a static IP for my phone, so this can be easily ping'd.
As a first stab, I tried the following (as jarvis.py, naturally):
#!/usr/bin/env python
import subprocess
PHONE_IP = '192.168.0.6'
def isHome():
with open(subprocess.os.devnull,'w') as DEVNULL:
output = subprocess.Popen(["fping","-c","1",PHONE_IP],stdout=DEVNULL,stderr=DEVNULL,shell=False)
output.communicate()
return output.returncode == 0
def main():
wasHome = True
while True:
homeness = isHome()
if wasHome != homeness:
print 'state changed to ' + str(homeness)
wasHome = homeness
if __name__ == '__main__':
main()
This ran into a problem, though - ping, though pretty reliable, isn't guaranteed to succeed. I was getting false positives all over the place. I introduced a "buffering" system in the next iteration, as well as an actual action to be taken (emailing myself a "Welcome Home!" note, via mutt)
#!/usr/bin/env python
import subprocess
PHONE_IP = '192.168.0.6'
CACHING_LEVEL = 3
def isHome():
with open(subprocess.os.devnull,'w') as DEVNULL:
output = subprocess.Popen(["fping","-c","1",PHONE_IP],stdout=DEVNULL,stderr=DEVNULL,shell=False)
output.communicate()
return output.returncode == 0
def onHomenessChange(homeness):
if homeness:
p1 = subprocess.Popen(['echo'],stdout=subprocess.PIPE)
p2 = subprocess.Popen(['mutt','-s','Welcome home!','scubbojj@gmail.com'],stdin=p1.stdout, stdout=subprocess.PIPE)
p2.communicate()
def main():
previousHomenessState = True
cachedHomenessStates = [True]*CACHING_LEVEL
while True:
homeness = isHome()
cachedHomenessStates = cachedHomenessStates[1:] + [homeness]
if previousHomenessState != homeness and (not any(cachedHomenessStates) if previousHomenessState else all(cachedHomenessStates)):
onHomenessChange(homeness)
previousHomenessState = homeness
if __name__ == '__main__':
main()
This way, the "change" has to last for CACHING_LEVEL number of pings before it registers. If your ping is regularly blipping out for more than three consecutive attempts, well, you've probably got bigger problems on your hands.
I'm pretty proud of the if clause in main(), which checks that:
- the latest "homeness" value is different from the oldest recorded one, and that
- all the recorded "homeness" values (except the oldest one) are the same - I could have achieved the same with something like reduce(lambda x, y: x and y, [cachedHomenessStates[i] == cachedHomenessStates[i+1] for i in range(len(cachedHomenessStates) - 1)]), which would arguably have been more readable and less clever, but I couldn't not use this once I'd thought of it!
But wait! When you close the ssh connection, this process will end! Never fear, nohup is here. Simply run nohup ./jarvis.py & and your process will merrily run until the end of time - the appended & sends the process into the background, and nohup means the process keeps running even after receiving the "hang-up" signal (sent by a disconnected ssh session).
For my next trick, I'll re-establish my torrent server, and set it to only be downloading when I'm not around and wanting my precious bandwidth. Anything else I should implement?
Still got a ways to go yet
Wednesday, 5 November 2014
Tuesday, 21 October 2014
Sunday, 21 September 2014
A fresh install, a fresh start...
Thanks to a sketchy WiFi card, I was recently issued with a new work laptop. This provided a great prompt for a quasi-companion-piece to George's recent "What's in the bag" blog post - a run-down of all the software, apps, and plugins that I installed on a "bare" machine (with obvious disclaimer that Mac OSX is hardly "bare")
Subscribe to:
Posts (Atom)