Package SpecClient :: Module SpecChannel
[hide private]
[frames] | no frames]

Source Code for Module SpecClient.SpecChannel

  1  #$Id: SpecChannel.py,v 1.6 2006/12/14 10:03:13 guijarro Exp $ 
  2  """SpecChannel module 
  3   
  4  This module defines the SpecChannel class 
  5  """ 
  6   
  7  __author__ = 'Matias Guijarro' 
  8  __version__ = '1.0' 
  9   
 10  import SpecEventsDispatcher 
 11  import SpecWaitObject 
 12  import weakref 
 13  import types 
 14   
 15  (DOREG, DONTREG, WAITREG) = (0, 1, 2) 
 16   
17 -class SpecChannel:
18 """SpecChannel class 19 20 Represent a channel in Spec 21 22 Signals: 23 valueChanged(channelValue, channelName) -- emitted when the channel gets updated 24 """ 25 channel_aliases = {} 26
27 - def __init__(self, connection, channelName, registrationFlag = DOREG):
28 """Constructor 29 30 Arguments: 31 connection -- a SpecConnection object 32 channelName -- string representing a channel name, i.e. 'var/toto' 33 34 Keyword arguments: 35 registrationFlag -- defines how the channel is registered, possible 36 values are : SpecChannel.DOREG (default), SpecChannel.DONTREG 37 (do not register), SpecChannel.WAITREG (delayed registration until Spec is 38 reconnected) 39 """ 40 self.connection = weakref.ref(connection) 41 self.name = channelName 42 43 if channelName.startswith("var/") and '/' in channelName[4:]: 44 l = channelName.split('/') 45 self.spec_chan_name = "/".join((l[0], l[1])) 46 if self.spec_chan_name in SpecChannel.channel_aliases: 47 SpecChannel.channel_aliases[self.spec_chan_name].append(self.name) 48 else: 49 SpecChannel.channel_aliases[self.spec_chan_name] = [self.name] 50 51 if len(l)==3: 52 self.access1=l[2] 53 self.access2=None 54 else: 55 self.access1=l[2] 56 self.access2=l[3] 57 else: 58 self.spec_chan_name = self.name 59 if not self.spec_chan_name in SpecChannel.channel_aliases: 60 SpecChannel.channel_aliases[self.spec_chan_name]=[self.name] 61 self.access1=None 62 self.access2=None 63 self.registrationFlag = registrationFlag 64 self.isdisconnected = True 65 self.registered = False 66 self.value = None 67 68 SpecEventsDispatcher.connect(connection, 'connected', self.connected) 69 SpecEventsDispatcher.connect(connection, 'disconnected', self.disconnected) 70 71 if connection.isSpecConnected(): 72 self.connected()
73 74
75 - def connected(self):
76 """Do registration when Spec gets connected 77 78 If registration flag is WAITREG put the flag to DOREG if not yet connected, 79 and register if DOREG 80 """ 81 if self.registrationFlag == WAITREG: 82 if self.isdisconnected: 83 self.registrationFlag = DOREG 84 85 self.isdisconnected = False 86 87 if self.registrationFlag == DOREG: 88 self.register()
89 90
91 - def disconnected(self):
92 """Reset channel object when Spec gets disconnected.""" 93 self.value = None 94 self.isdisconnected = True
95 96
97 - def unregister(self):
98 """Unregister channel.""" 99 connection = self.connection() 100 101 if connection is not None: 102 connection.send_msg_unregister(self.spec_chan_name) 103 self.registered = False 104 self.value = None
105 106
107 - def register(self):
108 """Register channel 109 110 Registering a channel means telling the server we want to receive 111 update events when a channel value changes on the server side. 112 """ 113 connection = self.connection() 114 115 if connection is not None: 116 connection.send_msg_register(self.spec_chan_name) 117 self.registered = True
118 119
120 - def update(self, channelValue, deleted = False):
121 """Update channel's value and emit the 'valueChanged' signal.""" 122 if type(channelValue) == types.DictType and self.access1 is not None: 123 if self.access1 in channelValue: 124 if deleted: 125 SpecEventsDispatcher.emit(self, 'valueChanged', (None, self.name, )) 126 else: 127 if self.access2 is None: 128 if self.value is None or self.value != channelValue[self.access1]: 129 self.value = channelValue[self.access1] 130 SpecEventsDispatcher.emit(self, 'valueChanged', (self.value, self.name, )) 131 else: 132 if self.access2 in channelValue[self.access1]: 133 if deleted: 134 SpecEventsDispatcher.emit(self, 'valueChanged', (None, self.name, )) 135 else: 136 if self.value is None or self.value != channelValue[self.access1][self.access2]: 137 self.value = channelValue[self.access1][self.access2] 138 SpecEventsDispatcher.emit(self, 'valueChanged', (self.value, self.name, )) 139 return 140 141 if type(self.value) == types.DictType and type(channelValue) == types.DictType: 142 # update dictionary 143 if deleted: 144 for key,val in channelValue.iteritems(): 145 if type(val) == types.DictType: 146 for k in val: 147 try: 148 del self.value[key][k] 149 except KeyError: 150 pass 151 if len(self.value[key])==1 and None in self.value[key]: 152 self.value[key]=self.value[key][None] 153 else: 154 try: 155 del self.value[key] 156 except KeyError: 157 pass 158 else: 159 for k1,v1 in channelValue.iteritems(): 160 if type(v1)==types.DictType: 161 try: 162 self.value[k1].update(v1) 163 except KeyError: 164 self.value[k1]=v1 165 except AttributeError: 166 self.value[k1]={None: self.value[k1]} 167 self.value[k1].update(v1) 168 else: 169 if self.value.has_key(k1) and type(self.value[k1]) == types.DictType: 170 self.value[k1][None] = v1 171 else: 172 self.value[k1] = v1 173 value2emit=self.value.copy() 174 else: 175 if deleted: 176 self.value = None 177 else: 178 self.value = channelValue 179 value2emit=self.value 180 181 SpecEventsDispatcher.emit(self, 'valueChanged', (value2emit, self.name, ))
182 183
184 - def read(self):
185 """Read the channel value 186 187 If channel is registered, just return the internal value, 188 else obtain the channel value and return it. 189 """ 190 if self.registered and self.value is not None: 191 #we check 'value is not None' because the 192 #'registered' flag could be set, but before 193 #the message with the channel value arrived ; 194 #in this case, the 'else' is executed and the 195 #channel value is read (slower...) 196 return self.value 197 else: 198 connection = self.connection() 199 200 if connection is not None: 201 w = SpecWaitObject.SpecWaitObject(connection) 202 # make sure spec is connected, we give a short timeout 203 # because it is supposed to be the case already 204 w.waitConnection(timeout=500) 205 w.waitReply('send_msg_chan_read', (self.spec_chan_name, )) 206 207 self.update(w.value) 208 209 return self.value
210 211
212 - def write(self, value):
213 """Write a channel value.""" 214 connection = self.connection() 215 216 if connection is not None: 217 if self.access1 is not None: 218 if self.access2 is None: 219 value = { self.access1: value } 220 else: 221 value = { self.access1: { self.access2: value } } 222 223 connection.send_msg_chan_send(self.spec_chan_name, value)
224