Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

# -*- coding: utf-8 -*- 

"""The value 

 

""" 

 

__license__ = """ 

    This file is part of Janitoo. 

 

    Janitoo is free software: you can redistribute it and/or modify 

    it under the terms of the GNU General Public License as published by 

    the Free Software Foundation, either version 3 of the License, or 

    (at your option) any later version. 

 

    Janitoo is distributed in the hope that it will be useful, 

    but WITHOUT ANY WARRANTY; without even the implied warranty of 

    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 

    GNU General Public License for more details. 

 

    You should have received a copy of the GNU General Public License 

    along with Janitoo. If not, see <http://www.gnu.org/licenses/>. 

 

""" 

__author__ = 'Sébastien GALLET aka bibi21000' 

__email__ = 'bibi21000@gmail.com' 

__copyright__ = "Copyright © 2013-2014-2015-2016 Sébastien GALLET aka bibi21000" 

 

import logging 

logger = logging.getLogger(__name__) 

 

from janitoo.utils import json_dumps 

from janitoo.value import JNTValue 

 

############################################################## 

#Check that we are in sync with the official command classes 

#Must be implemented for non-regression 

from janitoo.classes import COMMAND_DESC 

 

COMMAND_CONFIGURATION = 0x0070 

COMMAND_SENSOR_BINARY = 0x0030 

COMMAND_SENSOR_MULTILEVEL = 0x0031 

 

assert(COMMAND_DESC[COMMAND_CONFIGURATION] == 'COMMAND_CONFIGURATION') 

assert(COMMAND_DESC[COMMAND_SENSOR_BINARY] == 'COMMAND_SENSOR_BINARY') 

assert(COMMAND_DESC[COMMAND_SENSOR_MULTILEVEL] == 'COMMAND_SENSOR_MULTILEVEL') 

############################################################## 

 

class JNTValueFactoryEntry(JNTValue): 

    """Implement a value entry for the factory. Used to create complex values. 

    """ 

    def __init__(self, uuid="value_entry_uuid", **kwargs): 

        """ 

        """ 

        self.entry_name = kwargs.pop('entry_name', 'an_entry_name') 

        self.options = kwargs.pop('options', None) 

        JNTValue.__init__(self, entry_name = "value_entry_name", uuid=uuid, **kwargs) 

        self.instances = {} 

        self._keys = {} 

        """The different instances of the values (indexed on index) 

        """ 

 

    def create_config_value(self, **kwargs): 

        """ 

        """ 

        return self._create_config_value(**kwargs) 

 

    def create_poll_value(self, **kwargs): 

        """ 

        """ 

        return self._create_poll_value(**kwargs) 

 

    def _create_config_value(self, **kwargs): 

        """Create a config value associated to the main value 

        """ 

        index = kwargs.pop('index', 0) 

        help = kwargs.pop('help', 'A value config') 

        label = kwargs.pop('label', 'config') 

        uuid = kwargs.pop('uuid', '%s_%s' % (self.uuid,'config')) 

        type = kwargs.pop('type', 0x02) 

        get_data_cb = kwargs.pop('get_data_cb', self.get_config) 

        set_data_cb = kwargs.pop('set_data_cb', self.set_config) 

        return JNTValue(uuid=uuid, help=help, label=label, 

            index=index, type=type, 

            get_data_cb=get_data_cb, set_data_cb=set_data_cb, 

            cmd_class=COMMAND_CONFIGURATION, genre=0x03, is_writeonly=False, is_readonly=False, 

            master_config_value=self) 

 

    def set_config(self, node_uuid, index, data): 

        """ 

        """ 

        if index not in self.instances: 

            self.instances[index] = {} 

        try: 

            if 'config' not in self.instances[index] or self.instances[index]['config'] != data: 

                self.instances[index]['config'] = data 

                self.options.set_option(node_uuid, '%s_%s_%s'%(self.uuid, 'config', index), data) 

        except: 

            logger.exception('[%s] - Exception when writing %s_%s_%s for node %s', self.__class__.__name__, self.uuid, 'config', index, node_uuid) 

 

    def get_config(self, node_uuid, index): 

        """ 

        """ 

        if index not in self.instances: 

            self.instances[index] = {} 

        if 'config' not in self.instances[index]: 

            self.instances[index]['config'] = None 

        if index != 0: 

            if self.instances[index]['config'] is None: 

                try: 

                    self.instances[index]['config'] = self.options.get_option(node_uuid, '%s_%s_%s'%(self.uuid, 'config', index)) 

                except: 

                    logger.exception('[%s] - Exception when retrieving %s_%s_%s for node %s', self.__class__.__name__, self.uuid, 'config', index, node_uuid) 

        else: 

            stopped = False 

            i = 0 

            while not stopped: 

                try: 

                    data = self.options.get_option(node_uuid, '%s_%s_%s'%(self.uuid, 'config', i)) 

                    #~ print "get data", self.uuid, data 

                    if data is not None: 

                        if i not in self.instances: 

                            self.instances[i] = {} 

                        self.instances[i]['config'] = data 

                        i += 1 

                    else: 

                        stopped = True 

                except: 

                    logger.exception('[%s] - Exception when retrieving %s_%s_%s for node %s', self.__class__.__name__, self.uuid, 'config', i, node_uuid) 

        if index not in self.instances: 

            return None 

        return self.instances[index]['config'] 

 

    def _create_poll_value(self, **kwargs): 

        """Create a poll value associated to the main value 

        """ 

        index = kwargs.pop('index', 0) 

        help = kwargs.pop('help', 'The poll delay of the value') 

        label = kwargs.pop('label', 'poll_delay') 

        uuid = kwargs.pop('uuid', '%s_%s' % (self.uuid,'poll')) 

        default = kwargs.pop('default', 30) 

        self._update_poll(default) 

        units = kwargs.pop('units', "seconds") 

        get_data_cb = kwargs.pop('get_data_cb', self._get_poll) 

        set_data_cb = kwargs.pop('set_data_cb', self._set_poll) 

        return JNTValue(uuid=uuid, help=help, label=label, 

            index=index, units=units, poll_delay=default, 

            get_data_cb=get_data_cb, set_data_cb=set_data_cb, 

            cmd_class=COMMAND_CONFIGURATION, genre=0x03, type=0x04, is_writeonly=False, is_readonly=False) 

 

    def _update_poll(self, data): 

        """ 

        """ 

        if data > 0: 

            self.is_polled = True 

            self.poll_delay = data 

        else: 

            self.is_polled = False 

            self.poll_delay = 0 

 

    def _set_poll(self, node_uuid, index, data): 

        """ 

        """ 

        try: 

            if index not in self.instances: 

                self.instances[index] = {} 

            if index not in self.instances or self.instances[index]['poll'] != int(data): 

                self.instances[index]['poll'] = int(data) 

                self.options.set_option(node_uuid, '%s_%s_%s'%(self.uuid, 'poll', index), data) 

                if index == 0: 

                    self._update_poll(self.instances[index]['poll']) 

        except: 

            logger.exception('[%s] - Exception when writing %s_%s_%s for node %s', self.__class__.__name__, self.uuid, 'poll', index, node_uuid) 

 

    def _get_poll(self, node_uuid, index): 

        """ 

        """ 

        if index not in self.instances: 

            self.instances[index] = {} 

        if 'poll' not in self.instances[index]: 

            self.instances[index]['poll'] = None 

        if self.instances[index]['poll'] is None: 

            try: 

                data = self.options.get_option(node_uuid, '%s_%s_%s'%(self.uuid, 'poll', index)) 

                if data is None: 

                    data = self.poll_delay 

                data = int(data) 

                self.instances[index]['poll'] = data 

                if index == 0: 

                    self._update_poll(data) 

                return data 

            except: 

                logger.exception('[%s] - Exception when retrieving %s_%s_%s for node %s', self.__class__.__name__, self.uuid, 'poll', index, node_uuid) 

        return self.instances[index]['poll'] 

 

    def get_length(self, node_uuid=None): 

        """Returns the number of defindes instances 

        """ 

        ret = [] 

        i=0 

        stopped = False 

        while not stopped : 

            if i in self.instances and \ 

               ( ('config' in self.instances[i] and self.instances[i]['config'] is not None) or \ 

                 ('data' in self.instances[i] and self.instances[i]['data'] is not None) ): 

                ret.append(self.instances[i]) 

                i += 1 

            else: 

                stopped = True 

        return len(ret) 

 

    def get_max_index(self, node_uuid=None): 

        """ 

        """ 

        return len(self.get_index_configs())-1 

 

    def get_index_configs(self): 

        """ 

        """ 

        ret = [] 

        if len(self.instances) > 0 : 

            #~ print "_instances", self.instances 

            i=0 

            stopped = False 

            while not stopped : 

                if i in self.instances  and 'config' in self.instances[i] and self.instances[i]['config'] is not None: 

                    ret.append(self.instances[i]['config']) 

                    i += 1 

                else: 

                    stopped = True 

        #~ print "ret of index_configs", ret 

        return ret 

 

    def get_data_index(self, node_uuid=None, index=None, config=None): 

        """ 

        """ 

        try: 

            if node_uuid is None: 

                node_uuid = self.node_uuid 

            if config is not None: 

                configs = self.get_index_configs() 

                i = 0 

                for conf in configs: 

                    if config == conf: 

                        index = i 

                        break 

                    i += 1 

            if index is None: 

                index = self.index 

            if index not in self.instances: 

                self.instances[index] = {'data':None, 'config':None} 

            if 'data' not in self.instances[index]: 

                self.instances[index]['data'] = None 

            if self.instances[index]['data'] is None and self.genre == 0x03: 

                #It's a config, try to retrieve option from config 

                self.instances[index]['data'] = self.convert(self.options.get_option(node_uuid, '%s_%s'%(self.uuid, index))) 

            if self._data is not None: 

                self.instances[index]['data'] = self._data 

            if self.instances[index]['data'] is None: 

                self.instances[index]['data'] = self.default 

            return self.instances[index]['data'] 

        except: 

            logger.exception('[%s] - Exception when retrieving %s_%s_%s for node %s', self.__class__.__name__, self.uuid, 'poll', index, node_uuid) 

        return self.default 

 

    def set_data_index(self, node_uuid=None, index=None, config=None, data=None): 

        """ 

        """ 

        if node_uuid is None: 

            node_uuid = self.node_uuid 

        if config is not None: 

            configs = self.get_index_configs() 

            i = 0 

            for conf in configs: 

                if config == conf: 

                    index = i 

                    break 

                i += 1 

        if index is None: 

            index = self.index 

        if index not in self.instances: 

            self.instances[index] = {} 

        if 'data' not in self.instances[index]: 

            self.instances[index]['data'] = None 

        #~ print index, self.instances[index]['data'], data 

        try: 

            #~ self.instances[index]['data'] = self.default 

            if node_uuid is None: 

                node_uuid = self.node_uuid 

            if index is None: 

                index = self.index 

            self.instances[index]['data'] = data 

            if index == 0: 

                self._data = data 

            #~ print "Ok" 

            if self.genre == 0x03: 

                #~ print "Ok", '%s_%s'%(self.uuid, index) 

                self.options.set_option(node_uuid, '%s_%s'%(self.uuid, index), data) 

            #~ print index, self.instances[index]['data'] 

        except: 

            logger.exception('[%s] - Exception when setting %s_%s_%s for node %s', self.__class__.__name__, self.uuid, 'data', index, node_uuid) 

 

    def to_dict_with_index(self, index, initial=None): 

        """Retrieve a json version of the value 

        """ 

        if initial is None: 

            initial = JNTValue.to_dict(self) 

        configs = self.get_index_configs() 

        res = {} 

        res.update(initial) 

        #~ print "len(configs)", len(configs) 

        if len(configs) == 0: 

            return res 

        res['index'] = index 

        res['label'] = "%s (%s)" % (res['label'], configs[index]) 

        if index in self.instances and 'data' in self.instances[index]: 

            res['data'] = self.instances[index]['data'] 

        elif self._get_data_cb is not None: 

            res['data'] = self._get_data_cb(self.node_uuid, index) 

        else: 

            res['data'] = self.default 

        #~ print "---------------------------------------------------------- res ", res 

        return res 

 

    def to_dict_with_indexes(self): 

        """Retrieve a dict version of the value 

        """ 

        res = JNTValue.to_dict(self) 

        #~ print "self.instances[0] %s"%self.instances[0] 

        #~ print "---------------------------------------------------------- self.get_max_index() ", self.get_max_index() 

        #~ print "---------------------------------------------------------- self.instances ", self.instances 

        if self.get_max_index() == -1 or 'config' not in self.instances[0]: 

            return res 

        if self.get_max_index() == -1 or self.instances[0]['config'] is None: 

            return {} 

        ret = {} 

        try: 

            #~ configs = self.get_index_configs() 

            #~ print "self.get_index_configs() %s"%configs 

            i = 0 

            #~ print i, res['label'] 

            #~ print i, '%s'%self.instances 

            #~ print i, '%s'%self.instances[i] 

            while i <= self.get_max_index(): 

                #~ print "---------------------------------------------------------- i ", i 

                #~ print i, res['label'], configs[i] 

                ret[i] = self.to_dict_with_index(i, res) 

                i += 1 

        except: 

            logger.exception('[%s] - Exception in to_dict_with_indexes', self.__class__.__name__) 

        #~ print "---------------------------------------------------------- ret ", ret 

        return ret 

 

    def to_json_with_indexes(self): 

        """Retrieve a json version of the value 

        """ 

        try: 

            res = self.to_dict_with_indexes() 

            #~ print "to_json_with_indexes", res 

            return json_dumps(res) 

        except: 

            logger.exception('[%s] - Exception in to_json_with_indexes', self.__class__.__name__) 

        return None