Spacestate Switch
Project: Spacestate Switch | |
---|---|
Status | voltooid |
Betrokkenen | , Failbaitr
Failbaitr Rol: deelnemer Deskundig met: Arduino, CNC, CNC-Frezen, Canvas, Digitale Fabricatie, ENC28J60, Glasvezel lassen, HTML, Hydroponics, Javascript, LPD8806, Linux, Mercurial, Programmeren, Python, Robotica, Software, Stappenmotor Beginnend met: Elektronica Werkt aan: Geen projecten :( |
Kennisgebied(en) | Python
|
Afgeleide projecten | Spacestate Switch v2 |
Projectoverzicht – Project toevoegen |
Een deurschakelaar in het slot van de toegangsdeur gebaseerd op ethernet. Dit om de staat van de space automatisch te detecteren en veranderingen naar de online tracker te sturen.
Omdat we niets mogen verbouwen aan de space heb ik eens zitten denken aan andere mogelijkheden waarop we kunnen zien of de space open is. Na wat overwegen en bedenken kwam ik tot de conclusie dat er vast een trigger op het slot van de deur van de space gezet kon worden, eentje waarvoor niets gesloopt hoeft te worden.
Contents
Ideeën
Er waren een aantal methoden om een trigger op het slot te plaatsen zonder te hoeven slopen. Dit zou kunnen door middel van een metaal-detector achtig ding of met van die batterij veertjes in het slot-gedeelte van het kozijn die dan kortgesloten worden door het slot. Deze laatste optie was het makkelijkste in te bouwen, en daarvoor had ik de volgende ideeën om hem "uit te lezen":
- Via een twee-pins kabeltje en een microcontroller.
- Met een netwerkkabel en een switchpoort op een managed switch, link up/down detectie gebruiken.
De switch
Ik ben uiteindelijk voor de tweede optie gegaan omdat de managed switch reeds aanwezig is en een microcontroller er apart voor geprogrammeerd en aangeschaft moest worden.
Het doel van de netwerkkabel was om een link-up/link-down event te genereren op de switchpoort waar de kabel in zit. Ik heb van denz gehoord dat Hack42 ook een dergelijk systeem gebruiken voor de spacestate, dit is simpelweg te doen door de volgende pins van een UTP met elkaar te kortsluiten:
- Pin 1 (oranje-wit) met Pin 3 (groen-wit) - Tx+ en Rx+
- Pin 2 (oranje) met Pin 6 (groen) - Tx- en Rx-
Een van de twee pins kan permanent kortgesloten zijn, de andere pins kunnen kortgesloten worden door de deur.
Resultaat
Dit heeft geresulteerd in de volgende contraptie:
Deze contraptie heb ik meegenomen naar de space en wonder boven wonder paste het meteen in de deur zonder modificaties! Dit is het resultaat:
Nadat de "schakelaar" in de deur gezet was, even ter test een laptop aangesloten. Deur niet op slot gaf inderdaad netjes link-down, met de deur op slot gedraait kwam de link netjes op en negotiate die naar 100Mbit Full-duplex!
Kortom: Het werkt!!!
Gebruik
Failbaitr heeft geholpen met het uitzoeken welke switchpoort er beschikbaar was: Dit is poort 22 geworden (Kabel D-1-22, de gele die boven de deur hangt). De deurswitch is hierop aangesloten en de barpc is ingesteld dat deze via SNMP ook bij de switch kan. Hierna heb ik de volgende twee scripts op de BarPC gezet voor het automatisch switchen van de spacestate:
- changespacestate.py, dit script praat met de Frack Spacestate API. Los gedraait met als keyword 'open' of 'close' checkt de state en verandert deze indien die niet klopt.
- snmpdoorif.py, dit script leest de switch uit via SNMP, deze heeft changespacestate.py als module geïmporteerd en roept enkel de state check en de statechange functies aan.
Het script snmpdoorif.py is in de crontab gezet van de BarPC, deze draait iedere minuut. Met behulp van de sleutel van Iisschots even getest en het werkt!
Nooddeur
De nooduitgang van het gereedschapshok heeft een identieke schakelaar gekregen. Deze is aangesloten op poort 7 van switch #2 (Kabel D-2-7). Hiervoor is het snmpdoorif.py script uit de repository licht aangepast en draait nu op de server om de poort in de gaten te houden. Als de link down gaat word er een SpaceAnnounce message gegenereerd in het subdomein x02. In de FrackBot zit een plugin die deze announcements opvangt en daarop reageert.
Port statistieken
Op de space server draait inmiddels een MRTG proces. Deze neemt daarin ook de spacestate switch mee en dat levert een interessante grafiek op. De auto-sense van de switch genereerd genoeg verkeer om een open/close grafiek te maken: Zodra de space gesloten is er verkeer op de poort te zien. We hebben Space-state history op deze manier!
WAARSCHUWING
Als de switch PoE (Power over Ethernet) ondersteunt, is het verstandig dit uit te schakelen voor de poort waar de deurschakelaar aan hangt! |
In theorie zou het goed moeten gaan als de gebruikte PoE techniek IEEE 802.3af is, deze schakelt de stroom pas in als deze een 25k Ohm weerstand detecteerd. Echter bij bijvoorbeeld Cisco Systems hun eigen Inline Power implementatie word de detectie gedaan door een 340kHz toon op de TX te zetten. Als deze terug komt verwacht de cisco switch dat er een PoE device is en schakelt deze de 48v/15,4 watt powersupply in. Deze staat dan effectief in kortsluiting op de switch. DO NOT WANT!
Kortom: Preventief Power over Ethernet disablen op de poort waar de deur aan hangt!
Scripts
snmpdoorif.py
import netsnmp import sys import ConfigParser import os import changespacestate def GetIfStatus(oid, host, community): """ This polls the requested OID and returns True if the interface is UP.""" if netsnmp.snmpget(netsnmp.Varbind(oid), Version = 1, DestHost = host, Community=community)[0] == '1': return True return False def DoorPoller(conffile): """ The doorpoller, reads the specified configfile and then uses that data to get the interface status of a distinct switchport and compares it's state with the spacesstate. It changes the spacestate accordingly. """ config = ConfigParser.RawConfigParser() config.read(conffile) ifstate = GetIfStatus(config.get('snmp', 'oid'), config.get('snmp', 'host'), config.get('snmp', 'community')) space = changespacestate.DoSpaceStateCheck(config.get('space', 'statefile')) if ifstate == space: newstate = '1' if ifstate: newstate = '0' changespacestate.DoChangeSpaceState(config.get('space', 'stateurl'), config.get('space', 'statefile'), config.get('space', 'key'), newstate) if __name__ == '__main__': try: CONF = sys.argv[1] MSG = "ERROR: configfile %s not found." % CONF except IndexError: # WARNING: This does NOT work from CRON, when running from CRON always use # the full config path to avoid it from trying the default value. CONF = os.path.expanduser("~/.snmpdoorif.conf") MSG = "ERROR: Default config (%s) not found, please specify a file." % CONF if os.path.isfile(CONF): DoorPoller(CONF) else: print "%s\r\nUsage: %s [conffile]" % (MSG, sys.argv[0]) </syntaxhighlight> === changespacestate.py === <syntaxhighlight lang="python"> import urllib2 import urllib import sys STATEURL = "http://frack.nl/spacestate/" STATEFILE = "http://frack.nl/spacestate/status.txt" KEY = "password" def DoChangeSpaceState(stateurl, statefile, key, newstate): """ This function closes/opens the space. Returns True if successful """ opts = { 'pass': key, 'newstate': newstate } reqstate = False if newstate == "1": reqstate = True try: urllib2.urlopen(stateurl, urllib.urlencode(opts), 10).readlines() if DoSpaceStateCheck(statefile) == reqstate: return True except urllib2.URLError, (err): print "ERROR: Failed to open the URL (%s)" % err return False def DoSpaceStateCheck(statefile): """ Checks if the space is opened (returns True if yes). """ try: if urllib2.urlopen(statefile, timeout=10).readlines()[0] == '1': return True except urllib2.URLError, (err): print "ERROR: Failed to open the URL (%s)" % err return False def AutoChangeSpaceState(stateurl, statefile, key, newstate): """ Main function that calls the other functions in order. """ reqstate = False if newstate == "1": reqstate = True if DoSpaceStateCheck(statefile) == reqstate: return "INFO: Space is already in the requested state." else: if DoChangeSpaceState(stateurl, statefile, key, newstate): return "INFO: Spacestate has been changed as requested." else: return "WARNING: Failed to change the spacestate!" if __name__ == '__main__': try: ARGS = sys.argv[1] except IndexError: print "Usage: %s [open|close]" % sys.argv[0] sys.exit(1) if ARGS == "open": print AutoChangeSpaceState(STATEURL, STATEFILE, KEY, "1") elif ARGS == "close": print AutoChangeSpaceState(STATEURL, STATEFILE, KEY, "0") else: print "Usage: %s [open|close]" % sys.argv[0]