# Twisted Imports
from twisted.internet import reactor, defer, task
from twisted.internet.interfaces import IAddress

# Zope Imports
from zope.interface import implementer

# Phidget Imports
from Phidgets.PhidgetException import PhidgetErrorCodes, PhidgetException

# System Imports
import time
	
@implementer(IAddress)
class PhidgetAddress (object):
	compareAttributes = ('device_class', 'id')

	def __init__ (self, id):
		self.id = id

	def __repr__ (self):
		return "%s(%s)" % (self.__class__.__name, self.id)


class Phidget (object):
	def __init__ (self, id):
		self.id = id
		self.name = "phidget(%s)" % id

	def connect (self, protocolFactory):
		d = defer.Deferred()
		addr = PhidgetAddress(self.id)
		protocol = protocolFactory.buildProtocol(addr)

		def attach_handler (event):
			# Not clear whether this is necessary, or if the devices are filtered...
			serial = event.device.getSerialNum()
			name = event.device.getDeviceName()
			print("Phidget Device '" + str(name) + "', Serial Number: " + str(serial) + " Connected")

			try:
				if serial == self.id:
					d.callback(protocol)
			except defer.AlreadyCalledError:
				pass

		def detach_handler (event):
			print "Detached"
			
		@defer.inlineCallbacks
		def check_attached ():
				tries = 0
				while tries < 20:
						if protocol.isAttached():
								serial = protocol.getSerialNum()
								name = protocol.getDeviceName()
								print("Phidget Device '" + str(name) + "', Serial Number: " + str(serial) + " Connected")

								defer.returnValue(protocol)
						else:
								tries += 1
								yield task.deferLater(reactor, 0.5, lambda: True)

				raise Exception("Attachment to phidget timed out")

		try:
			protocol.openPhidget(self.id)

			# Blocks to allow time for phidget to initialise
			time.sleep(0.00125)

			check_attached().addCallbacks(d.callback, d.errback)

			# if protocol.isAttached():
				# d.callback(protocol)
			# else:			
				# protocol.setOnAttachHandler(attach_handler)
				# protocol.setOnDetachHandler(detach_handler)
		except PhidgetException as e:
			d.errback(e)

		return d


@@ -508,16 +508,231 @@
 f.id)%0A%0A%0A
+class PhidgetTransport (object):%0A%09def __init__ (self, protocol):%0A%09%09self.protocol = protocol%0A%0A%09def loseConnection (self):%0A%09%09try:%0A%09%09%09self.protocol.closePhidget()%0A%09%09except (AttributeError, PhidgetException):%0A%09%09%09pass%0A%0A%0A
 class Ph
@@ -969,447 +969,58 @@
 dr)%0A
-%0A
 %09%09
-def attach_handler (event):%0A%09%09%09# Not clear whether this is necessary, or if the devices are filtered...%0A%09%09%09serial = event.device.getSerialNum()%0A%09%09%09name = event.device.getDeviceName()%0A%09%09%09print(%22Phidget Device '%22 + str(name) + %22', Serial Number: %22 + str(serial) + %22 Connected%22)%0A%0A%09%09%09try:%0A%09%09%09%09if serial == self.id:%0A%09%09%09%09%09d.callback(protocol)%0A%09%09%09except defer.AlreadyCalledError:%0A%09%09%09%09pass%0A%0A%09%09def detach_handler (event):%0A%09%09%09print %22Detached%22%0A%09%09%09
+protocol.transport = PhidgetTransport(protocol)%0A
 %0A%09%09@
@@ -1069,17 +1069,16 @@
  ():%0A%09%09%09
-%09
 tries = 
@@ -1079,17 +1079,16 @@
 ies = 0%0A
-%09
 %09%09%09while
@@ -1104,18 +1104,16 @@
 20:%0A%09%09%09%09
-%09
-%09
 if proto
@@ -1135,19 +1135,16 @@
 ):%0A%09%09%09%09%09
-%09%09
-%09
 serial =
@@ -1168,19 +1168,16 @@
 alNum()%0A
-%09%09%09
 %09%09%09%09%09nam
@@ -1205,19 +1205,16 @@
 eName()%0A
-%09%09%09
 %09%09%09%09%09pri
@@ -1306,19 +1306,16 @@
 )%0A%0A%09%09%09%09%09
-%09%09%09
 defer.re
@@ -1338,18 +1338,16 @@
 ol)%0A%09%09%09%09
-%09%09
 else:%0A%09%09
@@ -1349,19 +1349,16 @@
 e:%0A%09%09%09%09%09
-%09
-%09%09
 tries +=
@@ -1360,19 +1360,16 @@
 es += 1%0A
-%09%09%09
 %09%09%09%09%09yie
@@ -1416,17 +1416,16 @@
  True)%0A%0A
-%09
 %09%09%09raise
@@ -1647,181 +1647,8 @@
 ack)
-%0A%0A%09%09%09# if protocol.isAttached():%0A%09%09%09%09# d.callback(protocol)%0A%09%09%09# else:%09%09%09%0A%09%09%09%09# protocol.setOnAttachHandler(attach_handler)%0A%09%09%09%09# protocol.setOnDetachHandler(detach_handler)
 %0A%09%09e

Add disconnect support to Phidget transport.