Is this acceptable for single device serial communications?

This is a legacy forum which is locked for new topics. New topics should be started in one of the other forums under Extending Indigo
Forum rules
This is a legacy forum which is locked for new topics. New topics should be started in one of the other forums under Extending Indigo
yergeyj
Posts: 260
Joined: Wed Dec 29, 2004 7:30 am

Is this acceptable for single device serial communications?

Post by yergeyj »

I'd like to know if the following is an appropriate implementation for serial communication.

BACKGROUND: I'm working on a plugin for serial communication/control of Zodiac/Jandy Pool/Spa systems. I assume that users will have only a single Jandy system on a given instance of Indigo, and verify that when adding a new Jandy device.

With that background, here's how I've implemented the serial communications, which need to be opened, and a concurrent thread used to send commands and receive information that the Jandy system sends, independent of user commands.

In the main python.py the following is used to start and end device communication (note that python.py also queues commands that arrive from Actions):

Code: Select all

	##############################################################################################
	def deviceStartComm(self, dev):
		self.debugLog("<<-- entering deviceStartComm, Device: " + dev.name + "; ID=" +  str(dev.id) + ", Type=" + dev.deviceTypeId)
		self.jandyaqualink.startCommThread(dev)
		self.debugLog(u"exiting deviceStartComm -->>")

	def deviceStopComm(self, dev):
		self.debugLog("<<-- entering deviceStopComm, Device: " + dev.name + "; ID=" +  str(dev.id) + ", Type=" + dev.deviceTypeId)
		self.jandyaqualink.stopCommThread(dev)
		self.debugLog("exiting deviceStopComm -->>")
python.py then calls the following in jandyaqualink.py to actually start and stop the serial communication, and start/stop a concurrent thread to handle ongoing communication:

Code: Select all

	
        ##############################################################################################
	def startCommThread(self, dev):
		devProps = dev.pluginProps
		portName = devProps.get("serialPort")
		self.conn = self.plugin.openSerial(dev.name, portName, 9600, timeout=1, writeTimeout=1)

		### If connection to serial device is successfully statrted, queue initial commands
		### Else, log error starting communication
		if self.conn:
			### Queue commands here ...
			self.commQueue = []
                (add commands to queue)
	
			### Start separate concurrentSerialComm thread - syntax roughly based on EasyDAQ Plugin
			self.concurThread = threading.Thread(target=functools.partial(self.concurrentSerialComm, dev))
			self.concurThread.start()			
		else:
			indigo.server.log("Error initializing communciations with serial device " + dev.name)
			
	######################
	# Send command to stop concurrentSerialComm thread, then close serial connection and exit.
	def stopCommThread(self, dev):
		self.queueSerialCmd("stopConcurrentSerialComm")
		time.sleep(10)		# Give plenty of time for command to stop concurrent thread to execute.
		self.conn.close()
		self.plugin.debugLog("closed connection to device " + dev.name)


	##############################################################################################
	def concurrentSerialComm(self, dev):
		try:
			
			while True:

				##################################################################################
				# Start each pass by reading/decoding any commands from Aqualink.
				self.readSerialBuffer(dev)

				##################################################################################
				# Next, send commands from those queued.
				# Use a copy of the queue to avoid confusion if added to while executing.
				# Check for command to terminate thread
				if len(self.commQueue) >= 1:
					workingQueue = self.commQueue
					lenQueue = len(workingQueue)
					for command in self.commQueue:
						if command == "stopConcurrentSerialComm":	# Command to stop queue?
							raise self.StopThread					# Raise exception to stop thread.
						else:
							self.sendSerialCmd(dev, command)
					self.commQueue = self.commQueue[lenQueue:]

				##################################################################################
				# Sleep a bit on each cycle.
				time.sleep(kSleepAfterSerialCommand * 3)
				
		### Exceptions to exit thread.  !!! Need to understand 2nd and 3rd except:, "borrowed" from EasyDAQ plugin.
		except self.StopThread:
			pass	# silently fall into finally: section below
		except Exception, e:
			self.plugin.exceptionLog()
		except:
			self.plugin.exceptionLog()
		finally:
			pass	# Finally, exit thread.
			
Does this seem reasonable? It seems to work, but I wasn't sure if passing information using the self.conn and self. commQueue are "acceptable"?

Jim
User avatar
matt (support)
Site Admin
Posts: 21542
Joined: Mon Jan 27, 2003 1:17 pm
Location: Texas
Contact:

Re: Is this acceptable for single device serial communicatio

Post by matt (support) »

I think that should be fine. Although you are about 98% of the way to allowing multiple Jandy devices if you just pass the conn object into concurrentSerialComm as an argument instead of using self.conn. :-)
Image
Locked

Return to “Extending Indigo with Plugins and Python”