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

# -*- 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" 

 

# Set default logging handler to avoid "No handler found" warnings. 

import logging 

logger = logging.getLogger(__name__) 

 

from classes import GENRE_DESC, VALUE_DESC 

from utils import json_dumps 

from options import JNTOptions, string_to_bool 

 

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

#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 JNTValue(object): 

    def __init__(self, uuid="a_unik_identifier_for_the_value_on_the_controller", node_uuid="the_unik_identifier_of_the_node", get_data_cb = None, set_data_cb = None, **kwargs): 

        """ 

        :param int uuid: the unique uuid of the value on the controller 

        """ 

        self.uuid = uuid 

        """The UUID of the value""" 

        self.node_uuid = node_uuid 

        """The UUID of the node the valuse is attached to""" 

        self.voice_uuid = kwargs.get('voice_uuid', None) 

        """The voice_uuid of this value. Can be use to a""" 

        self.hadd = kwargs.get('hadd', None) 

        """The HADD of the node associated to this value""" 

        self.cmd_class = kwargs.get('cmd_class', 0x0000) 

        """The command class implemented by the value""" 

        self.is_readonly = kwargs.get('is_readonly', True) 

        """Is the value readonly""" 

        self.is_writeonly = kwargs.get('is_writeonly', True) 

        """Is the value writeonly""" 

        self.default = kwargs.get('default', None) 

        """The default data of the value""" 

        self.label = kwargs.get('label', None) 

        """The help of the value""" 

        self.help = kwargs.get('help', None) 

        """The label of the value""" 

        self.units = kwargs.get('units', None) 

        """The units of the value""" 

        self.list_items = kwargs.get('list_items', None) 

        """The list of all valid items when the value type is list. This list is separated with pipe : '|'""" 

        self.max = kwargs.get('max', None) 

        """The max of the value""" 

        self.min = kwargs.get('min', None) 

        """The min of the value""" 

        self.genre = kwargs.get('genre', 0x01) 

        """The genre of the value""" 

        self.type = kwargs.get('type', 0x01) 

        """The type of the value""" 

        self.index = kwargs.get('index', 0) 

        """Get the value index (use with multi_instance nodes)""" 

        self.is_polled = kwargs.get('is_polled', False) 

        """Say if the value is polled""" 

        self.poll_delay = kwargs.get('poll_delay', 0) 

        """The delay between 2 polls""" 

        self._get_data_cb = get_data_cb 

        """The callback to get the value""" 

        self._set_data_cb = set_data_cb 

        """The callback to get the value""" 

        self._data = None 

        """The last known data of the value""" 

        self.reply_hadd = None 

        """The hadd to reply to""" 

        self.master_config_value = kwargs.get('master_config_value', None) 

        """The master_value. Used with value_factory entries""" 

 

    def convert(self, data): 

        """ 

        Convert data to the type of value 

 

        :return: The data of the value 

        :rtype: depending of the type of the value 

 

        """ 

        if data is not None: 

            try: 

                if self.type == 0x01: 

                    #Bool 

                    return string_to_bool(data) 

                elif self.type == 0x02 or self.type == 0x04 or self.type == 0x07: 

                    #Byte or Int or Short 

                    return int(data) 

                elif self.type == 0x03: 

                    #Decimal 

                    return float(data) 

                elif self.type == 0x16: 

                    #Array 

                     return data.split('|') 

                logger.warning('[%s] - Do not convert data %s to %s.', self.__class__.__name__, data, VALUE_DESC[self.type]['label']) 

                return data 

            except: 

                logger.exception('[%s] - Exception when converting data %s to %s', self.__class__.__name__, data, VALUE_DESC[self.type]['label']) 

                return None 

        return None 

 

    @property 

    def data(self): 

        """ 

        Get the current data of the value. 

 

        :return: The data of the value 

        :rtype: depending of the type of the value 

 

        """ 

        if self._get_data_cb is not None: 

            self._data = self._get_data_cb(self.node_uuid, self.index) 

        if self._data is None: 

            self._data = self.default 

        return self._data 

 

    @data.setter 

    def data(self, value): 

        """ 

        Set the data of the value. 

 

        Best practice: Use check_data before setting it: 

 

        new_val = value.check_data(some_data) 

        if new_val != None: 

            value.data = new_val 

 

        :param value: The new data value 

        :type value: 

 

        """ 

        res = True 

        if self._set_data_cb is not None: 

            res = self._set_data_cb(self.node_uuid, self.index, value) 

        if res == True: 

            self._data = value 

        return res 

 

    def start(self): 

        """Start the value. Can be used to start a thread to acquire data. 

        This method is not called in the nodeman process. 

        Programmer must call it manually, ie at stat machine change. 

 

        """ 

        return True 

 

    def stop(self): 

        """Stop the value. 

        This method is not called in the nodeman process. 

        Programmer must call it manually, ie at stat machine change. 

 

        """ 

        return True 

 

    def from_dict(self, adict): 

        """Update internal dict from adict 

        """ 

        self.__dict__.update(adict) 

        return self 

 

    def to_dict(self): 

        """Retrieve a dict version of the value. 

        Include all properties except : 

         - ends with lock, _cb, 

         - starts with timer, _ 

        So use the naming convention above or ask for update if you really need it. 

 

        """ 

        res = {} 

        res.update(self.__dict__) 

        for key in res.keys(): 

            if key.endswith('lock') or key.endswith('_cb') \ 

              or key.startswith('_') or key.startswith('timer') \ 

              or key in ['instances', 'options', 'master_config_value']: 

                del res[key] 

        res['data'] = self.data 

        return res 

 

    def to_json(self): 

        """Retrieve a json version of the value 

        """ 

        res = self.to_dict() 

        return json_dumps(res) 

 

def value_system_heartbeat(get_data_cb, set_data_cb): 

    return JNTValue( uuid='heartbeat', 

        help='The heartbeat delay in seconds', 

        label='heartbeat', 

        units='seconds', 

        index=0, 

        cmd_class=COMMAND_CONFIGURATION, 

        genre=0x04, 

        max=3000, 

        min=0, 

        type=0x04, 

        is_readonly=False, 

        is_writeonly=False, 

        is_polled=False, 

        poll_delay=0, 

        get_data_cb = get_data_cb, 

        set_data_cb = set_data_cb 

    ) 

 

def value_system_config_timeout(get_data_cb, set_data_cb): 

    return JNTValue( uuid='config_timeout', 

        help='The config timeout before applying configuration and rebooting', 

        label='config_timeout', 

        units='seconds', 

        index=0, 

        cmd_class=COMMAND_CONFIGURATION, 

        genre=0x04, 

        max=3000, 

        min=0, 

        type=0x04, 

        is_readonly=False, 

        is_writeonly=False, 

        is_polled=False, 

        poll_delay=0, 

        get_data_cb = get_data_cb, 

        set_data_cb = set_data_cb 

    ) 

 

def value_system_hadd(get_data_cb, set_data_cb): 

    return JNTValue( uuid='hadd', 

        help='The Janitoo Home address', 

        label='hadd', 

        units='', 

        index=0, 

        cmd_class=COMMAND_CONFIGURATION, 

        genre=0x04, 

        type=0x20, 

        is_readonly=False, 

        is_writeonly=False, 

        is_polled=False, 

        poll_delay=0, 

        get_data_cb = get_data_cb, 

        set_data_cb = set_data_cb 

    ) 

 

def value_config_name(get_data_cb, set_data_cb): 

    return JNTValue( uuid='name', 

        help='The name of the node', 

        label='name', 

        index=0, 

        cmd_class=COMMAND_CONFIGURATION, 

        genre=0x03, 

        type=0x08, 

        is_readonly=False, 

        is_writeonly=False, 

        is_polled=False, 

        poll_delay=0, 

        get_data_cb = get_data_cb, 

        set_data_cb = set_data_cb 

    ) 

 

def value_config_location(get_data_cb, set_data_cb): 

    return JNTValue( uuid='location', 

        help='The location of the node', 

        label='location', 

        index=0, 

        cmd_class=COMMAND_CONFIGURATION, 

        genre=0x03, 

        type=0x08, 

        is_readonly=False, 

        is_writeonly=False, 

        is_polled=False, 

        poll_delay=0, 

        get_data_cb = get_data_cb, 

        set_data_cb = set_data_cb 

    ) 

 

def value_config_poll(uuid, get_data_cb, set_data_cb, help='The poll delay of the value', label="poll_delay", index=0, default = 300): 

    return JNTValue( uuid=uuid, 

        help=help, 

        label=label, 

        index=index, 

        cmd_class=COMMAND_CONFIGURATION, 

        genre=0x03, 

        type=0x04, 

        is_readonly=False, 

        is_writeonly=False, 

        is_polled=False, 

        default = default, 

        poll_delay=0, 

        get_data_cb = get_data_cb, 

        set_data_cb = set_data_cb 

    )