-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
modbus_init, Luxtronic2 reconnect and pack/unpack and smartvisu type error #210
base: develop
Are you sure you want to change the base?
Conversation
@@ -46,6 +56,12 @@ Defines a mapping to a attribute (read-only). All attribute values are bytes (nu | |||
### lux2_c | |||
Defines a mapping to a calculated value (read-only). All calculated values are integer (numbers). | |||
|
|||
### lux2_unpack | |||
Python lambda function. Called before the value is sent towards the device. | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The unpack option sounds like the common eval
setting for items. It evaluates the value and puts the result into the item. IMHO, I prefer to use common settings instead of having special plugin settings for all the plugins.
|
||
### lux2_pack | ||
Called before the value is written to the smarthome item. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could also be a common setting for items - something like eval_out
- which works like eval
, but the other way around when item is set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see your point and I thought about it too. Something like eval_out would work most of the time, but it would fail for something like the example below. My thinking is that a plugin should provide you with a ready to use value and the other way around should take the unencoded value. E.g. for the knx plugin you have to provide knx_dpt and the plugin handles pack/unpack stuff.
First I only created *_pack for something like below and the way I think of plugins and I did *_unpack out of symmetry. E.g. one could use *_unpack to do the word/byte/... decoding stuff and eval for some value transformation (seconds to days).
I can make the *_pack and *_unpack optional, populated to hand the values through, but I would like to keep them.
[[[dp1]]]
type = num
knx_dpt = 9
knx_send = 10/4/8
modbus_addr = Blub1 | 1 | 9 | 1
modbus_type = HoldingRegister
modbus_readInterval = -1
modbus_pack = lambda x: [int((x * 1023) / 102.3)]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ohinckel I looked a bit further into default values for modbus_pack (same for unpack and lux2).
I still don't see a good way for eval_out
. To make something like my last example work, it would have to check the caller e.g. like: eval_out = return knxVal if caller == 'KNX' else return modbusVal
I gonna stick with pack(/unpack), if you don't have a better solution.
The somewhat defaults at the moment are lambda x: x
. I think this means one does not have to use the pack/unpack functions if the type is set to list
. If *_pack is used it could be any other type and it should be possible to use eval for unpacking. I did not test that.
So again I don't see any better way.
# fail in this application, because it calles the foo without checking | ||
# if the last call finished. This could clog up the system. | ||
threading.Thread(name='Lux2_cycle', target=self.__refresh).start() | ||
threading.Thread(name='Lux2_recon', target=self._reconnect).start() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there really cases were the update cylce needs too much time? Maybe using a short timeout for querying the device could help here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See also my bug report for that. For now, it works with threading, but I could not get it working with the scheduler. I don't think it is about the socket timeout, because I also had problems with the scheduler in the modbus plugin too.
@@ -328,22 +399,44 @@ def _decode(self, identifier, value): | |||
return value | |||
|
|||
def parse_item(self, item): | |||
def __reverseListOp(param): | |||
# reversing list building of smarthome.py config parser for the | |||
# binary or opperator | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think putting the value in quotes will fix this problem too. Usually you should be using quotes around the value to avoid escaping problem.
Other setting may have this problem too, but we should not start to implement such an "unquoting mechanism" for each of these settings. A general solution, which already exists (using quotes), would be more clear and consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not know that quotes are supported, but if it works it's most definitely a better way to do it. I am going to fix it when there is time for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ohinckel I just check the config parser again and quotes are not supported right now. I also tried it and there is no magic gunk happening somewhere else.
config.py line:89...
attr, __, value = line.partition('=')
...
attr = attr.strip()
...
if '|' in value:
item[attr] = [strip_quotes(x) for x in value.split('|')]
else:
item[attr] = strip_quotes(value)
So to allow list operators in combination with quotes, it would have to ignore pipes inside of quotes and split if there are pips outside of them. I did a quick hack, see below. If you have a better solution or if I missed something let me know.
def split_pipe(s):
output = []
split_pos = []
quotes = ['"',"'"]
pipe = '|'
in_quoate = False
start_quote = None
for i in range(0, len(s)):
if not in_quoate and s[i] == pipe:
split_pos.append(i)
if not in_quoate and s[i] in quotes:
start_quote = s[i]
in_quoate = True
elif in_quoate and s[i] == start_quote:
in_quoate = False
if len(split_pos) > 0:
output.append(s[0:split_pos[0]])
for i in range(0,len(split_pos)):
if i+1 < len(split_pos):
output.append(s[split_pos[i]+1:split_pos[i+1]])
else:
output.append(s[split_pos[i]+1:])
output = [strip_quotes(x) for x in output]
return output
else:
return strip_quotes(s)
s = """'123|456'|"789'10'|1112"|131415 """
current = [strip_quotes(x) for x in s.split('|')]
for i in current:
print(i)
print('-'*10)
x = split_pipe(s)
for i in x:
print(i)
print('-'*10)
x = split_pipe('1')
print(x)
Added some debug gunk. Verbose output option, status for each master in var/modbus/*.txt, ... Added random start time for reads to even out load
modbus_init: readme
Luxtronic2: readme
The count string handed from smartvisu was not casted to int.