Skip to content

Commit 850341c

Browse files
authored
Merge pull request #981 from SergeoLacruz/develop
Add plugin for piusv
2 parents 7aac02b + 334c192 commit 850341c

File tree

9 files changed

+771
-0
lines changed

9 files changed

+771
-0
lines changed

piusv/__init__.py

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
#!/usr/bin/env python3
2+
# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab
3+
#########################################################################
4+
# Copyright 2020- <AUTHOR> <EMAIL>
5+
#########################################################################
6+
# This file is part of SmartHomeNG.
7+
# https://www.smarthomeNG.de
8+
# https://knx-user-forum.de/forum/supportforen/smarthome-py
9+
#
10+
# Sample plugin for new plugins to run with SmartHomeNG version 1.8 and
11+
# upwards.
12+
#
13+
# SmartHomeNG is free software: you can redistribute it and/or modify
14+
# it under the terms of the GNU General Public License as published by
15+
# the Free Software Foundation, either version 3 of the License, or
16+
# (at your option) any later version.
17+
#
18+
# SmartHomeNG is distributed in the hope that it will be useful,
19+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
20+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21+
# GNU General Public License for more details.
22+
#
23+
# You should have received a copy of the GNU General Public License
24+
# along with SmartHomeNG. If not, see <http://www.gnu.org/licenses/>.
25+
#
26+
#########################################################################
27+
28+
from lib.model.smartplugin import SmartPlugin
29+
from lib.item import Items
30+
31+
from .webif import WebInterface
32+
33+
import smbus
34+
35+
class piusv(SmartPlugin):
36+
"""
37+
Main class of the Plugin. Does all plugin specific stuff and provides the update functions for the items
38+
"""
39+
40+
PLUGIN_VERSION = '0.1.0'
41+
42+
def __init__(self, sh):
43+
"""
44+
Initalizes the plugin.
45+
46+
If you need the sh object at all, use the method self.get_sh() to get it. There should be almost no need for
47+
a reference to the sh object anymore.
48+
49+
"""
50+
51+
# Call init code of parent class (SmartPlugin)
52+
super().__init__()
53+
54+
self._item_dict = {}
55+
self._cyclic_update_active = False
56+
self.alive = False
57+
self.suspended = False
58+
59+
# check if shNG is running on Raspberry Pi
60+
try:
61+
self.webif_pagelength = self.get_parameter_value('webif_pagelength')
62+
self.poll_cycle = self.get_parameter_value('poll_cycle')
63+
self.i2c_address = self.get_parameter_value('i2c_address')
64+
except KeyError as e:
65+
self.logger.critical("Plugin '{}': Inconsistent plugin (invalid metadata definition: {} not defined)".format(self.get_shortname(), e))
66+
self._init_complete = False
67+
return
68+
69+
self.init_webinterface(WebInterface)
70+
return
71+
72+
####################################################################################
73+
# Die Parameter der Pi USV+ byteweise auslesen
74+
def get_parameter(self, index):
75+
parameters = [0,0,0,0,0,0,0,0,0,0]
76+
77+
try:
78+
self.piusv_handle.write_byte(self.i2c_address, 0x02)
79+
except (IOError):
80+
self.logger.error("get_parameter: error writing to piusv")
81+
return(0)
82+
for i in range(10):
83+
try:
84+
parameters[i] = self.piusv_handle.read_byte(self.i2c_address)
85+
except (IOError):
86+
self.logger.error("get_parameter: error reading to piusv")
87+
return(0)
88+
value = 256*parameters[index] + parameters[index+1]
89+
return value
90+
91+
# Statusbyte auslesen
92+
def get_status(self):
93+
94+
try:
95+
self.piusv_handle.write_byte(self.i2c_address, 0x00)
96+
except (IOError):
97+
self.logger.error("get_status: error writing to piusv")
98+
return(0)
99+
try:
100+
status = self.piusv_handle.read_byte(self.i2c_address)
101+
except (IOError):
102+
self.logger.error("get_status: error reading to piusv")
103+
return(0)
104+
return status
105+
106+
# Firmware auslesen
107+
def get_firmware(self):
108+
109+
version = ''
110+
try:
111+
self.piusv_handle.write_byte(self.i2c_address, 0x01)
112+
except (IOError):
113+
self.logger.error("get_get_firmware: error writing to piusv")
114+
return(0)
115+
for i in range (12):
116+
try:
117+
version = version + chr(self.piusv_handle.read_byte(self.i2c_address))
118+
except (IOError):
119+
self.logger.error("get_firmware: error reading to piusv")
120+
return(0)
121+
return version
122+
###############################################################################
123+
def run(self):
124+
"""
125+
Run method for the plugin
126+
"""
127+
self.logger.debug("Run method called")
128+
# Handle
129+
self.piusv_handle = smbus.SMBus(1)
130+
131+
# setup scheduler for device poll loop (disable the following line, if you don't need to poll the device. Rember to comment the self_cycle statement in __init__ as well)
132+
self.scheduler_add('poll_device', self.poll_device, cycle=self.poll_cycle)
133+
self.alive = True
134+
135+
def stop(self):
136+
"""
137+
Stop method for the plugin
138+
"""
139+
self.logger.debug("Stop method called")
140+
self.scheduler_remove('poll_device')
141+
self.alive = False
142+
143+
def parse_item(self, item):
144+
"""
145+
Default plugin parse_item method. Is called when the plugin is initialized.
146+
The plugin can, corresponding to its attribute keywords, decide what to do with
147+
the item in the future, like adding it to an internal array for future reference
148+
:param item: The item to process.
149+
:return: If the plugin needs to be informed of an items change you should return a call back function
150+
like the function update_item down below. An example when this is needed is the knx plugin
151+
where parse_item returns the update_item function when the attribute knx_send is found.
152+
This means that when the items value is about to be updated, the call back function is called
153+
with the item, caller, source and dest as arguments and in case of the knx plugin the value
154+
can be sent to the knx with a knx write function within the knx plugin.
155+
"""
156+
if self.has_iattr(item.conf, 'piusv_func'):
157+
self.logger.debug(f"parse item: {item}")
158+
self._item_dict[item] = self.get_iattr_value(item.conf, 'piusv_func')
159+
160+
elif self.has_iattr(item.conf, 'piusv_sys'):
161+
return self.update_item
162+
163+
def update_item(self, item, caller=None, source=None, dest=None):
164+
"""
165+
Item has been updated
166+
167+
This method is called, if the value of an item has been updated by SmartHomeNG.
168+
:param item: item to be updated towards the plugin
169+
:param caller: if given it represents the callers name
170+
:param source: if given it represents the source
171+
:param dest: if given it represents the dest
172+
"""
173+
if self.alive and caller != self.get_shortname():
174+
# code to execute if the plugin is not stopped and only, if the item has not been changed by this plugin:
175+
self.logger.info(f"Update item: {item.property.path}, item has been changed outside this plugin")
176+
177+
if self.has_iattr(item.conf, 'piusv_sys'):
178+
self.logger.debug(f"update_item was called with item {item.property.path} from caller {caller}, source {source} and dest {dest}")
179+
if self.get_iattr_value(item.conf, 'piusv_sys') == 'update' and bool(item()):
180+
self.logger.info(f"Update of all items of piusv Plugin requested. ")
181+
self.poll_device()
182+
item(False)
183+
pass
184+
185+
def poll_device(self):
186+
"""
187+
Polls for updates of the device
188+
"""
189+
# check if another cyclic cmd run is still active
190+
if self._cyclic_update_active:
191+
self.logger.warning('Triggered cyclic poll_device, but previous cyclic run is still active. Therefore request will be skipped.')
192+
return
193+
elif self.suspended:
194+
self.logger.warning('Triggered cyclic poll_device, but Plugin in suspended. Therefore request will be skipped.')
195+
return
196+
else:
197+
self.logger.info('Triggering cyclic poll_device')
198+
199+
# set lock
200+
self._cyclic_update_active = True
201+
202+
for item in self._item_dict:
203+
# self.logger.debug(f"poll_device: handle item {item.id()}")
204+
value = eval(f"self.{self.get_iattr_value(item.conf, 'piusv_func')}()")
205+
# self.logger.info(f"poll_device: {value=} for item {item.id()} will be set.")
206+
item(value, self.get_shortname())
207+
208+
# release lock
209+
self._cyclic_update_active = False
210+
211+
pass
212+
213+
def u_batt(self):
214+
return self.get_parameter(0)
215+
216+
def i_rasp(self):
217+
return self.get_parameter(2)
218+
219+
def u_rasp(self):
220+
return self.get_parameter(4)
221+
222+
def u_usb(self):
223+
return self.get_parameter(6)
224+
225+
def u_ext(self):
226+
return self.get_parameter(8)
227+
228+
def piusv_status(self):
229+
return self.get_status()
230+
231+
def piusv_firmware(self):
232+
return self.get_firmware()
233+
234+
@property
235+
def item_list(self):
236+
return list(self._item_dict.keys())
237+
238+
@property
239+
def log_level(self):
240+
return self.logger.getEffectiveLevel()

piusv/locale.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# translations for the web interface
2+
plugin_translations:
3+
'Value':
4+
de: 'Wert'
5+
en: 'Value'
6+
'Attribute':
7+
de: 'Attribut'
8+
en: 'Attribute'
9+
'Last Change':
10+
de: 'Letzte Änderung'
11+
en: 'Last Change'
12+
'Last Update':
13+
de: 'Letztes Update'
14+
en: 'Last Update'
15+
'Type':
16+
de: 'Typ'
17+
en: 'Type'

0 commit comments

Comments
 (0)