merged in cherry-picked service discovery changes
authorb.taylor@willowglen.ca
Wed, 12 Aug 2009 16:09:00 -0600
changeset 376 53b00ff1b2d6
parent 357 19db1076e93c (current diff)
parent 375 b16bcfe531d7 (diff)
child 377 9db62e0280f5
merged in cherry-picked service discovery changes
--- a/Zeroconf.py	Mon Jul 06 11:27:06 2009 -0600
+++ b/Zeroconf.py	Wed Aug 12 16:09:00 2009 -0600
@@ -1154,7 +1154,7 @@
         """Updates service information from a DNS record"""
         if record is not None and not record.isExpired(now):
             if record.type == _TYPE_A:
-                if record.name == self.name:
+                if record.name == self.server:
                     self.address = record.address
             elif record.type == _TYPE_SRV:
                 if record.name == self.name:
@@ -1162,7 +1162,6 @@
                     self.port = record.port
                     self.weight = record.weight
                     self.priority = record.priority
-                    self.address = None
                     self.updateRecord(zeroconf, now, zeroconf.cache.getByDetails(self.server, _TYPE_A, _CLASS_IN))
             elif record.type == _TYPE_TXT:
                 if record.name == self.name:
--- a/discovery.py	Mon Jul 06 11:27:06 2009 -0600
+++ b/discovery.py	Wed Aug 12 16:09:00 2009 -0600
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 #This file is part of Beremiz, a Integrated Development Environment for
@@ -27,7 +26,7 @@
 import socket
 import  wx.lib.mixins.listctrl  as  listmix
 
-class TestListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
+class AutoWidthListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
     def __init__(self, parent, ID, pos=wx.DefaultPosition,
                  size=wx.DefaultSize, style=0):
         wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
@@ -38,17 +37,22 @@
         self.my_result=None
         wx.Dialog.__init__(self, parent, id, title, size=(600,600), style=wx.DEFAULT_DIALOG_STYLE)
 
+        # set up dialog sizer
+
         sizer = wx.FlexGridSizer(2, 1, 2, 2)  # rows, cols, vgap, hgap
         sizer.AddGrowableRow(0)
         sizer.AddGrowableCol(0)
 
-        self.list = TestListCtrl(self, -1,
-                                 #pos=(50,20), 
-                                 #size=(500,300),
-                                 style=wx.LC_REPORT 
-                                | wx.LC_EDIT_LABELS
-                                | wx.LC_SORT_ASCENDING
-                                )
+        # set up list control
+
+        self.list = AutoWidthListCtrl(self, -1,
+                                      #pos=(50,20), 
+                                      #size=(500,300),
+                                      style=wx.LC_REPORT 
+                                     | wx.LC_EDIT_LABELS
+                                     | wx.LC_SORT_ASCENDING
+                                     | wx.LC_SINGLE_SEL 
+                                     )
         sizer.Add(self.list, 1, wx.EXPAND)
 
         btsizer = wx.FlexGridSizer(1, 6, 2, 2)  # rows, cols, vgap, hgap
@@ -60,6 +64,8 @@
         self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected, self.list)
         self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated, self.list)
 
+        # set up buttons
+
         local_id = wx.NewId()
         b = wx.Button(self, local_id, "Refresh")
         self.Bind(wx.EVT_BUTTON, self.OnRefreshButton, b)
@@ -89,7 +95,12 @@
 
         listmix.ColumnSorterMixin.__init__(self, 4)
 
-        #type = "_http._tcp.local."
+        # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
+        self.itemDataMap = {}
+
+        # a counter used to assign a unique id to each listctrl item
+        self.nextItemId = 0
+
         self.browser = None
         self.zConfInstance = Zeroconf()
         self.RefreshList()
@@ -97,7 +108,7 @@
         self.Bind(wx.EVT_CLOSE, self.OnClose)
 
     def RefreshList(self):
-        type = "_PYRO._tcp.local."
+        type = "_WGPLC._tcp.local."
         self.browser = ServiceBrowser(self.zConfInstance, type, self)        
 
     def OnRefreshButton(self, event):
@@ -158,16 +169,55 @@
         return self.my_result
         
     def removeService(self, zeroconf, type, name):
-        pass
+        '''
+        called when a service with the desired type goes offline.
+        '''
+
+        # loop through the list items looking for the service that went offline
+        for idx in xrange(self.list.GetItemCount()):
+            # this is the unique identifier assigned to the item
+            item_id = self.list.GetItemData(idx)
+
+            # this is the full typename that was received by addService
+            item_name = self.itemDataMap[item_id][4]
+
+            if item_name == name:
+                self.list.DeleteItem(idx)
+                break
 
     def addService(self, zeroconf, type, name):
+        '''
+        called when a service with the desired type is discovered.
+        '''
+
         info = self.zConfInstance.getServiceInfo(type, name)
+
+        svcname  = name.split(".")[0]
         typename = type.split(".")[0][1:]
+        ip       = str(socket.inet_ntoa(info.getAddress()))
+        port     = info.getPort()
+
         num_items = self.list.GetItemCount()
-        self.list.InsertStringItem(num_items, name.split(".")[0])
-        self.list.SetStringItem(num_items, 1, "%s"%typename)
-        self.list.SetStringItem(num_items, 2, "%s"%str(socket.inet_ntoa(info.getAddress())))
-        self.list.SetStringItem(num_items, 3, "%s"%info.getPort())
+
+        # display the new data in the list
+        new_item = self.list.InsertStringItem(num_items, svcname)
+        self.list.SetStringItem(new_item, 1, "%s" % typename)
+        self.list.SetStringItem(new_item, 2, "%s" % ip)
+        self.list.SetStringItem(new_item, 3, "%s" % port)
+
+        # record the new data for the ColumnSorterMixin
+        # we assign every list item a unique id (that won't change when items
+        # are added or removed)
+        self.list.SetItemData(new_item, self.nextItemId)
+ 
+        # the value of each column has to be stored in the itemDataMap
+        # so that ColumnSorterMixin knows how to sort the column.
+
+        # "name" is included at the end so that self.removeService
+        # can access it.
+        self.itemDataMap[self.nextItemId] = [ svcname, typename, ip, port, name ]
+
+        self.nextItemId += 1
 
     def CreateURI(self, connect_type, connect_address, connect_port):
         uri = "%s://%s:%s"%(connect_type, connect_address, connect_port)