-
Notifications
You must be signed in to change notification settings - Fork 0
/
plugin.py
228 lines (188 loc) · 8.65 KB
/
plugin.py
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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Telenet Python Plugin
#
# Author: Filip Demaertelaere
#
# Plugin to get the download volume for Telenet
#
"""
<plugin key="Telenet" name="Telenet" author="Filip Demaertelaere" version="3.0.0">
<params>
<param field="Mode1" label="Username" width="200px" required="true" default=""/>
<param field="Mode2" label="Password" width="200px" required="true" default="" password="true"/>
<param field="Mode5" label="Hours between update" width="120px" required="true" default="1"/>
<param field="Mode6" label="Debug" width="120px">
<options>
<option label="True" value="Debug"/>
<option label="False" value="Normal" default="True"/>
</options>
</param>
</params>
</plugin>
"""
#IMPORTS
import sys, os
major,minor,x,y,z = sys.version_info
sys.path.append('/usr/lib/python3/dist-packages')
sys.path.append('/usr/local/lib/python{}.{}/dist-packages'.format(major, minor))
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
from domoticz_tools import *
import Domoticz
import Telenet
import threading
import queue
import time
#DEFAULT IMAGE
_IMAGE = 'Telenet'
#THE HAERTBEAT IS EVERY 10s
_HOUR = MINUTE*60
################################################################################
# Start Plugin
################################################################################
class BasePlugin:
def __init__(self):
self.debug = DEBUG_OFF
self.runAgain = MINUTE
self.Login = False
self.ErrorLevel = 0
self.MyTelenet = None
self.tasksQueue = queue.Queue()
self.tasksThread = threading.Thread(name='QueueThread', target=BasePlugin.handleTasks, args=(self,))
def onStart(self):
Domoticz.Debug('onStart called')
# Debugging On/Off
self.debug = DEBUG_ON if Parameters['Mode6'] == 'Debug' else DEBUG_OFF
Domoticz.Debugging(self.debug)
if self.debug == DEBUG_ON:
DumpConfigToLog(Parameters, Devices)
# Check if images are in database
if _IMAGE not in Images:
Domoticz.Image('Telenet.zip').Create()
# Timeout all devices
TimeoutDevice(Devices, All=True)
# Start thread
self.MyTelenet = Telenet.Telenet(Parameters['Mode1'], Parameters['Mode2'])
self.tasksThread.start()
self.tasksQueue.put({'Action': 'Login'})
def onStop(self):
Domoticz.Debug('onStop called')
# Signal queue thread to exit
self.tasksQueue.put(None)
self.tasksThread.join()
# Wait until queue thread has exited
Domoticz.Debug('Threads still active: {} (should be 1)'.format(threading.active_count()))
endTime = time.time() + 70
while (threading.active_count() > 1) and (time.time() < endTime):
for thread in threading.enumerate():
if thread.name != threading.current_thread().name:
Domoticz.Debug('Thread {} is still running, waiting otherwise Domoticz will abort on plugin exit.'.format(thread.name))
time.sleep(1.0)
Domoticz.Debug('Plugin stopped')
def onConnect(self, Connection, Status, Description):
Domoticz.Debug('onConnect called ({}) with status={}'.format(Connection.Name, Status))
def onMessage(self, Connection, Data):
Domoticz.Debug("onMessage called: {} - {}".format(Connection.Name, Data['Status']))
def onCommand(self, Unit, Command, Level, Hue):
Domoticz.Debug('onCommand called for Unit: {} - Parameter: {} - Level: {}'.format(Unit, Command, Level))
def onNotification(self, Name, Subject, Text, Status, Priority, Sound, ImageFile):
Domoticz.Debug('Notification: {}, {}, {}, {}, {}, {}, {}'.format(
Name, Subject, Text, Status, Priority, Sound, ImageFile
))
def onDisconnect(self, Connection):
Domoticz.Debug('onDisconnect called ({})'.format(Connection.Name))
def onHeartbeat(self):
self.runAgain -= 1
if self.runAgain <= 0:
self.tasksQueue.put({'Action': 'GetInternetVolume'})
if self.ErrorLevel == 3:
TimeoutDevice(Devices, All=True)
Domoticz.Error('Unable to get data from Telenet.')
if self.ErrorLevel and not self.ErrorLevel % 2:
self.tasksQueue.put({'Action': 'Login'})
self.runAgain = _HOUR*float(Parameters['Mode5'].replace(',','.'))
# Thread to handle the messages
def handleTasks(self):
try:
Domoticz.Debug('Entering tasks handler')
while True:
task = self.tasksQueue.get(block=True)
if task is None:
Domoticz.Debug('Exiting task handler')
try:
self.MyTelenet.close()
except AttributeError:
pass
self.tasksQueue.task_done()
break
Domoticz.Debug('Handling task: {}.'.format(task['Action']))
if task['Action'] == 'Login':
self.Login = False
if self.MyTelenet.login() and self.MyTelenet.get_user_data():
self.Login = True
else:
self.ErrorLevel += 1
Domoticz.Error('Unable to login on MyTelenet with defined hardware settings or no contract data found.')
elif task['Action'] == 'GetInternetVolume':
if self.Login and self.MyTelenet.login() and self.MyTelenet.get_user_data():
if self.MyTelenet.telemeter():
for Contract in self.MyTelenet.telemeter_info:
Unit = FindUnitFromName(Devices, Parameters, Contract['municipality'])
if not Unit:
Unit = GetNextFreeUnit(Devices)
description = CreateDescription(Contract['businessidentifier'])
Domoticz.Device(Unit=Unit, Name=Contract['municipality'], Description=description, TypeName="Custom", Options={"Custom": "0;GB"}, Image=Images[_IMAGE].ID, Used=1).Create()
TimeoutDevice(Devices, Unit=Unit)
if 'total_usage_gb' in Contract:
UpdateDevice(False, Devices, Unit, 0, '%.3f' % Contract['total_usage_gb'])
Domoticz.Debug('Telenet Usage: {}'.format(Contract['total_usage_gb']))
self.ErrorLevel = 0
else:
self.ErrorLevel += 1
else:
self.ErrorLevel += 1
else:
self.ErrorLevel += 1
else:
Domoticz.Error('TaskHandler: unknown action code {}'.format(task['Action']))
Domoticz.Debug('Finished handling task: {}.'.format(task['Action']))
self.tasksQueue.task_done()
except Exception as err:
Domoticz.Error('General error TaskHandler: {}'.format(err))
# For debugging
import traceback
Domoticz.Debug('Login error TRACEBACK: {}'.format(traceback.format_exc()))
with open('{}Telenet_traceback.txt'.format(Parameters['HomeFolder']), "a") as myfile:
myfile.write('{}'.format(traceback.format_exc()))
myfile.write('---------------------------------\n')
self.tasksQueue.task_done()
global _plugin
_plugin = BasePlugin()
def onStart():
global _plugin
_plugin.onStart()
def onStop():
global _plugin
_plugin.onStop()
def onConnect(Connection, Status, Description):
global _plugin
_plugin.onConnect(Connection, Status, Description)
def onMessage(Connection, Data):
global _plugin
_plugin.onMessage(Connection, Data)
def onCommand(Unit, Command, Level, Hue):
global _plugin
_plugin.onCommand(Unit, Command, Level, Hue)
def onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile):
global _plugin
_plugin.onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile)
def onDisconnect(Connection):
global _plugin
_plugin.onDisconnect(Connection)
def onHeartbeat():
global _plugin
_plugin.onHeartbeat()
################################################################################
# Specific helper functions
################################################################################