schelli04
Posts: 13
Joined: Fri Feb 03, 2012 7:41 pm

Websocketserver in Python (twisted + autobahn)

Thu Sep 06, 2012 2:07 pm

Hallo zusammen!

Vorab: ich bin ziemlicher Einsteiger. Programmierung läuft bei mir zu 90% Copy&Paste

Bin momentan dabei mir daheim ne kleine Alarmanlage zusammenzubauen. Das Script zur Überwachung der GPIO Pins ist fertig (Python). Zu An und Aus schalten der Alarmanlage habe ich ne kleine Webapp mit Websocketverbindung erstellt. Der Websocketserver (twisted + autobahn) läuft auch als einzelnes Script in Python. Das Problem ist, dass das Script nur auf Verbindungsereignisse reagiert, ich also die Schleife, die die GPIO's überwacht nicht im selben Script laufen lassen kann. Hat jemand ne Idee, wie ich das bewerkstelligen kann, dass beide Scripte miteinander kommunizieren?
Wenn ich daheim bin füge ich noch ein den Quelltext mit ein.

Gruß Schelli

schelli04
Posts: 13
Joined: Fri Feb 03, 2012 7:41 pm

Re: Websocketserver in Python (twisted + autobahn)

Thu Sep 06, 2012 5:18 pm

So ich habe es nun am laufen. Die Kommunikation läuft über eine Datei (comm.ini)

Das ist der Code der eigentlichen Alarmanlage:

Code: Select all

import smsgateway, emailsenden, sys
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)								# BCM - Modus verwenden
GPIO.setup(4, GPIO.IN, pull_up_down=GPIO.PUD_UP)	# GPIO 4 als Eingang setzen
GPIO.setup(0, GPIO.OUT)
aktiv = False					# Bei Start Alarmanlage deaktiviert
print aktiv

while True:
	while aktiv != True:		# Solange Alarmanlage nicht aktiv
		File = open('comm.ini', 'w+')
		msg = File.read()
		File.write('')
		File.close()
		if msg=='on':				# Warten auf Aktivierung
			aktiv = True
			print aktiv
		if msg=='status':
			File = open('comm.ini', 'w')
			if aktiv:
				status = 'Aktiv'
			else:
				status = 'Inaktiv'
			File.write(status)
			File.close

	while aktiv:
		GPIO.output(0, True)
		if False:#GPIO.input(4) != 0:				# Wenn Tuer geoeffnet wird
			#smsgateway.sms('Tuer geoeffnet')
			emailsenden.send('Tuer geoeffnet')
			aktiv = False
		File = open('comm.ini', 'w+')
		msg = File.read()
		File.write('')
		File.close()
		if msg=='off':				# Warten auf Deaktivierung
			aktiv = False
			print aktiv
		if msg=='status':
			File = open('comm.ini', 'w')
			if aktiv:
				status = 'Aktiv'
			else:
				status = 'Inaktiv'
			File.write(status)
			File.close
Und hier der Code des Websocket-Servers:

Code: Select all

import sys, time

from twisted.internet import reactor
from twisted.python import log

from autobahn.websocket import	WebSocketServerFactory, \
								WebSocketServerProtocol, \
								listenWS


class EchoServerProtocol(WebSocketServerProtocol):
	def onMessage(self, msg, binary):
		print msg
		if msg == "on":
			file = open('comm.ini', 'w+')
			file.write('on')
			file.close()
			self.sendMessage('AN', binary)
		if msg == "off":
			file = open('comm.ini', 'w+')
			file.write('off')
			file.close()
			self.sendMessage('AUS', binary)
		if msg == "status":
			file = open('comm.ini', 'w+')
			file.write('status')
			file.close()
			time.sleep(2)
			file = open('comm.ini', 'r')
			bmsg = file.read()
			file.close()
			file = open('comm.ini', 'w')
			file.write('')
			file.close()
			self.sendMessage(bmsg, binary)
			print 'Status', bmsg


if __name__ == '__main__':

	#log.startLogging(sys.stdout)

	factory = WebSocketServerFactory("ws://192.168.0.191:9123", debug = False)
	factory.protocol = EchoServerProtocol
	factory.setProtocolOptions(allowHixie76 = True)
	listenWS(factory)

	reactor.run()
Vielleicht hat jemand einen Tip wie ich das ganze besser lösen kann. Habe das Gefühl, dass das Alarmanlagenskript oft die Datei blockiert.

oberstet
Posts: 3
Joined: Fri Sep 07, 2012 9:09 am

Re: Websocketserver in Python (twisted + autobahn)

Fri Sep 07, 2012 9:13 am

Generell sollte in Twisted Code niemals blockierender Code aufgerufen werden. Für die Kommunikation über Serial Ports gibt es http://twistedmatrix.com/documents/curr ... lPort.html. Um blockierenden Code in einem eigenem Thread auszuführen gibt es deferToThread u.ä. Funktionen.

schelli04
Posts: 13
Joined: Fri Feb 03, 2012 7:41 pm

Re: Websocketserver in Python (twisted + autobahn)

Sun Sep 09, 2012 12:43 pm

Danke für den Tip! Werde mich diesbezüglich mal einlesen. Neue Lösung werde ich dann hier einstellen wenn es läuft.

schelli04
Posts: 13
Joined: Fri Feb 03, 2012 7:41 pm

Re: Websocketserver in Python (twisted + autobahn)

Sun Sep 09, 2012 5:45 pm

So habe nun die "Alarmüberwachung" in einen eigenen Thread gepackt. Läuft bis jetzt ohne erkennbare Probleme und Verzögerung. Wesentliche bessere Lösung als mein erster Ansatz mit der Datei.

Vollständiger Code:

Code: Select all

import time
import sys				# Modul fuer Dateioperationen
import RPi.GPIO as GPIO
import thread
import smsgateway, emailsenden

from twisted.internet import reactor
from twisted.python import log

from autobahn.websocket import	WebSocketServerFactory, \
								WebSocketServerProtocol, \
								listenWS

# GPIO nach BCM initalisieren
GPIO.setmode(GPIO.BCM)

# GPIO Eingang setzen
GPIO.setup(4, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# Status LED setzen
GPIO.setup(14, GPIO.OUT)

status = False

class EchoServerProtocol(WebSocketServerProtocol):
	def onMessage(self, msg, binary):
		global status
		print msg
		if msg == "on":
			status = True
		if msg == "off":
			status = False
		self.sendMessage(str(status), binary)
		print 'Status', str(status)
			
def alarm():
	global status
	while True:
		while status:
			GPIO.output(14, True)
			if GPIO.input(4) == 0:				# Wenn Tuer geoeffnet wird '==' muss im endgueltigen Zustand in '!=' geaendert werden. Aktuell reagiert die Schleife auf Tastendruck
				#smsgateway.sms('Tuer geoeffnet')
				#emailsenden.send('Tuer geoeffnet')
				print str(status)
				status = False
		GPIO.output(14, False)

if __name__ == '__main__':

	log.startLogging(sys.stdout)

	factory = WebSocketServerFactory("ws://192.168.0.191:9123", debug = False)
	factory.protocol = EchoServerProtocol
	factory.setProtocolOptions(allowHixie76 = True)
	listenWS(factory)
	
	thread.start_new_thread(alarm, ())
	
	reactor.run()
In Zeile 41 wird zu Testzwecken nur auf den Tastendruck reagiert. Im finalen Stadium soll reagiert werden wenn ein an der Tür angebrachter Reedkontakt geöffnet ist.

oberstet
Posts: 3
Joined: Fri Sep 07, 2012 9:09 am

Re: Websocketserver in Python (twisted + autobahn)

Sun Sep 09, 2012 5:51 pm

Das wird nicht (robust) funktionieren .. denn Du möchtest ja von dem Hintergrund Thread aus Messages über WebSocket versenden und letzteres läuft im Twisted Main Thread => callFromThread.
http://twistedmatrix.com/documents/curr ... ading.html

schelli04
Posts: 13
Joined: Fri Feb 03, 2012 7:41 pm

Re: Websocketserver in Python (twisted + autobahn)

Mon Sep 10, 2012 6:40 am

(Vorerst) sollen per Websocket nur Nachrichten geschickt werden, wenn welche empfangen werden. Sozusagen als Statusmeldung. Das Funktioniert ja. Die Alarmmeldung selber geht per SMS raus, weil ich ja sonst ständig mit der WebApp online sein müsste, um die Nachrichten zu empfangen.
Werds mir dein Link trotzdem mal anschauen, da ich noch weitere Funktionen mit einbauen wollte.

oberstet
Posts: 3
Joined: Fri Sep 07, 2012 9:09 am

Re: Websocketserver in Python (twisted + autobahn)

Tue Sep 11, 2012 9:43 am

Wie machst Du das SMS versenden? Würde mich auch interessieren ..

schelli04
Posts: 13
Joined: Fri Feb 03, 2012 7:41 pm

Re: Websocketserver in Python (twisted + autobahn)

Tue Sep 11, 2012 12:31 pm

Ich habe mir ein Account unter http://www.sms-expert.de angelegt. Der Versand erfolgt dann über einen http-Request. Da kostet die SMS allerdings 0,05 €.

Code: Select all

import urllib, urllib2, time
import md5
from config import smsuser, smspasswd


def sms(message, nr):
	url = 'https://gateway.sms-expert.de/send/'
	user = smsuser
	type = 'standard'
	receiver = str(nr)
	hashstring = user + '|' + str(smspasswd) + '|' + type + '||' + receiver + '|' + message + '|'
	print hashstring
	hash = md5.new(hashstring).hexdigest()
	print hash
	values = {	'user':user,
				'type':type,
				'receiver':receiver,
				'message':message,
				'hash':hash}
	try:
		data = urllib.urlencode(values)
		req = urllib2.Request(url, data)
		response = urllib2.urlopen(req)
		antwort = response.read()
		print antwort
	except Exception, detail:
		print "Err ", detail
smsuser und smspasswd sind die Zuganngsdaten zum SMS-Gateway. Habe ich in ner extra Datei config.py gespeichert.

Später wollte ich das ganze aber mit Hilfe eines UMTS Stick mit SIM-Karte machen, damit das ganze nicht auf mein Heimnetzwerk angewiesen ist. Also der Versand direkt über den UMTS-Stick ohne das zusätzliche Gateway im Netz.

theTimewalker
Posts: 1
Joined: Wed Mar 05, 2014 10:18 am

Re: Websocketserver in Python (twisted + autobahn)

Wed Mar 05, 2014 10:20 am

Hallo schelli04,

habe deinen Beitrag gerade zufällig gefunden und wollte mal fragen ob du den SMS-Versand per UMTS-Stick inzwischen umgesetzt hast. Wenn ja, wäre ich um eine kurze Hilfestellung (Anleitung oder Links) sehr dankbar...

VG,
Timewalker

schelli04
Posts: 13
Joined: Fri Feb 03, 2012 7:41 pm

Re: Websocketserver in Python (twisted + autobahn)

Thu Mar 13, 2014 6:43 am

Hey Timewalker,

da ich mich zwischenzeitlich mit anderen Projekten beschäftigt habe, bin ich noch nicht dazu gekommen den SMS-Versand über einen UMTS-Stick zu realisieren. In nächster Zeit werde ich auch die Zeit dazu nicht finden.

MfG, Schelli

Return to “Deutsch”