Is this acceptable for single device serial communications?

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

Posted on
Fri Sep 09, 2011 9:48 pm
yergeyj offline
Posts: 260
Joined: Dec 29, 2004

Is this acceptable for single device serial communications?

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

Posted on
Sat Sep 10, 2011 3:05 pm
matt (support) offline
Site Admin
User avatar
Posts: 21417
Joined: Jan 27, 2003
Location: Texas

Re: Is this acceptable for single device serial communicatio

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

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 3 guests