From 4be1e31522575d46255eb95bb1b6ba3c3836f510 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 16 Dec 2017 22:47:25 +0100 Subject: [PATCH 01/11] Fixed debug levels, updated config files and readme, added example item files --- avdevice/AVDeviceInit.py | 9 +- avdevice/Denon_Items.yaml | 346 ++++++++++++++++++++++++++++++++++++ avdevice/Pioneer_Items.yaml | 218 +++++++++++++++++++++++ avdevice/README.md | 132 ++++---------- avdevice/__init__.py | 49 ++--- avdevice/denon-avr6300.txt | 46 +++-- avdevice/sc-lx86.txt | 24 ++- avdevice/vsx-923.txt | 22 ++- 8 files changed, 690 insertions(+), 156 deletions(-) create mode 100755 avdevice/Denon_Items.yaml create mode 100755 avdevice/Pioneer_Items.yaml diff --git a/avdevice/AVDeviceInit.py b/avdevice/AVDeviceInit.py index 869e8fc3d..581bc12f1 100755 --- a/avdevice/AVDeviceInit.py +++ b/avdevice/AVDeviceInit.py @@ -27,6 +27,7 @@ import codecs import re +import os import threading VERBOSE1 = logging.DEBUG - 1 VERBOSE2 = logging.DEBUG - 2 @@ -305,7 +306,7 @@ def _create_responsecommands(self): else: self._special_commands['Input']['Command'].append(response) self._special_commands['Input']['Ignore'].append(0) - self.logger.log(VERBOSE1, "Initializing {}: Found Input Command and added it to display commands.".format(self._name)) + self.logger.log(VERBOSE2, "Initializing {}: Found Input Command and added it to display commands.".format(self._name)) elif (function == 'title' or function == 'station' or function == 'genre'): if 'Nowplaying' not in self._special_commands: self._special_commands['Nowplaying'] = {'Command': [response]} @@ -340,7 +341,7 @@ def _create_responsecommands(self): self.logger.log(VERBOSE1, "Initializing {}: Adding additional list to function {} for response {} with value {}.".format( self._name, function, response, self._response_commands[response])) except Exception as err: - self.logger.log(VERBOSE1, "Initializing {}: Creating response command for: {}. Message: {}".format(self._name, response, err)) + self.logger.log(VERBOSE2, "Initializing {}: Creating response command for: {}. Message: {}".format(self._name, response, err)) self._response_commands[response] = [[ valuelength, commandlength, position, item, function, 'zone{}'.format(zone), inverse, expectedtype, functiontype]] self._response_commands[response] = sorted(self._response_commands[response], key=lambda x: x[0], reverse=True) @@ -372,8 +373,7 @@ def _read_commandfile(self): try: self.logger.debug("Initializing {}: Starting to read file {}. Lock is {}".format( self._name, self._model, self._threadlock_standard.locked())) - filename = '{}/plugins/avdevice/{}.txt'.format( - self._sh.base_dir, self._model) + filename = '{}/{}.txt'.format(os.path.abspath(os.path.dirname(__file__)), self._model) commands = codecs.open(filename, 'r', 'utf-8') zones = [0] @@ -413,6 +413,7 @@ def _read_commandfile(self): try: row[8] = row[8].replace('string', 'str') row[8] = row[8].replace('num', 'int,float') + row[8] = row[8].replace('|', ',') if row[8] == '': row[8] = 'bool,int,str' except Exception: diff --git a/avdevice/Denon_Items.yaml b/avdevice/Denon_Items.yaml new file mode 100755 index 000000000..38d301606 --- /dev/null +++ b/avdevice/Denon_Items.yaml @@ -0,0 +1,346 @@ +%YAML 1.1 +--- +Denon: + type: foo + + Powerall: + type: bool + visu_acl: rw + avdevice_zone0: power + + Update: + type: bool + visu_acl: rw + avdevice_zone0: statusupdate + enforce_updates: 'yes' + + Power: + type: bool + visu_acl: rw + avdevice_zone1: power + + Mute: + type: bool + visu_acl: rw + avdevice_zone1: mute + + VolumeFL: + type: num + visu_acl: rw + avdevice_zone1: volumefl + cache: 'True' + + VolumeFLUp: + type: bool + visu_acl: rw + avdevice_zone1: volumefl+ + enforce_updates: 'yes' + + VolumeFLDown: + type: bool + visu_acl: rw + avdevice_zone1: volumefl- + enforce_updates: 'yes' + + VolumeFR: + type: num + visu_acl: rw + avdevice_zone1: volumefr + cache: 'True' + + VolumeFRUp: + type: bool + visu_acl: rw + avdevice_zone1: volumefr+ + enforce_updates: 'yes' + + VolumeFRDown: + type: bool + visu_acl: rw + avdevice_zone1: volumefr- + enforce_updates: 'yes' + + Volume: + type: num + visu_acl: rw + avdevice_zone1: volume + cache: 'True' + + VolumeMax: + type: num + visu_acl: ro + avdevice_zone1: volumemax + + VolumeUp: + type: bool + visu_acl: rw + avdevice_zone1: volume+ + enforce_updates: 'yes' + + VolumeDown: + type: bool + visu_acl: rw + avdevice_zone1: volume- + enforce_updates: 'yes' + + VolumeLow: + type: bool + enforce_updates: 'yes' + visu_acl: rw + avdevice_zone1: volumelow + + VolumeHigh: + type: bool + enforce_updates: 'yes' + visu_acl: rw + avdevice_zone1: volumehigh + + Eco: + type: str + visu_acl: rw + avdevice_zone0: eco + + Source: + type: str + visu_acl: rw + avdevice_zone1: input + + Music: + type: bool + visu_acl: ro + eval: 1 if ((sh.Denon.Source() == 'DVD' or sh.Denon.Source() == 'CD' or sh.Denon.Source() == 'NET') and sh.Denon.Power()) else 0 + eval_trigger: + - Denon.Source + - Denon.Power + enforce_updates: 'yes' + + Mode: + type: str + visu_acl: rw + avdevice_zone1: mode + + Dialog: + type: num + visu_acl: rw + avdevice_zone1: dialog + enforce_updates: 'no' + + Dialogtoggle: + type: bool + visu_acl: rw + avdevice_zone1: dialogtoggle + + Subwoofer: + type: num + visu_acl: rw + avdevice_zone1: subwoofer + enforce_updates: 'no' + + Subwoofertoggle: + type: bool + visu_acl: rw + avdevice_zone1: subwoofertoggle + + CinemaEQ: + type: bool + visu_acl: rw + avdevice_zone1: cinemaeq + + Mainspeakers: + type: str + visu_acl: rw + avdevice_zone1: mainspeakers + + Sleep: + type: num + visu_acl: rw + avdevice_zone1: sleep + + Standby: + type: foo + visu_acl: rw + avdevice_zone1: standby + + Bass: + type: num + visu_acl: rw + avdevice_zone1: bass + + BassUp: + type: num + visu_acl: rw + avdevice_zone1: bass+ + enforce_updates: 'yes' + + BassDown: + type: num + visu_acl: rw + avdevice_zone1: bass- + enforce_updates: 'yes' + + Tone: + type: bool + visu_acl: rw + avdevice_zone1: tone + + Trebble: + type: num + visu_acl: rw + avdevice_zone1: trebble + + TrebbleUp: + type: num + visu_acl: rw + avdevice_zone1: trebble+ + enforce_updates: 'yes' + + TrebbleDown: + type: num + visu_acl: rw + avdevice_zone1: trebble- + enforce_updates: 'yes' + + Videoinput: + type: str + visu_acl: rw + avdevice_zone1: videoinput + + Audioinput: + type: str + visu_acl: rw + avdevice_zone1: audioinput + + Videoparams: + type: str + visu_acl: rw + avdevice_zone1: videoparams + + Power2: + type: bool + visu_acl: rw + avdevice_zone2: power + + Source2: + type: str + visu_acl: rw + avdevice_zone2: input + + Music: + type: bool + visu_acl: ro + eval: 1 if ((sh.Denon.Source2() == 'DVD' or sh.Denon.Source2() == 'CD' or sh.Denon.Source2() == 'NET') and sh.Denon.Power2()) else 0 + eval_trigger: + - Denon.Source2 + - Denon.Power2 + + Mute2: + type: bool + visu_acl: rw + avdevice_zone2: mute + + Volume2: + type: num + visu_acl: rw + avdevice_zone2: volume + + Fading: + type: num + + VolumeUp2: + type: bool + visu_acl: rw + avdevice_zone2: volume+ + enforce_updates: 'yes' + + VolumeDown2: + type: bool + visu_acl: rw + avdevice_zone2: volume- + enforce_updates: 'yes' + + VolumeHigh2: + type: bool + visu_acl: rw + avdevice_zone2: volumehigh + enforce_updates: 'yes' + + VolumeLow2: + type: bool + visu_acl: rw + avdevice_zone2: volumelow + enforce_updates: 'yes' + + Sleep2: + type: num + visu_acl: rw + avdevice_zone2: sleep + + Standby2: + type: foo + visu_acl: rw + avdevice_zone2: standby + + Power3: + type: bool + visu_acl: rw + avdevice_zone3: power + + Source3: + type: str + visu_acl: rw + avdevice_zone3: input + + Musik: + type: bool + visu_acl: ro + eval: 1 if ((sh.Denon.Source3() == 'DVD' or sh.Denon.Source3() == 'CD' or sh.Denon.Source3() == 'NET') and sh.Denon.Power3()) else 0 + eval_trigger: + - Denon.Source3 + - Denon.Power3 + + Mute3: + type: bool + visu_acl: rw + avdevice_zone3: mute + + Volume3: + type: num + visu_acl: rw + avdevice_zone3: volume + + Fading: + type: num + + VolumeUp3: + type: bool + visu_acl: rw + avdevice_zone3: volume+ + enforce_updates: 'yes' + + VolumeDown3: + type: bool + visu_acl: rw + avdevice_zone3: volume- + enforce_updates: 'yes' + + VolumeHigh3: + type: bool + visu_acl: rw + avdevice_zone3: volumehigh + enforce_updates: 'yes' + + VolumeLow3: + type: bool + visu_acl: rw + avdevice_zone3: volumelow + enforce_updates: 'yes' + + Sleep3: + type: num + visu_acl: rw + avdevice_zone3: sleep + + Standby3: + type: foo + visu_acl: rw + avdevice_zone3: standby diff --git a/avdevice/Pioneer_Items.yaml b/avdevice/Pioneer_Items.yaml new file mode 100755 index 000000000..df3a7ad88 --- /dev/null +++ b/avdevice/Pioneer_Items.yaml @@ -0,0 +1,218 @@ +%YAML 1.1 +--- + Pioneer: + type: foo + + Update: + type: bool + visu_acl: rw + avdevice_zone0: statusupdate + enforce_updates: 'yes' + + Speakers: + type: num + visu_acl: rw + avdevice_zone1: speakers + + SpeakerA: + type: bool + visu_acl: rw + avdevice_zone1_speakers: 1 + + SpeakerB: + type: bool + visu_acl: rw + avdevice_zone1_speakers: 2 + + Power: + type: bool + visu_acl: rw + avdevice_zone1: power + + Mute: + type: bool + visu_acl: rw + avdevice_zone1: mute + + Volume: + type: num + visu_acl: rw + avdevice_zone1: volume + cache: 'True' + + Fading: + type: num + + VolumeUp: + type: bool + visu_acl: rw + avdevice_zone1: volume+ + enforce_updates: 'yes' + + VolumeDown: + type: bool + visu_acl: rw + avdevice_zone1: volume- + enforce_updates: 'yes' + + VolumeLow: + type: bool + enforce_updates: 'yes' + visu: rw + avdevice_zone1: volumelow + + VolumeHigh: + type: bool + enforce_updates: 'yes' + visu: rw + avdevice_zone1: volumehigh + + Source: + type: num + visu_acl: rw + avdevice_zone1: input + + Music: + type: bool + visu_acl: ro + eval: 1 if (sh.Pioneer.Source() == 13 and sh.Pioneer.Power()) else 0 + eval_trigger: + - Pioneer.Source + - Pioneer.Power + enforce_updates: 'yes' + + Mode: + type: num + visu_acl: rw + avdevice_zone1: mode + + Playingmode: + type: foo + visu_acl: ro + avdevice_zone1: playingmode + + Bass: + type: num + visu_acl: rw + avdevice_zone1: bass + + BassUp: + type: bool + visu_acl: rw + avdevice_zone1: bass+ + enforce_updates: 'yes' + + BassDown: + type: bool + visu_acl: rw + avdevice_zone1: bass- + enforce_updates: 'yes' + + Dialog: + type: num + visu_acl: rw + avdevice_zone1: dialog + + Trebble: + type: num + visu_acl: rw + avdevice_zone1: trebble + + TrebbleUp: + type: bool + visu_acl: rw + avdevice_zone1: trebble+ + enforce_updates: 'yes' + + TrebbleDown: + type: bool + visu_acl: rw + avdevice_zone1: trebble- + enforce_updates: 'yes' + + Tone: + type: bool + visu_acl: rw + avdevice_zone1: tone + + Display: + type: str + visu_acl: ro + avdevice_zone0: display + + HDMI: + type: num + visu_acl: ro + avdevice_zone1: HDMI + + Title: + type: str + visu_acl: ro + avdevice_zone0: title + + Station: + type: str + visu_acl: ro + avdevice_zone0: station + + Genre: + type: str + visu_acl: ro + avdevice_zone0: genre + + Power2: + type: bool + visu_acl: rw + avdevice_zone2: power + + Source2: + type: num + visu_acl: rw + avdevice_zone2: input + + Musik: + type: bool + visu_acl: ro + eval: 1 if (sh.Pioneer.Source2() == 13 and sh.Pioneer.Power2()) else 0 + eval_trigger: + - Musik.Source2 + - Musik.Power2 + enforce_updates: 'no' + + Mute2: + type: bool + visu_acl: rw + avdevice_zone2: mute + + Volume2: + type: num + visu_acl: rw + avdevice_zone2: volume + cache: 'True' + + Fading: + type: num + + VolumeUp2: + type: bool + visu_acl: rw + avdevice_zone2: volume+ + enforce_updates: 'yes' + + VolumeDown2: + type: bool + visu_acl: rw + avdevice_zone2: volume- + enforce_updates: 'yes' + + VolumeHigh2: + type: num + visu_acl: rw + avdevice_zone2: volumehigh + enforce_updates: 'yes' + + VolumeLow2: + type: num + visu_acl: rw + avdevice_zone2: volumelow + enforce_updates: 'yes' diff --git a/avdevice/README.md b/avdevice/README.md index 07a5f475d..9f6b87745 100755 --- a/avdevice/README.md +++ b/avdevice/README.md @@ -29,7 +29,7 @@ avdevice: rs232_port: /dev/ttyUSB1 #rs232_baudrate: 9600 #rs232_timeout: 0.1 - #ignoreresponse: 'RGB,RGC,RGD,GBH,GHH,LM0,VTA,AUA,AUB' + #ignoreresponse: 'RGB,RGC,RGD,GBH,GHH,VTA,AUA,AUB' #forcebuffer: 'GEH01020, GEH04022, GEH05024' #inputignoredisplay: '' #dependson_item: '' @@ -58,20 +58,20 @@ avdevice: * `rs232_port`: If you use a RS232 cable to communicate with your device (highly recommended!) define the interface port * `rs232_baudrate`: baudrate for RS232 * `rs232_timeout`: timeout for RS232 -* `ignoreresponse`: list of values. the plugin doesn't care about responses from the device starting with the given values. List responses for menu navigation, etc. For Pioneer receivers the following list is recommended: RGB, RGC, RGD, GBH, GHH, LM0, VTA, AUA, AUB +* `ignoreresponse`: list of values. the plugin doesn't care about responses from the device starting with the given values. List responses for menu navigation, etc. For Pioneer receivers the following list is recommended: RGB, RGC, RGD, GBH, GHH, VTA, AUA, AUB * `forcedbuffer`: list of strings. If for whatever reason you don't want to buffer the response from your device you can still define specific responses that should get buffered. This is important for responses that change or get sent very quickly. Artist, title, radio station, etc. are examples that should be put here. For Pioneer receivers the following list is recommended: GEH01020, GEH04022, GEH05024 * `inputignoredisplay`: list of int. The value of the LCD display on your receiver might get updated very often, e.g. when it shows song titles as a scrolling text. To avoid constant display updates and therefore possible confusion with relevant answers of your device listing source inputs like internet radio, LAN streaming, etc. here is highly recommended. For Pioneer receivers the following list is recommended: 26,38,40,41,44,17,02,48,0 * `dependson_item`: item. If given item has given value the commands are sent to the device, otherwise they are not. Relevant if you have your device connected to a power socket that can be turned off. * `dependson_value`: boolean. If given item has given value the commands are sent to the device, otherwise they are not. Relevant if you have your device connected to a power socket that can be turned off. -* `errorresponse`: list of strings. The standard error responses from your device. For Pioneer receivers they are "E" followed by a number. If no values are provided error answers from your device might get recognized much slower but actually should still get recognized. +* `errorresponse`: list of strings. The standard error responses from your device. For Pioneer receivers they are "E" followed by a number. If no values are provided error answers from your device might get recognized much slower but actually should still get recognized. * `resetonerror`: boolean. Reset the value of the item that could not be updated. E.g. you set the volume of zone 2 to "100". If either the dependson item is off or the device sends an error response or after several connection and send retries the expected response is not received, the volume item gets set to value it had before you sent the command. That way you avoid having a wrong value displayed in your Visu. * `depend0_power0`: boolean. If the dependson item is off the power off all zones are set to off. This is especially relevant for a correct representation in your Visu when you have a powered on device but turn off the power socket. * `depend0_volume0`: boolean. Same as above but in this case the volume is set to 0 for all zones. This is for Visu purposes only. * `sendretries`: integer. This value defines how often a command should be sent when receiving a wrong answer from the device. * `resendwait`: float. Seconds the plugin should wait between each resend retry. -* `reconnectretries`: integer. If the plugin can not connect to the device it retries this often. This is especially useful for TCP connections on devices that are plugged into a switchable socket as most receivers need about 40-50 seconds to boot their network device. -* `secondstokeep`: integer. Seconds the plugin should temporarily save a command to retry later on after establishing a connection. This is especially useful for TCP connections on devices that are plugged into a switchable socket as most receivers need about 40-50 seconds to boot their network device. -* `responsebuffer`: integer or boolean. Set this to a number to collect quickly received responses in a buffer and evaluate them collectively. The standard value should be fine and prevent responses getting lost. Some receivers might first respond to a command with an update of the display and then with the actual value. The buffer ensures the correct evaluation of the response. +* `reconnectretries`: integer. If the plugin can not connect to the device it retries this often. This is especially useful for TCP connections on devices that are plugged into a switchable socket as most receivers need about 40-50 seconds to boot their network device. +* `secondstokeep`: integer. Seconds the plugin should temporarily save a command to retry later on after establishing a connection. This is especially useful for TCP connections on devices that are plugged into a switchable socket as most receivers need about 40-50 seconds to boot their network device. +* `responsebuffer`: integer or boolean. Set this to a number to collect quickly received responses in a buffer and evaluate them collectively. The standard value should be fine and prevent responses getting lost. Some receivers might first respond to a command with an update of the display and then with the actual value. The buffer ensures the correct evaluation of the response. * `autoreconnect`: boolean. Automatically tries to reconnect if no response is received or connection is lost. This should not be necessary as the plugin always tries to reconnect before sending a command. ### items.yaml @@ -80,7 +80,10 @@ avdevice: specifiy the zone number and instance. The command has to correspond to a "base" command in the relevant text configuration file in the avdevice plugin folder named the same as the "model" configured in plugin.yaml. -Only use the first part of the command before the space, e.g. "power" instead of "power on" or "power off". "volume" instead of "volume set", etc. +It is important to set the correct type for each item. The Pioneer RS232 codeset expects bool and int types only. +For example to set the listening mode to "pure direct", the item has to be int and you set it to the value "8". + +Full item examples are included as separate yaml files for Pioneer and Denon devices. In general the items are setup the same independent of the AV device model. The example include the tested items/commands and allow easy copy/paste. #### Example @@ -89,81 +92,12 @@ Only use the first part of the command before the space, e.g. "power" instead of Pioneer: type: foo - Update: - type: bool - visu_acl: rw - avdevice_zone0@pioneer_one: statusupdate - enforce_updates: 'yes' - knx_dpt: 1 - - Running: - type: bool - visu_acl: ro - enforce_updates: 'yes' - value: 0 - Power: type: bool visu_acl: rw avdevice_zone1@pioneer_one: power enforce_updates: 'no' knx_dpt: 1 - - Mute: - type: bool - visu_acl: rw - avdevice_zone1@pioneer_one: mute - enforce_updates: 'no' - knx_dpt: 1 - - Volume: - type: num - visu_acl: rw - enforce_updates: 'no' - avdevice_zone1@pioneer_one: volume - - VolumeUp: - type: bool - visu_acl: rw - avdevice_zone1@pioneer_one: volume+ - enforce_updates: 'yes' - - VolumeDown: - type: bool - visu_acl: rw - avdevice_zone1@pioneer_one: volume- - enforce_updates: 'yes' - - VolumeLow: - type: bool - enforce_updates: 'yes' - avdevice_zone1@pioneer_one: volumelow - visu_acl: rw - - VolumeHigh: - type: bool - enforce_updates: 'yes' - visu_acl: rw - avdevice_zone1@pioneer_one: volumehigh - - Source: - type: num - visu_acl: rw - knx_dpt: 7 - avdevice_zone1@pioneer_one: input - enforce_updates: 'no' - - Power2: - type: bool - visu_acl: rw - avdevice_zone2@pioneer_one: power - enforce_updates: 'no' - - Source2: - type: num - visu_acl: rw - avdevice_zone2@pioneer_one: input - enforce_updates: 'no' ``` ### model.txt @@ -176,9 +110,9 @@ Each line holds one specific command that should be sent to the device. You also * `zone`: Number of zone. Has to correspond to the attribute in item.yaml. E.g. for zone 1 use "avdevice_zone1: command". Zone 0 holds special commands like navigating in the menu, display reponse, information about currently playing songs, etc. -* `function`: name of the function. You can name them whatever you like. You reference this value in the item using avdevice_zoneX: function. +* `function`: name of the function. You can name it whatever you like. You reference this value in the item using avdevice_zoneX: function. -* `functiontype`: for boolean functions use "on" or "off". For commands setting a specific value like source, input mode, volume, etc. use "set". To increase ot decrease a value use the corresponding "increase" or "decrease". For everything else leave empty! +* `functiontype`: for boolean functions use "on" or "off". For commands setting a specific value like source, input mode, volume, etc. use "set". To increase or decrease a value use the corresponding "increase" or "decrease". For everything else leave empty! * `send`: the command to be sent, e.g. power off is "PF" for Pioneer receivers. You can use a pipe "|" if more than one command should be sent. That might be necessary for power on commands via RS232, e.g. for Pioneer receivers to power on "PO|PO" forces the plugin to send the "PO" command twice. Use stars "\*" to specify the format of the value to be sent. Let's say your device expects the value for volume as 3 digits, a "\*\*\*VL" ensures that even setting the volume to "5" sends the command as "005VL" @@ -190,9 +124,9 @@ Each line holds one specific command that should be sent to the device. You also * `invertresponse`: some devices are stupid enough to reply with a "0" for "on" and "1" for "off". E.g. a Pioneer receiver responds with "PWR0" if the device is turned on. Configure with "yes" if your device is quite stupid, too. -* `maxvalue`: You can define the maximum value for setting a specific function. This might be most relevant for setting the volume. If you configure this with "100" and set the volume to "240" (via Visu or CLI) the value will get clamped by the plugin and set to "100". +* `maxvalue`: You can define the maximum value for setting a specific function. This might be most relevant for setting the volume. If you configure this with "100" and set the volume to "240" (via Visu or CLI) the value will get clamped by the plugin and set to "100". -* `responsetype`: Defines the type of the response value and can be set to "bool", "num" or "string" or a mixture of them. Most response types are set automatically on startup but you can force specific type using this value. It is recommended to use the values suggested in the txt files that come with the plugin. +* `responsetype`: Defines the type of the response value and can be set to "bool", "num" or "str" or a mixture of them (separated by a pipe "|"). Most response types are set automatically on startup but you can force a specific type using this value. It is recommended to use the values suggested in the txt files that come with the plugin. #### Example @@ -201,31 +135,25 @@ Each line holds one specific command that should be sent to the device. You also ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MAXVALUE; RESPONSETYPE 1; power; on; PO|PO; ?P; PWR*; RW; yes 1; power; off; PF; ?P; PWR*; RW; yes -1; volume+; VU; ; VOL; W -1; volume-; VD; ; VOL; W -1; volumehigh; 150VL; ?V; VOL150; W -1; volumelow; 110VL; ?V; VOL110; W +1; volume+; increase; VU; ; VOL; W +1; volume-; decrease; VD; ; VOL; W 1; volume; set; ***VL; ?V; VOL***; RW; ; 185 -1; mute; on; MO; ?M; MUT*; RW; yes -1; mute; off; MF; ?M; MUT*; RW; yes 1; input; set; **FN; ?F; FN**; RW +1; speakers; set; *SPK; ?SPK; SPK*; RW 2; power; on; APO|APO; ?AP; APR*; RW; yes 2; power; off; APF; ?AP; APR*; RW; yes -2; volume+; ZU; ; ZV; W -2; volume-; ZD; ; ZV; W -2; volumehigh; 75ZV; ?ZV; ZV75; W -2; volumelow; 45ZV; ?ZV; ZV45; W -2; volume; set; **ZV; ?ZV; ZV**; RW; ; 81 -2; mute; on; Z2MO; ?Z2M; Z2MUT*; RW; yes -2; mute; off; Z2MF; ?Z2M; Z2MUT*; RW; yes -2; input; set; **ZS; ?ZS; Z2F**; RW -0; title; ; ; GEH01020; R -0; station; ; ; GEH04022; R -0; genre; ; ; GEH05024; R -0; display; ?FL; ?FL; FL******************************; R -1; speakers; set; *SPK; ?SPK; SPK*; RW -``` +0; title; ; ; ; GEH01020; R +0; station; ; ; ; GEH04022; R +0; genre; ; ; ; GEH05024; R +0; display; ; ?FL; ?FL; FL******************************; R -### Debugging +``` -You can use level 9 (VERBOSE1) and 8 (VERBOSE2) as debugging levels in logging.yaml +### Troubleshooting +1.) Have a look at the smarthome logfile. If you can't figure out the reason for your problem, change the verbose level in logging.yaml. +You can use level 10 (=DEBUG), 9 (VERBOSE1) and 8 (VERBOSE2) as debugging levels. +2.) Concerning send and response entries in the textfile, make sure the number of stars correspond to the way your device wants to receive the command or sends the response. +Example 1: Your Pioneer receiver expects the value for the volume as three digits. So the command needs three stars. If you now set the item to a value with only two digits, like 90, the plugin converts the command automatically to have a leading 0. +Example 2: Your Denon receiver responds with values like ON, OFF or STANDBY to power commands. Replace every character with a star! ON = 2 stars, OFF = 3 stars, etc. +Example 3: Sending or receiving strings of different length like "CD", "GAME", etc. should be set up with one star only. Set the responsetype accordingly! +3.) Set the response type in the textfile to the correct value. The plugin tries to anticipate the correct value but that doesn't always work. The sleep timer of Denon devices is a wonderfully sick example: You can set values betwwen 1 and 120 to set the timer in minutes. If you want to turn it off, the receiver expects the value "OFF" instead of a zero. The plugin fixes that problem if you set the responsetype to bool|num. As soon as you set the item to 0, it magically converts that value to "OFF" and the other way around when receiving "OFF". diff --git a/avdevice/__init__.py b/avdevice/__init__.py index 34842cd8e..6baee7ffd 100644 --- a/avdevice/__init__.py +++ b/avdevice/__init__.py @@ -26,12 +26,9 @@ import logging from lib.model.smartplugin import SmartPlugin from itertools import groupby -import threading -import os import io import time import re -import codecs import errno import serial import socket @@ -47,9 +44,9 @@ class AVDevice(SmartPlugin): ALLOW_MULTIINSTANCE = True PLUGIN_VERSION = "1.3.2" - def __init__(self, smarthome, + def __init__(self, smarthome, model='', - ignoreresponse='RGB,RGC,RGD,GBH,GHH,LM0,VTA,AUA,AUB', + ignoreresponse='RGB,RGC,RGD,GBH,GHH,VTA,AUA,AUB', errorresponse='E02,E04,E06', forcebuffer='GEH01020, GEH04022, GEH05024', inputignoredisplay='', @@ -97,7 +94,7 @@ def __init__(self, smarthome, self._parsinginput = [] try: - self._model = self.get_parameter_value('model') + self._model = self.get_parameter_value('model') self._resend_wait = float(self.get_parameter_value('resendwait')) self._secondstokeep = int(self.get_parameter_value('secondstokeep')) self._auto_reconnect = self.get_parameter_value('autoreconnect') @@ -160,7 +157,7 @@ def _resetitem(self): self.logger.log(VERBOSE1, "Resetting {}: Cannot find Sendingcommand. Using first Command in queue: {}. Message: {}".format(self._name, response, e)) sorted_response_commands = sorted(self._response_commands, key=len, reverse=True) for key in sorted_response_commands: - self.logger.log(VERBOSE1, "Resetting {}: Trying to reset Item. Comparing: {} with {}".format(self._name, key, response)) + self.logger.log(VERBOSE2, "Resetting {}: Trying to reset Item. Comparing: {} with {}".format(self._name, key, response)) for resp in response: for entry in self._response_commands[key]: try: @@ -309,12 +306,12 @@ def _write_itemsdict(self, data): sorted_response_commands = sorted(self._response_commands, key=len, reverse=True) updated = 0 for command in sorted_response_commands: - self.logger.log(VERBOSE1, "Storing Values {}: Comparing command {}.".format(self._name, command)) + self.logger.log(VERBOSE2, "Storing Values {}: Comparing command {}.".format(self._name, command)) if data == command: self.logger.debug("Storing Values {}: Response is identical to expected response. Skipping Storing: {}".format(self._name, data)) break for entry in self._response_commands[command]: - self.logger.log(VERBOSE1, "Storing Values {}: Comparing entry {}.".format(self._name, entry)) + self.logger.log(VERBOSE2, "Storing Values {}: Comparing entry {}.".format(self._name, entry)) if entry[1] == entry[2]: commandstart = 0 commandend = entry[2] @@ -337,7 +334,7 @@ def _write_itemsdict(self, data): self._items[zone][function]['Value'] = receivedvalue self.logger.debug("Storing Values {}: Found writeable dict key: {}. Zone: {}. Value {} with type {}. Function: {}.".format(self._name, command, zone, receivedvalue, expectedtype, function)) updated = 1 - return self._items[zone][function], receivedvalue, expectedtype + return self._items[zone][function], receivedvalue, expectedtype break else: self.logger.debug("Storing Values {}: Found writeable dict key: {} with type {}, but received value {} is type {}. Not writing value!".format(self._name, command, expectedtype, receivedvalue, type(receivedvalue))) @@ -357,7 +354,7 @@ def _write_itemsdict(self, data): if updated == 1: return self._items[zone][function], receivedvalue, expectedtype else: - return 'empty', 'empty', 'empty' + return 'empty', 'empty', 'empty' # Finding relevant items for the plugin based on the avdevice keyword def parse_item(self, item): @@ -557,7 +554,7 @@ def _processing_response(self, socket): break self._send_commands.pop(0) self._sendingcommand = 'done' - self.logger.debug("Processing Response {}: Response {} is same as expected {}. Removing command from send list. It is now: {}. Ignore responses are: {}".format( + self.logger.debug("Processing Response {}: Response {} is same as expected {} and defined as response to be ignored. Removing command from send list. It is now: {}. Ignore responses are: {}".format( self._name, line, compare, self._send_commands, self._ignore_response)) sending = self._send('command', 'commandremoval') except Exception as err: @@ -644,7 +641,7 @@ def run(self): self._items = self.init._addstatusupdate() self._response_commands, self._special_commands = self.init._create_responsecommands() self._power_commands = self.init._create_powercommands() - self._query_commands, self._query_zonecommands = self.init._create_querycommands() + self._query_commands, self._query_zonecommands = self.init._create_querycommands() self.logger.log(VERBOSE1, "Initializing {}: Functions: {}, Number of Zones: {}".format(self._name, self._functions, self._number_of_zones)) self.logger.log(VERBOSE1, "Initializing {}: Responsecommands: {}.".format(self._name, self._response_commands)) self.logger.log(VERBOSE1, "Initializing {}: Special Commands: {}".format(self._name, self._special_commands)) @@ -991,7 +988,7 @@ def _duplicateindex(seq,item): expectedindices = _duplicateindex(expectedresponse, expected) for expectedindex in expectedindices: - if self._send_commands[expectedindex] not in updatedcommands: + if self._send_commands[expectedindex] not in updatedcommands: expectedtype = self._send_commands[expectedindex].split(',') try: expectedtype[3:] = [','.join(expectedtype[3:])] @@ -1000,9 +997,11 @@ def _duplicateindex(seq,item): testvalue = '' if not valuetype == testvalue: updatedcommands.append(self._send_commands[expectedindex]) - self.logger.log(VERBOSE2, "Parsing Input {}: Test Value is not same as Valuetype: {}. Adding to Sendcommands again.".format(self._name, testvalue, valuetype)) + self.logger.log(VERBOSE2, "Parsing Input {}: Test Value {} of {} is not same as Valuetype: {}. Adding to Sendcommands again.".format( + self._name, testvalue, self._send_commands[expectedindex], valuetype)) else: - self.logger.log(VERBOSE2, "Parsing Input {}: Test Value is same as Valuetype: {}. Not adding to Sendcommands again.".format(self._name, testvalue, valuetype)) + self.logger.log(VERBOSE1, "Parsing Input {}: Test Value {} of {} is same as Valuetype: {}. Not adding to Sendcommands again.".format( + self._name, testvalue, self._send_commands[expectedindex], valuetype)) except Exception as err: self.logger.log(VERBOSE1, "Parsing Input {}: Write to dict problems: {}".format(self._name, err)) @@ -1075,7 +1074,7 @@ def _duplicateindex(seq,item): if not data == 'ERROR' and data not in self._error_response: self.logger.log(VERBOSE1, "Parsing Input {}: Starting to compare values for data {}.".format(self._name, data)) for key in sorted_response_commands: - self.logger.log(VERBOSE1, "Parsing Input {}: Starting to compare values for data {} with key: {}.".format(self._name, data, key)) + self.logger.log(VERBOSE2, "Parsing Input {}: Starting to compare values for data {} with key: {}.".format(self._name, data, key)) if data == key: tempcommands = [] for entry in self._send_commands: @@ -1180,19 +1179,19 @@ def _duplicateindex(seq,item): value = receivedvalue self.logger.debug("Parsing Input {}: Found key {} in response at position {} with value {}.".format( self._name, key, index, value)) - + for entry in self._keep_commands: self.logger.log(VERBOSE1, "Parsing Input {}: Testing Keep Command entry {}".format( self._name, entry, self._keep_commands.get(entry))) if data in self._keep_commands.get(entry).split(",")[2].split("|"): self.logger.debug("Parsing Input {}: Removing {} from Keep Commands {} because corresponding value received.".format( self._name, entry, self._keep_commands.get(entry), self._keep_commands)) - self._keep_commands.pop(entry) - break + self._keep_commands.pop(entry) + break if function in self._items[zone].keys(): self._items[zone][function]['Value'] = value self.logger.log(VERBOSE1, "Parsing Input {}: Updated Item dict {}".format(self._name, self._items[zone][function])) - + for singleitem in item: singleitem(value, 'AVDevice', self._tcp) self.logger.debug("Parsing Input {}: Updating Item {} with {} Value: {}.".format( @@ -1227,7 +1226,7 @@ def _duplicateindex(seq,item): if self._send_commands == []: self._sendingcommand = 'done' self.logger.log(VERBOSE1, "Parsing Input {}: Finished. Send Commands: {}, sending Command: {}. Data: {}".format( - self._name, self._send_commands, self._sendingcommand, data)) + self._name, self._send_commands, self._sendingcommand, data)) except Exception as err: self.logger.error("Parsing Input {}: Problems parsing input. Error: {}".format(self._name, err)) finally: @@ -1610,8 +1609,10 @@ def update_item(self, item, caller=None, source=None, dest=None): value = value.upper() self.logger.debug("Updating Item for avdevice_{}: Value has to be string. Value is {}".format(self._name.lower(), value)) try: - command_re = commandinfo[2].replace('*', '{}'.format(value)) - response = commandinfo[4].replace('*', '{}'.format(value)) + command_re = commandinfo[2].replace('*', '{}'.format(value), 1) + command_re = command_re.replace('*', '') + response = commandinfo[4].replace('*', '{}'.format(value), 1) + response = response.replace('*', '') except Exception: command_re = commandinfo[2] response = commandinfo[4] diff --git a/avdevice/denon-avr6300.txt b/avdevice/denon-avr6300.txt index 1676ba907..9db8423e4 100644 --- a/avdevice/denon-avr6300.txt +++ b/avdevice/denon-avr6300.txt @@ -1,13 +1,13 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MAXVALUE; RESPONSETYPE 0; power; on; PWON|PWON; PW?; PW**; RW 0; power; off; PWSTANDBY; PW?; PW*******; RW -0; eco; set; ECO*; ECO?; ECO*; RW; ; ; string,bool +0; eco; set; ECO*; ECO?; ECO*; RW; ; ; str|bool 1; power; on; ZMON; ZM?; ZM**; RW 1; power; off; ZMOFF; ZM?; ZM***; RW 1; mute; on; MUON; MU?; MU**; RW 1; mute; off; MUOFF; MU?; MU***; RW -1; sleep; set; SLP***; SLP?; SLP***; RW; ; 120; num,bool -1; standby; set; STBY*; STBY?; STBY*; RW; ; ; string +1; sleep; set; SLP***; SLP?; SLP***; RW; ; 120; num|bool +1; standby; set; STBY*; STBY?; STBY*; RW; ; ; str 1; volume; set; MV**; MV?; MV**; RW; ; 90 1; volume+; increase; MVUP; ; MV; W 1; volume-; decrease; MVDOWN; ; MV; W @@ -20,15 +20,31 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; 1; volumelow; ; MV50; MV?; MV50; W; ; ; num 1; volumehigh; ; MV75; MV?; MV75; W; ; ; num 1; volumemax; ; MVMAX **; MV?; MVMAX **; RW -1; input; set; SI*; SI?; SI*; RW; ; ; string -1; mode; set; MS*; MS?; MS*; RW; ; ; string -1; audioinput; set; SD*; SD?; SD*; RW; ; ; string,bool -1; videoinput; set; SV*; SV?; SV*; RW; ; ; string,bool -1; digitalinput; set; DC*; DC?; DC*; RW; ; ; string -1; video; set; VS*; ; VS*; RW; ; ; string +1; input; set; SI*; SI?; SI*; RW; ; ; str +1; mode; set; MS*; MS?; MS*; RW; ; ; str +1; audioinput; set; SD*; SD?; SD*; RW; ; ; str +1; videoinput; set; SV*; SV?; SV*; RW; ; ; str|bool +1; videoparams; set; VS*; ; VS*; RW; ; ; str +1; tone; on; PSTONE CTRL ON; PSTONE CTRL ?; PSTONE CTRL **; RW +1; tone; off; PSTONE CTRL OFF; PSTONE CTRL ?; PSTONE CTRL ***; RW +1; bass; set; PSBAS **; PSBAS ?; PSBAS **; RW; ; 99 +1; trebble; set; PSTRE **; PSTRE ?; PSTRE **; RW; ; 99 +1; bass+; increase; PSBAS UP; ; PSBAS; W +1; bass-; decrease; PSBAS DOWN; ; PSBAS; W +1; trebble+; increase; PSTRE UP; ; PSTRE; W +1; trebble-; decrease; PSTRE DOWN; ; PSTRE; W +1; dialogtoggle; on; PSDIL ON; PSDIL ?; PSDIL **; RW +1; dialogtoggle; off; PSDIL OFF; PSDIL ?; PSDIL ***; RW +1; dialog; set; PSDIL **; PSDIL ?; PSDIL **; RW; ; 62 +1; subwoofertoggle; on; PSSWL ON; PSSWL ?; PSSWL **; RW +1; subwoofertoggle; off; PSSWL OFF; PSSWL ?; PSSWL ***; RW +1; subwoofer; set; PSSWL **; PSSWL ?; PSSWL **; RW; ; 62 +1; cinemaeq; on; PSCINEMA EQ.ON; PSCINEMA EQ. ?; PSCINEMA EQ.**; RW +1; cinemaeq; off; PSCINEMA EQ.OFF; PSCINEMA EQ. ?; PSCINEMA EQ.***; RW +1; mainspeakers; set; PSSP:*; PSSP: ?; PSSP:*; RW; ; ; str 2; power; on; Z2ON; Z2?; Z2**; RW 2; power; off; Z2OFF; Z2?; Z2***; RW -2; input; set; Z2*; Z2?; Z2*; RW; ; ; string +2; input; set; Z2*; Z2?; Z2*; RW; ; ; str 2; mute; on; Z2MUON; Z2MU?; Z2MU**; RW 2; mute; off; Z2MUOFF; Z2MU?; Z2MU***; RW 2; volume+; increase; Z2UP; ; Z2; W @@ -36,11 +52,11 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; 2; volumelow; ; Z250; MV?; Z250; W; ; ; num 2; volumehigh; ; Z275; MV?; Z275; W; ; ; num 2; volume; set; Z2**; Z2?; Z2**; RW; ; 90 -2; standby; set; Z2STBY*; Z2STBY?; Z2STBY*; RW; ; ; string -2; sleep; set; Z2SLP***; Z2SLP?; Z2SLP***; RW; ; 120; num,bool +2; standby; set; Z2STBY*; Z2STBY?; Z2STBY*; RW; ; ; str +2; sleep; set; Z2SLP***; Z2SLP?; Z2SLP***; RW; ; 120; num|bool 3; power; on; Z3ON; Z3?; Z3**; RW 3; power; off; Z3OFF; Z3?; Z3***; RW -3; input; set; Z3*; Z3?; Z3*; RW; ; ; string +3; input; set; Z3*; Z3?; Z3*; RW; ; ; str 3; mute; on; Z3MUON; Z3MU?; Z3MU**; RW 3; mute; off; Z3MUOFF; Z3MU?; Z3MU***; RW 3; volume+; increase; Z3UP; ; Z3; W @@ -48,5 +64,5 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; 3; volumelow; ; Z350; MV?; Z350; W; ; ; num 3; volumehigh; ; Z375; MV?; Z375; W; ; ; num 3; volume; set; Z3**; Z3?; Z3**; RW; ; 90 -3; standby; set; Z3STBY*; Z3STBY?; Z3STBY*; RW; ; ; string -3; sleep; set; Z3SLP***; Z3SLP?; Z3SLP***; RW; ; 120; num,bool \ No newline at end of file +3; standby; set; Z3STBY*; Z3STBY?; Z3STBY*; RW; ; ; str +3; sleep; set; Z3SLP***; Z3SLP?; Z3SLP***; RW; ; 120; num|bool diff --git a/avdevice/sc-lx86.txt b/avdevice/sc-lx86.txt index 7206df569..ec4c8daf0 100755 --- a/avdevice/sc-lx86.txt +++ b/avdevice/sc-lx86.txt @@ -1,19 +1,31 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MAXVALUE; RESPONSETYPE 1; power; on; PO|PO; ?P; PWR*; RW; yes 1; power; off; PF; ?P; PWR*; RW; yes -1; volume+; ; VU; ; VOL; W -1; volume-; ; VD; ; VOL; W +1; volume+; increase; VU; ; VOL; W +1; volume-; decrease; VD; ; VOL; W 1; volumehigh; ; 150VL; ?V; VOL150; W 1; volumelow; ; 110VL; ?V; VOL110; W 1; volume; set; ***VL; ?V; VOL***; RW; ; 161 1; mute; on; MO; ?M; MUT*; RW; yes 1; mute; off; MF; ?M; MUT*; RW; yes 1; mode; set; ****SR; ?S; SR****; RW +1; playingmode; ; ?L; ?L; LM****; R +1; speakers; set; *SPK; ?SPK; SPK*; RW 1; input; set; **FN; ?F; FN**; RW +1; tone; on; 1TO; ?TO; TO*; RW +1; tone; off; 0TO; ?TO; TO*; RW +1; bass; set; **BA; ?BA; BA**; RW; ; 12 +1; trebble; set; **TR; ?TR; TR**; RW; ; 12 +1; bass+; increase; BI; ; BA; W +1; bass-; decrease; BD; ; BA; W +1; trebble+; increase; TI; ; TR; W +1; trebble-; decrease; TD; ; TR; W +1; dialog; set; *ATH; ?ATH; ATH*; RW +1; HDMI; set; *HO; ?HO; HO*; RW 2; power; on; APO|APO; ?AP; APR*; RW; yes 2; power; off; APF; ?AP; APR*; RW; yes -2; volume+; ; ZU; ; ZV; W -2; volume-; ; ZD; ; ZV; W +2; volume+; increase; ZU; ; ZV; W +2; volume-; decrease; ZD; ; ZV; W 2; volumehigh; ; 70ZV; ?ZV; ZV70; W 2; volumelow; ; 45ZV; ?ZV; ZV45; W 2; volume; set; **ZV; ?ZV; ZV**; RW; ; 81 @@ -22,8 +34,8 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; 2; input; set; **ZS; ?ZS; Z2F**; RW 3; power; on; BPO|BPO; ?BP; BPR*; RW; yes 3; power; off; BPF; ?BP; BPR*; RW; yes -3; volume+; ; YU; ; YV; W -3; volume-; ; YD; ; YV; W +3; volume+; increase; YU; ; YV; W +3; volume-; decrease; YD; ; YV; W 3; volumehigh; ; 75YV; ?YV; YV75; W 3; volumelow; ; 45YV; ?YV; YV45; W 3; volume; set; **YV; ?YV; YV**; RW; ; 81 diff --git a/avdevice/vsx-923.txt b/avdevice/vsx-923.txt index 148f4656b..0f3c08e60 100755 --- a/avdevice/vsx-923.txt +++ b/avdevice/vsx-923.txt @@ -1,18 +1,31 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MAXVALUE; RESPONSETYPE 1; power; on; PO|PO; ?P; PWR*; RW; yes 1; power; off; PF; ?P; PWR*; RW; yes -1; volume+; ; VU; ; VOL; W -1; volume-; ; VD; ; VOL; W +1; volume+; increase; VU; ; VOL; W +1; volume-; decrease; VD; ; VOL; W 1; volumehigh; ; 150VL; ?V; VOL150; W 1; volumelow; ; 110VL; ?V; VOL110; W 1; volume; set; ***VL; ?V; VOL***; RW; ; 185 1; mute; on; MO; ?M; MUT*; RW; yes 1; mute; off; MF; ?M; MUT*; RW; yes 1; input; set; **FN; ?F; FN**; RW +1; mode; set; ****SR; ?S; SR****; RW +1; playingmode; ; ?L; ?L; LM****; R +1; speakers; set; *SPK; ?SPK; SPK*; RW +1; tone; on; 1TO; ?TO; TO*; RW +1; tone; off; 0TO; ?TO; TO*; RW +1; bass; set; **BA; ?BA; BA**; RW; ; 12 +1; trebble; set; **TR; ?TR; TR**; RW; ; 12 +1; bass+; increase; BI; ; BA; W +1; bass-; decrease; BD; ; BA; W +1; trebble+; increase; TI; ; TR; W +1; trebble-; decrease; TD; ; TR; W +1; dialog; set; *ATH; ?ATH; ATH*; RW +1; HDMI; set; *HO; ?HO; HO*; RW 2; power; on; APO|APO; ?AP; APR*; RW; yes 2; power; off; APF; ?AP; APR*; RW; yes -2; volume+; ; ZU; ; ZV; W -2; volume-; ; ZD; ; ZV; W +2; volume+; increase; ZU; ; ZV; W +2; volume-; decrease; ZD; ; ZV; W 2; volumehigh; ; 75ZV; ?ZV; ZV75; W 2; volumelow; ; 45ZV; ?ZV; ZV45; W 2; volume; set; **ZV; ?ZV; ZV**; RW; ; 81 @@ -23,4 +36,3 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; 0; station; ; ; ; GEH04022; R 0; genre; ; ; ; GEH05024; R 0; display; ; ?FL; ?FL; FL******************************; R -1; speakers; set; *SPK; ?SPK; SPK*; RW From 718ebadfa1c32d88406ba511ff45774ec5197041 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 16 Dec 2017 22:49:54 +0100 Subject: [PATCH 02/11] Fixed standard ignore responses in yaml --- avdevice/plugin.yaml | 59 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/avdevice/plugin.yaml b/avdevice/plugin.yaml index ed20e3bc3..ed90e48df 100755 --- a/avdevice/plugin.yaml +++ b/avdevice/plugin.yaml @@ -19,7 +19,7 @@ plugin: parameters: # Definition of parameters to be configured in etc/plugin.yaml - model: + model: type: str default: '' mandatory: True @@ -27,51 +27,51 @@ parameters: de: 'Name des Geräts. Muss mit dem Namen der Textdatei unter plugins/avdevice korrelieren, die sämtliche Befehle beinhaltet.' en: 'Name of AV device. Has to correspond to a text file with the same name in the folder plugins/avdevice including all commands.' - tcp_ip: + tcp_ip: type: ip default: 0.0.0.0 description: de: 'Beim Nutzen der TCP Verbindungen ist die IP Adresse des Endgeräts anzugeben.' en: 'If you use TCP connection define IP address of your device.' - tcp_port: + tcp_port: type: int default: 23 description: de: 'Beim Nutzen der TCP Verbindungen ist der Port anzugeben, auf dem das Gerät Verbindungen zulässt. Für Denon: 23, für Pioneer: 8002.' en: 'If you use TCP connection define the port where your device accepts TCPIP connections. For Denon use 23, for Pioneer 8002.' - tcp_timeout: + tcp_timeout: type: int default: 1 description: de: 'Beim Nutzen der TCP Verbindungen kann ein Timeout angegeben werden.' en: 'If you use TCP connection you can define a connection timeout.' - rs232_port: + rs232_port: type: str default: '' description: de: "Beim Nutzen einer RS232 Schnittstelle (empfohlen!) ist die serielle Schnittstelle anzugeben." en: "If you use a RS232 cable to communicate with your device (highly recommended!) define the serial port." - rs232_baudrate: + rs232_baudrate: type: int default: 9600 description: de: "Beim Nutzen einer RS232 Schnittstelle ist die benötigte Baudrate anzugeben." en: "If you use a RS232 interface define the baudrate." - rs232_timeout: + rs232_timeout: type: float default: 0.1 description: de: "Beim Nutzen einer RS232 Schnittstelle kann ein Timeout zum Lesen und Schreiben definiert werden." en: "If you use a RS232 interface you can define read and write timeout." - ignoreresponse: + ignoreresponse: type: str - default: 'RGB,RGC,RGD,GBH,GHH,LM0,VTA,AUA,AUB' + default: 'RGB,RGC,RGD,GBH,GHH,VTA,AUA,AUB' description: de: "Das Plugin ignoriert Antworten die mit den hier angegebenen Werten starten, beispielsweise Rückmeldungen für die Menünavigation, etc. Der Defaultwert ist für Pioneer Receiver empfohlen." en: "The plugin doesn't care about responses from the device starting with the given values. List responses for menu navigation, etc. The default value is recommended for Pioneer receivers." @@ -82,8 +82,8 @@ parameters: description: de: "Wenn aus irgendeinem Grund die Antworten nicht gepuffert werden sollen, können hier dennoch Antworten definiert werden, die sehr wohl gepuffert werden. Dies ist besonders wichtig bei Informationen, die schnell hintereinander gesendet werden bzw. wechseln wie Künstler, Musiktitel, Radiostation, etc. Der Defaultwert ist für Pioneer Receiver empfohlen." en: "If for whatever reason you don't want to buffer the response from your device you can still define specific responses that should get buffered. This is important for responses that change or get sent very quickly. Artist, title, radio station, etc. are examples that should be put here. The default value is recommended for Pioneer receivers." - - inputignoredisplay: + + inputignoredisplay: type: str default: '' description: @@ -103,81 +103,80 @@ parameters: description: de: "Wenn das angegebene Item den angegebenen Wert erhält, werden die Befehle gesendet, ansonsten nicht. Das ist insbesondere dann sinnvoll, wenn das Gerät an einer schaltbaren Steckdose hängt." en: " If given item has given value the commands are sent to the device, otherwise they are not. Relevant if you have your device connected to a power socket that can be turned off." - - errorresponse: + + errorresponse: type: str default: 'E02,E04,E06' description: de: "Standard Fehlermeldungen des Geräts, bei Pioneer beispielsweise ein 'E' gefolgt von einer Nummer. Werden diese Antworten hier nicht angegeben, werden Rückmeldungen unter Umständen deutlich langsamer verarbeitet, aber voraussichtlich trotzdem erkannt." en: "The standard error responses from your device. For Pioneer receivers they are 'E' followed by a number. If no values are provided error answers from your device might get recognized much slower but actually should still get recognized." - + resetonerror: type: bool default: False description: de: "Zurücksetzen des Items auf den vorigen Wert, wenn kein Update durchgeführt werden konnte, zB das Setzen der Lautstärke in einer abgeschalteten Zone. Sobald das dependson Item ausgeschaltet wird oder mehrere Verbindungs- und Sendeversuche fehlgeschlagen sind, wird das Item zurückgesetzt, damit keine falschen Werte in der Visu angezeigt werden." en: "Reset the value of the item that could not be updated. E.g. you set the volume of zone 2 when it is not powered on. If either the dependson item is off or the device sends an error response or after several connection and send retries the expected response is not received, the item gets set to the value it had before you sent the command. That way you avoid having a wrong value displayed in your Visu." - - depend0_power0: + + depend0_power0: type: bool default: False description: de: "Wenn das dependson Item abgeschaltet ist, werden alle Poweritems ebenfalls auf 0 gesetzt. Das ist dann relevant, wenn beispielsweise das Gerät eingeschaltet ist, die Steckdose aber ausgeschaltet wird. Durch Aktivieren dieser Funktion werden automatisch die Poweritems auf 0 gesetzt." en: "If the dependson item is off the power off all zones are set to off. This is especially relevant for a correct representation in your Visu when you have a powered on device but turn off the power socket." - - depend0_volume0: + + depend0_volume0: type: bool default: False description: de: "Wie beim obigen Attribut dient auch diese Funktion zum korrekten Update der Visu auf den Lautstärkewert 0, sobald das dependson Item deaktiviert wird (zB Ausschalten der Steckdose)." en: "Same as above but in this case the volume is set to 0 for all zones. This is for Visu purposes only." - - sendretries: + + sendretries: type: int default: 10 description: de: "Dieser Wert definiert, wie oft bei einer falschen Antwort versucht werden soll, den Befehl nochmals zu senden." en: "This value defines how often a command should be sent when receiving a wrong answer from the device." - + resendwait: type: float default: 1.0 description: de: "Angabe der Pause zwischen Resend Versuchen in Sekunden" en: "Seconds the plugin should wait between each resend retry." - - reconnectretries: + + reconnectretries: type: int default: 13 description: de: "Anzahl der Verbindungsversuche bei Verbindungsproblemen. Das ist insbesondere bei TCP Verbindungen von Geräten relevant, die an schaltbaren Steckdosen hängen, da diese oftmals 30-40 Sekunden zum Hochfahren benötigen." en: "If the plugin can not connect to the device it retries this often. This is especially useful for TCP connections on devices that are plugged into a switchable socket as most receivers need about 40-50 seconds to boot their network device." - - secondstokeep: + + secondstokeep: type: int default: 50 description: de: "Dauer in Sekunden, wie lange ein Kommando, das nicht erfolgreich war in einem Zwischenspeicher aufbewahrt werden soll. Dies ist besonders bei TCP Verbindungen mit Geräten an schaltbaren Steckdosen relevant, da diese ofmals 30-40 Sekunden zum Hochfahren benötigen." en: "Seconds the plugin should temporarily save a command to retry later on after establishing a connection. This is especially useful for TCP connections on devices that are plugged into a switchable socket as most receivers need about 40-50 seconds to boot their network device." - + responsebuffer: type: int default: 5 description: de: "Schnell hintereinander empfangene Werte werden bei einer negativen Attributangabe im Puffer gespeichert und gemeinsam verarbeitet. Der Standardwert sollte dafür sorgen, dass keine Antworten verloren gehen. Einige Receiver antworten unter Umständen immer zuerst mit der Angabe zum auf dem Display gezeigten Wert. Der Puffer sorgt dafür, dass auch eine nachfolgende Rückmeldung evaluiert wird." en: "Set this to a number to collect quickly received responses in a buffer and evaluate them collectively. The standard value should be fine and prevent responses getting lost. Some receivers might first respond to a command with an update of the display and then with the actual value. The buffer ensures the correct evaluation of the response." - - autoreconnect: + + autoreconnect: type: bool default: False description: de: "Automatischer Versuch, sich mit dem Gerät zu verbinden, wenn keine Rückmeldung kommt oder die Verbindung verloren wurde. Dies sollte nicht notwendig sein, da das Plugin ohnehin bei jedem neuen Senden eines Befehls einen Verbindungsaufbauversuch startet." en: "Automatically tries to reconnect if no response is received or connection is lost. This should not be necessary as the plugin always tries to reconnect before sending a command." - + item_attributes: avdevice_zone[0-4]: type: str description: de: 'Obiges Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei hinterlegt ist, zB power oder volume' en: 'This attribute has to be followed by one of the commands declared in the device text file like power or volume' - From de564a5d137f8720b04c3d0eeb6d10470af650b5 Mon Sep 17 00:00:00 2001 From: Bernd Meiners Date: Mon, 18 Dec 2017 18:01:01 +0100 Subject: [PATCH 03/11] fix missing tzinfo with sunrise/sunset times --- uzsu/__init__.py | 91 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 28 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 158b8a60f..908b69a5e 100644 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -22,17 +22,25 @@ # Item Data Format # -# Each UZSU item is of type list. Each list entry has to be a dict with specific key and value pairs. Here are the possible keys and what their for: +# Each UZSU item is of type list. Each list entry has to be a dict with specific key and value pairs. +# Here are the possible keys and their purpose: # -# dtstart: a datetime object. Exact datetime as start value for the rrule algorithm. Important e.g. for FREQ=MINUTELY rrules (optional). +# dtstart: a datetime object. Exact datetime as start value for the rrule algorithm. Important e.g. for FREQ=MINUTELY rrules (optional). # -# value: the value which will be set to the item. +# value: the value which will be set to the item. # -# active: True if the entry is activated, False if not. A deactivated entry is stored to the database but doesn't trigger the setting of the value. It can be enabled later with the update method. +# active: True if the entry is activated, False if not. +# A deactivated entry is stored to the database but doesn't trigger the setting of the value. +# It can be enabled later with the update method. # -# time: time as string to use sunrise/sunset arithmetics like in the crontab eg. 17:008:00, 17:008:00 +# 17:00 datetime.now(self._sh.tzinfo()): return next, value if 'sun' in time: - next = self.sun(datetime.combine(today, datetime.min.time()).replace(tzinfo=self._sh.tzinfo()), time) - self.logger.debug("Result parsing time (sun) {}: {}".format(time, next)) + next = self._sun(datetime.combine(today, datetime.min.time()).replace(tzinfo=self._sh.tzinfo()), time) + self.logger.debug("Result parsing time (sun) {}: {}".format(time, next)) else: next = datetime.combine(today, parser.parse(time.strip()).time()).replace(tzinfo=self._sh.tzinfo()) if next and next.date() == today and next > datetime.now(self._sh.tzinfo()): @@ -218,9 +237,14 @@ def _next_time(self, entry): return None, None def _sun(self, dt, tstr): - #dt contains a datetime object, whereas tstr should contain a string like '6:00 Date: Wed, 20 Dec 2017 01:04:25 +0100 Subject: [PATCH 04/11] Backend: Basic editing functionallity for items of type list and dict; display of filename that the item is defiined in (for user items) --- backend/BackendItems.py | 1 + backend/BackendThreads.py | 6 +++--- backend/locale/de.json | 3 ++- backend/locale/en.json | 3 ++- backend/locale/fr.json | 3 ++- backend/locale/pl.json | 3 ++- backend/plugin.yaml | 4 ++-- backend/webif/templates/items.html | 10 ++++++++++ mail/__init__.py | 17 ++++++++++++----- 9 files changed, 36 insertions(+), 14 deletions(-) diff --git a/backend/BackendItems.py b/backend/BackendItems.py index 75aef066d..dd9487d82 100755 --- a/backend/BackendItems.py +++ b/backend/BackendItems.py @@ -342,6 +342,7 @@ def item_detail_json_html(self, item_path): 'config': json.dumps(item_conf_sorted), 'logics': json.dumps(logics), 'triggers': json.dumps(triggers), + 'filename': str(item._filename), } # cast raw data to a string diff --git a/backend/BackendThreads.py b/backend/BackendThreads.py index f7514de00..bb68c1be5 100755 --- a/backend/BackendThreads.py +++ b/backend/BackendThreads.py @@ -39,7 +39,7 @@ def thread_sum(self, name, count): thread['name'] = name thread['sort'] = str(thread['name']).lower() thread['id'] = "(" + str(count) + " threads" + ")" - thread['alive'] = 'Ja' + thread['alive'] = 'True' return thread @cherrypy.expose @@ -68,9 +68,9 @@ def threads_html(self): thread['id'] = t.ident try: if t.is_alive(): - thread['alive'] = 'Ja' + thread['alive'] = 'True' else: - thread['alive'] = 'Nein' + thread['alive'] = 'False' except AssertionError: thread['alive'] = 'AssertionError' diff --git a/backend/locale/de.json b/backend/locale/de.json index 7858c966b..df17f0618 100755 --- a/backend/locale/de.json +++ b/backend/locale/de.json @@ -205,7 +205,8 @@ "cycle": "cycle", "crontab": "crontab", "autotimer": "autotimer", - "threshold": "threshold" + "threshold": "threshold", + "filename": "definiert in" }, "_threads": { diff --git a/backend/locale/en.json b/backend/locale/en.json index ba0fc8d34..08946ddcf 100755 --- a/backend/locale/en.json +++ b/backend/locale/en.json @@ -205,7 +205,8 @@ "cycle": "cycle", "crontab": "crontab", "autotimer": "autotimer", - "threshold": "threshold" + "threshold": "threshold", + "filename": "defined in" }, "_threads": { diff --git a/backend/locale/fr.json b/backend/locale/fr.json index ffee4fc9d..32b84158f 100755 --- a/backend/locale/fr.json +++ b/backend/locale/fr.json @@ -207,7 +207,8 @@ "cycle": "cycle", "crontab": "crontab", "autotimer": "autotimer", - "threshold": "threshold" + "threshold": "threshold", + "filename": "" }, "_threads": { diff --git a/backend/locale/pl.json b/backend/locale/pl.json index 84fc594bc..07c1935f3 100755 --- a/backend/locale/pl.json +++ b/backend/locale/pl.json @@ -203,7 +203,8 @@ "cycle": "cykl", "crontab": "harmonogram", "autotimer": "autotimer", - "threshold": "próg" + "threshold": "próg", + "filename": "" }, "_threads": { diff --git a/backend/plugin.yaml b/backend/plugin.yaml index 5c9248473..86ac201fe 100755 --- a/backend/plugin.yaml +++ b/backend/plugin.yaml @@ -12,8 +12,8 @@ plugin: # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/959964-support-thread-für-das-backend-plugin - version: 1.4.8 # Plugin version - sh_minversion: 1.3d # minimum shNG version to use this plugin + version: 1.4.9 # Plugin version + sh_minversion: 1.4a # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance classname: BackendServer # class containing the plugin diff --git a/backend/webif/templates/items.html b/backend/webif/templates/items.html index 2bbe8abb8..4bf9f508e 100755 --- a/backend/webif/templates/items.html +++ b/backend/webif/templates/items.html @@ -49,6 +49,12 @@ case 'str': var input = ''; break; + case 'list': + var input = ''; + break; + case 'dict': + var input = ''; + break; case 'num': var input = ''; break; @@ -118,6 +124,10 @@ temp = temp + ''+triggers[i]+''; }; }; + if (element.filename != 'None') { + temp = temp + ''; + temp = temp + '{{ _('filename', 'items') }}'+element.filename+''; + } temp = temp + ''; diff --git a/mail/__init__.py b/mail/__init__.py index ac453c65b..6924e4ba2 100755 --- a/mail/__init__.py +++ b/mail/__init__.py @@ -104,12 +104,19 @@ def _cycle(self): logic = False if logic: logic.trigger('IMAP', fo, mail, dest=to) - rsp, data = imap.uid('copy', uid, 'Trash') - if rsp == 'OK': - typ, data = imap.uid('store', uid, '+FLAGS', '(\Deleted)') - self.logger.debug("Moving mail to trash. {0} => {1}: {2}".format(fo, to, subject)) + if self._host.lower() == 'imap.gmail.com': + typ, data = imap.uid('store', uid, '+X-GM-LABELS', '\\Trash') + if typ == 'OK': + logger.debug("Moving mail to trash. {0} => {1}: {2}".format(fo, to, subject)) + else: + logger.warning("Could not move mail to trash. {0} => {1}: {2}".format(fo, to, subject)) else: - self.logger.warning("Could not move mail to trash. {0} => {1}: {2}".format(fo, to, subject)) + rsp, data = imap.uid('copy', uid, 'Trash') + if rsp == 'OK': + typ, data = imap.uid('store', uid, '+FLAGS', '(\Deleted)') + self.logger.debug("Moving mail to trash. {0} => {1}: {2}".format(fo, to, subject)) + else: + self.logger.warning("Could not move mail to trash. {0} => {1}: {2}".format(fo, to, subject)) else: self.logger.info("Ignoring mail. {0} => {1}: {2}".format(fo, to, subject)) imap.close() From 543d676a59a92401e6043c95d4cf7099c1a4640d Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 21 Dec 2017 10:32:21 +0100 Subject: [PATCH 05/11] Auto-fix incorrect config, added two more commands for Pioneer --- avdevice/AVDeviceInit.py | 1 + avdevice/sc-lx86.txt | 4 ++++ avdevice/vsx-923.txt | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/avdevice/AVDeviceInit.py b/avdevice/AVDeviceInit.py index 581bc12f1..e75ac24e0 100755 --- a/avdevice/AVDeviceInit.py +++ b/avdevice/AVDeviceInit.py @@ -408,6 +408,7 @@ def _read_commandfile(self): row.append('bool') elif i == 8 and ("increase" in function or "decrease" in function): row.append('int,float') + row[5] = row[5].replace('*', '') else: row.append('') try: diff --git a/avdevice/sc-lx86.txt b/avdevice/sc-lx86.txt index ec4c8daf0..1791fde3d 100755 --- a/avdevice/sc-lx86.txt +++ b/avdevice/sc-lx86.txt @@ -22,6 +22,10 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; 1; trebble-; decrease; TD; ; TR; W 1; dialog; set; *ATH; ?ATH; ATH*; RW 1; HDMI; set; *HO; ?HO; HO*; RW +1; input+; increase; FU; ?F; FN; W +1; input-; decrease; FD; ?F; FN; W +1; radiof+; ; TPI; ; PR; W; ; ; str +1; radiof-; ; TPD; ; PR; W; ; ; str 2; power; on; APO|APO; ?AP; APR*; RW; yes 2; power; off; APF; ?AP; APR*; RW; yes 2; volume+; increase; ZU; ; ZV; W diff --git a/avdevice/vsx-923.txt b/avdevice/vsx-923.txt index 0f3c08e60..073fa39ac 100755 --- a/avdevice/vsx-923.txt +++ b/avdevice/vsx-923.txt @@ -22,6 +22,10 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; 1; trebble-; decrease; TD; ; TR; W 1; dialog; set; *ATH; ?ATH; ATH*; RW 1; HDMI; set; *HO; ?HO; HO*; RW +1; input+; increase; FU; ?F; FN; W +1; input-; decrease; FD; ?F; FN; W +1; radiof+; ; TPI; ; PR; W; ; ; str +1; radiof-; ; TPD; ; PR; W; ; ; str 2; power; on; APO|APO; ?AP; APR*; RW; yes 2; power; off; APF; ?AP; APR*; RW; yes 2; volume+; increase; ZU; ; ZV; W From 85fdf1e1ded40dd9668285343f282fecc51366ae Mon Sep 17 00:00:00 2001 From: msinn Date: Thu, 21 Dec 2017 17:05:24 +0100 Subject: [PATCH 06/11] Backend: Filtered out loggers, if they only have a NullHandler; extended display of shNG version --- backend/BackendLogging.py | 7 +++++-- backend/BackendSysteminfo.py | 6 +++--- backend/webif/templates/system.html | 8 ++++++-- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/backend/BackendLogging.py b/backend/BackendLogging.py index c6cb819e6..945f08f8c 100755 --- a/backend/BackendLogging.py +++ b/backend/BackendLogging.py @@ -79,8 +79,11 @@ def logging_html(self): except: fn = '' l['filenames'].append(fn) - - loggers.append(l) + + if l['handlers'] == ['NullHandler']: + self.logger.warning("logging_html: Filtered out logger {}: l['handlers'] = {}".format(l['name'], l['handlers'])) + else: + loggers.append(l) return self.render_template('logging.html', loggers=loggers) diff --git a/backend/BackendSysteminfo.py b/backend/BackendSysteminfo.py index 89f16a449..5d22dd3f4 100755 --- a/backend/BackendSysteminfo.py +++ b/backend/BackendSysteminfo.py @@ -96,7 +96,7 @@ def system_html(self): #req_dict = self.get_requirements_info() return self.render_template('system.html', - now=now, system=system, sh_vers=shngversion.get_shng_version(), plg_vers=shngversion.get_plugins_version(), sh_dir=self._sh_dir, + now=now, system=system, sh_vers=shngversion.get_shng_version(), sh_desc=shngversion.get_shng_description(), plg_vers=shngversion.get_plugins_version(), plg_desc=shngversion.get_plugins_description(), sh_dir=self._sh_dir, vers=vers, node=node, arch=arch, user=user, freespace=freespace, uptime=uptime, sh_uptime=sh_uptime, pyversion=pyversion, ip=ip, ipv6=ipv6) @@ -261,7 +261,7 @@ def pypi_json(self): package['sort'] = '3' else: package['sort'] = '4' - self.logger.info("pypi_json: sort=4, package['name'] = >{}<".format(package['name'])) + self.logger.debug("pypi_json: sort=4, package['name'] = >{}<".format(package['name'])) package['sort'] += package['name'] @@ -578,7 +578,7 @@ def check_requirement(self, package, req_str): # Now we have a list of [ requirement_source, min_version (with operator), max_version (with operator) ] if len(req_result) == 1: result = req_result[0] - self.logger.info("check_requirement: package {}, req_result = >{}<, result = >{}<".format(package, req_result, result)) + self.logger.debug("check_requirement: package {}, req_result = >{}<, result = >{}<".format(package, req_result, result)) #handle min op, req_min = self.split_operator(result[1]) if req_min == '*': diff --git a/backend/webif/templates/system.html b/backend/webif/templates/system.html index a49a76fb0..002eb019b 100755 --- a/backend/webif/templates/system.html +++ b/backend/webif/templates/system.html @@ -29,12 +29,16 @@ {{ _('SmartHomeNG Version') }}: - {{ sh_vers }} {{ _('in') }} {{ sh_dir }}  -  {{ _('Benutzer') }}: {{ user }} + {{ sh_vers }} {{ _('in') }} {{ sh_dir }}  -   {{ sh_desc }}   -  {{ _('Benutzer') }}: {{ user }} {{ _('SmartHomeNG Plugins Version') }}: - {{ plg_vers }} {{ _('in') }} {{ sh_dir }}/plugins + {{ plg_vers }} {{ _('in') }} {{ sh_dir }}/plugins + {% if plg_desc != '' %} +   -   {{ plg_desc }} + {% endif %} + From 0c884032b96d2d13e251996860a7aa99a113cf1c Mon Sep 17 00:00:00 2001 From: msinn Date: Thu, 21 Dec 2017 18:45:40 +0100 Subject: [PATCH 07/11] mail: Added some gmail support --- mail/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mail/README.md b/mail/README.md index 0f14a0ea6..42bc8e7e3 100644 --- a/mail/README.md +++ b/mail/README.md @@ -74,6 +74,15 @@ If the incoming mail subject matches the value of this key the logic will be tri If the mail is sent to specified address the logic will be triggerd. +If gmail is used, you can trigger multiple logics with one account - just extend email address +with ['+' sign](https://gmail.googleblog.com/2008/03/2-hidden-ways-to-get-more-from-your.html) +(eg use `myaccount+logicname@gmail.com` to trigger `logicname`) + +For safety reasons, use only dedicated gmail account with this plugin and filter out messages +from unkown senders (eg create filter `from:(-my_trusted_mail@example.com)` with action archive +or delete) + + #### mail A genric flag to trigger the logic on receiving a mail. From e71e6e32b46ec1698553072d63cab2e03b0aa25f Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 22 Dec 2017 09:50:54 +0100 Subject: [PATCH 08/11] Added functions for Pioneer --- avdevice/sc-lx86.txt | 8 ++++---- avdevice/vsx-923.txt | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/avdevice/sc-lx86.txt b/avdevice/sc-lx86.txt index 1791fde3d..7910ac0ad 100755 --- a/avdevice/sc-lx86.txt +++ b/avdevice/sc-lx86.txt @@ -9,7 +9,7 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; 1; mute; on; MO; ?M; MUT*; RW; yes 1; mute; off; MF; ?M; MUT*; RW; yes 1; mode; set; ****SR; ?S; SR****; RW -1; playingmode; ; ?L; ?L; LM****; R +1; playingmode; ; ?L; ?L; LM****; R; ; ; str 1; speakers; set; *SPK; ?SPK; SPK*; RW 1; input; set; **FN; ?F; FN**; RW 1; tone; on; 1TO; ?TO; TO*; RW @@ -49,7 +49,7 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; 4; power; on; ZEO; ?ZEP; ZEP*; RW; yes 4; power; off; ZEF; ?ZEP; ZEP*; RW; yes 4; input; set; **ZEA; ?ZEA; ZEA**; RW -0; title; ; ; ; GEH01020; R -0; station; ; ; ; GEH04022; R -0; genre; ; ; ; GEH05024; R +0; title; ; ; ; GEH01020; R; ; ; str +0; station; ; ; ; GEH04022; R; ; ; str +0; genre; ; ; ; GEH05024; R; ; ; str 0; display; ; ?FL; ?FL; FL******************************; R diff --git a/avdevice/vsx-923.txt b/avdevice/vsx-923.txt index 073fa39ac..b2e8e9dbf 100755 --- a/avdevice/vsx-923.txt +++ b/avdevice/vsx-923.txt @@ -10,7 +10,7 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; 1; mute; off; MF; ?M; MUT*; RW; yes 1; input; set; **FN; ?F; FN**; RW 1; mode; set; ****SR; ?S; SR****; RW -1; playingmode; ; ?L; ?L; LM****; R +1; playingmode; ; ?L; ?L; LM****; R; ; ; num 1; speakers; set; *SPK; ?SPK; SPK*; RW 1; tone; on; 1TO; ?TO; TO*; RW 1; tone; off; 0TO; ?TO; TO*; RW @@ -36,7 +36,7 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; 2; mute; on; Z2MO; ?Z2M; Z2MUT*; RW; yes 2; mute; off; Z2MF; ?Z2M; Z2MUT*; RW; yes 2; input; set; **ZS; ?ZS; Z2F**; RW -0; title; ; ; ; GEH01020; R -0; station; ; ; ; GEH04022; R -0; genre; ; ; ; GEH05024; R +0; title; ; ; ; GEH01020; R; ; ; str +0; station; ; ; ; GEH04022; R; ; ; str +0; genre; ; ; ; GEH05024; R; ; ; str 0; display; ; ?FL; ?FL; FL******************************; R From 2e597ea5ae253a17299cede069aa7415367abd75 Mon Sep 17 00:00:00 2001 From: msinn Date: Fri, 22 Dec 2017 12:16:28 +0100 Subject: [PATCH 09/11] Documentation changes --- cli/plugin.yaml | 2 +- cli/user_doc.rst | 122 ++++++++++++++++++++++++++++++++++++ sqlite/plugin.yaml | 4 +- sqlite_visu2_8/plugin.yaml | 4 +- visu_smartvisu/README.md | 47 ++++++++------ visu_smartvisu/plugin.yaml | 2 +- visu_smartvisu/user_doc.rst | 4 ++ 7 files changed, 161 insertions(+), 24 deletions(-) create mode 100755 cli/user_doc.rst create mode 100755 visu_smartvisu/user_doc.rst diff --git a/cli/plugin.yaml b/cli/plugin.yaml index 641fe6653..c0368033b 100755 --- a/cli/plugin.yaml +++ b/cli/plugin.yaml @@ -9,7 +9,7 @@ plugin: maintainer: msinn tester: onkelandy, Sandman60, ohinckel # keywords: iot xyz - documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page +# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page version: 1.4.0 # Plugin version sh_minversion: 1.3b # minimum shNG version to use this plugin diff --git a/cli/user_doc.rst b/cli/user_doc.rst new file mode 100755 index 000000000..ddfa3064f --- /dev/null +++ b/cli/user_doc.rst @@ -0,0 +1,122 @@ +.. index:: Plugins; CLI (CommandLine Interface) +.. index:: CLI + +cli +### + +Das CLI Plugin bietet einen Zugriff über Telnet auf SmartHomeNG. + +Über das Plugin können diverse Befehle an SmartHomeNG zur Auflistung, Debugging und Manipulation +von Items, Logiken, Plugins und internen Objekten geschickt werden. + + +Plugin Konfigurationsparameter +============================== + +Das Plugin kann über die folgende Konfiguration in der Datei etc/plugins.conf akitviert werden: + +.. code-block: yaml + cli: + plugin_name: cli + # ip: 0.0.0.0 + # port: 2323 + update: True + + + ++--------------+------------------------------------------------------------------------------+ +| Paramter | Erläuterung | ++==============+==============================================================================+ +| plugin_name | Referenziert das Plugin | ++--------------+------------------------------------------------------------------------------+ +| ip | Bei Verwendung mehrerer Netzwerke/Netzwerk Adapter: Netzwerk an das das CLI | +| | Plugin gebunden werden soll. | ++--------------+------------------------------------------------------------------------------+ +| port | Port der auf Verbindungen lauschen soll (default: 2323). | ++--------------+------------------------------------------------------------------------------+ +| update | Wenn der Parameter True konfiguriert wird, dürfen über das CLI-Plugin Daten | +| | geändert werden. | ++--------------+------------------------------------------------------------------------------+ + + + +Zugriff auf die CLI +=================== + +Linux +----- + +`telnet localhost 2323` + +Zugriff via Windows / Putty +--------------------------- + +In Putty bitte folgende Settings beachten, damit der Zugriff auf das CLI Plugin funktioniert: + +Session: + +- Connection type -> RAW wählen (nicht Telnet!) +- Host Namen des Servers eintragen, Port 2323 (oder wie er in der plugin.conf konfiguriert ist) + + +Terminal: + +- Implicit CR in every LF -> Haken setzen + +Connection - Telnet: + +- Keyboard sends Telnet special commands -> Haken setzen +- Return key sends Telnet New Line instead of ^M -> Haken entfernen + + +CLI Befehle +=========== + ++--------------------------+----------------------------------------------------------------------------------------------+ +| Befehl | Erläuterung | ++==========================+==============================================================================================+ +| help , h | Zeigt allgemeine Hilfe oder Hilfe für eine Guppe von Kommandos | ++--------------------------+----------------------------------------------------------------------------------------------+ +| if | Listet die Items der obersten Ebene | ++--------------------------+----------------------------------------------------------------------------------------------+ +| if | Listet das angegebene Item und alle Child-Items dazu mit Werten auf | ++--------------------------+----------------------------------------------------------------------------------------------+ +| ii | Dumpt Detail-Information über das angegebene Item - Kommando Alias: dump | ++--------------------------+----------------------------------------------------------------------------------------------+ +| il | Listet alle Items mit Werten - Kommando Alias: la | ++--------------------------+----------------------------------------------------------------------------------------------+ +| iup | Alias for iupdate - Kommando Alias: up | ++--------------------------+----------------------------------------------------------------------------------------------+ +| iupdate = | Weist dem Item einen neuen Wert zu - Kommando Alias: update | ++--------------------------+----------------------------------------------------------------------------------------------+ +| ld | Disabled die angegebene Logic - Kommando Alias: dl | ++--------------------------+----------------------------------------------------------------------------------------------+ +| le | Enabled die angegebene Logic - Kommando Alias: el | ++--------------------------+----------------------------------------------------------------------------------------------+ +| li | Logic Information - Dumpt Details über die angegebene Logik | ++--------------------------+----------------------------------------------------------------------------------------------+ +| ll | Listet alle Logiken und ihre nächste Ausführungszeit - Kommando Alias: lo | ++--------------------------+----------------------------------------------------------------------------------------------+ +| logc | Löscht das Memory-Log | ++--------------------------+----------------------------------------------------------------------------------------------+ +| logd | Dumpt das Memory-Log | ++--------------------------+----------------------------------------------------------------------------------------------+ +| lr | Führt ein Reload für die angegebene Logik aus - Kommando Alias: rl | ++--------------------------+----------------------------------------------------------------------------------------------+ +| lrr | Führt ein Reload für die angegebene Logik aus und triggert diese - Kommando Alias: rr | ++--------------------------+----------------------------------------------------------------------------------------------+ +| lt | Triggert die angegebene Logik - Kommando Alias: tr | ++--------------------------+----------------------------------------------------------------------------------------------+ +| rt | Zeit die Laufzeit von SmaertHomeNG an (return runtime) | ++--------------------------+----------------------------------------------------------------------------------------------+ +| si | Zeigt Details für den angegebene Scheduler Task an | ++--------------------------+----------------------------------------------------------------------------------------------+ +| sl | Listet alle Scheduler Tasks nach Namenauf | ++--------------------------+----------------------------------------------------------------------------------------------+ +| st | Listet alle Scheduler Tasks nach Ausführungszeit auf | ++--------------------------+----------------------------------------------------------------------------------------------+ +| tl | Listet die aktuellen Thread Namen auf | ++--------------------------+----------------------------------------------------------------------------------------------+ +| quit, q | Beendet die CLI Session | ++--------------------------+----------------------------------------------------------------------------------------------+ + diff --git a/sqlite/plugin.yaml b/sqlite/plugin.yaml index cfe4581fb..1a42b6909 100755 --- a/sqlite/plugin.yaml +++ b/sqlite/plugin.yaml @@ -3,8 +3,8 @@ plugin: # Global plugin attributes type: system # plugin type (gateway, interface, protocol, system, web) description: # Alternative: description in multiple languages - de: 'Integration einer SQLite Datenbank - kompatibel mit smartVISU 2.7' - en: '' + de: 'Integration einer SQLite Datenbank - kompatibel mit smartVISU v2.7' + en: 'Integration of a SQLite database - use this version of the plugin for smartVISU v2.7' maintainer: '?' # tester: # Who tests this plugin? keywords: database diff --git a/sqlite_visu2_8/plugin.yaml b/sqlite_visu2_8/plugin.yaml index 183b21923..fade5d564 100755 --- a/sqlite_visu2_8/plugin.yaml +++ b/sqlite_visu2_8/plugin.yaml @@ -3,8 +3,8 @@ plugin: # Global plugin attributes type: system # plugin type (gateway, interface, protocol, system, web) description: # Alternative: description in multiple languages - de: 'Integration einer SQLite Datenbank - zu verwenden für smartVISU 2.8' - en: '' + de: 'Integration einer SQLite Datenbank - zu verwenden für smartVISU v2.8 und höher' + en: 'Integration of a SQLite database - use this version of the plugin for smartVISU v2.8 and above' maintainer: '?' # tester: # Who tests this plugin? keywords: database diff --git a/visu_smartvisu/README.md b/visu_smartvisu/README.md index efbd56cc1..65d2ab8b5 100755 --- a/visu_smartvisu/README.md +++ b/visu_smartvisu/README.md @@ -76,24 +76,35 @@ Simply set the **`visu_acl`** attribute to something to allow read/write access #### sv_page Set **`sv_page`** to to one of the following values generate a page for this item. Every widget beneath this item will be included in the page. -Valid values are: - -| value | description | -| :---------------- | :---------------------------------------------------------- | -| **room** | The page appears in the room view of smartVISU | -| **seperator** | Inserts a seperator between entries in the room navigation | -| **overview** | The page groups of different items together | -| | | -| **category** | The page appears in the category view of smartVISU | -| **cat_seperator** | Inserts a seperator between entries in the category | -| | navigation | -| **cat_overview** | The page groups of different items together and is added | -| | to the category navigation | -| | | -| **room_lite** | The page appears in a lite view of the visualization | -[values for **`sv_page`**] - ---> Beschreibung für overview und separater vervollständigen +Valid values for **`sv_page`** are: + +``` ++---------------+-----------------------------------------------------+ +| value | description | ++===============+=====================================================+ +| room | The page appears in the room view of smartVISU | ++---------------+-----------------------------------------------------+ +| seperator | Inserts a seperator between entries in the room | +| | navigation | ++---------------+-----------------------------------------------------+ +| overview | The page groups of different items together | ++---------------+-----------------------------------------------------+ +| | | +| category | The page appears in the category view of smartVISU | ++---------------+-----------------------------------------------------+ +| cat_seperator | Inserts a seperator between entries in the category | +| | navigation | ++---------------+-----------------------------------------------------+ +| cat_overview | The page groups of different items together and is | +| | added to the category navigation | ++---------------+-----------------------------------------------------+ +| room_lite | The page appears in a lite view of the | +| | visualization | ++---------------+-----------------------------------------------------+ + +``` + +--> Beschreibung für overview und separator vervollständigen #### sv_overview If a page has defined **`sv_page`** as **`overview`**, it shows items of a specific type. The name/identifier of the type is defined by setting **`sv_overview`** to an unique name. For items to be displayed on this page, the items have to define **`sv_item_type`** and set it to the value of **`sv_overview`**. diff --git a/visu_smartvisu/plugin.yaml b/visu_smartvisu/plugin.yaml index 6d32d9969..3a0703eb1 100755 --- a/visu_smartvisu/plugin.yaml +++ b/visu_smartvisu/plugin.yaml @@ -8,7 +8,7 @@ plugin: maintainer: msinn tester: psilo909 # keywords: iot xyz - documentation: https://github.com/smarthomeNG/smarthome/wiki/Visu_Unterstuetzung # url of documentation (wiki) page +# documentation: https://github.com/smarthomeNG/smarthome/wiki/Visu_Unterstuetzung # url of documentation (wiki) page version: 1.3.4 # Plugin version sh_minversion: 1.3 # minimum shNG version to use this plugin diff --git a/visu_smartvisu/user_doc.rst b/visu_smartvisu/user_doc.rst new file mode 100755 index 000000000..3e40dfacd --- /dev/null +++ b/visu_smartvisu/user_doc.rst @@ -0,0 +1,4 @@ +visu_smartvisu +############## + +Genauer sind die Möglichkeiten unter :doc:`/visualisierung/visualisierung` beschrieben. From 9e8071a6145842d819685c5ca6377c93040c278b Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 22 Dec 2017 16:24:00 +0100 Subject: [PATCH 10/11] Updated README --- avdevice/README.md | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/avdevice/README.md b/avdevice/README.md index 9f6b87745..a04c5684b 100755 --- a/avdevice/README.md +++ b/avdevice/README.md @@ -83,7 +83,9 @@ The command has to correspond to a "base" command in the relevant text configura It is important to set the correct type for each item. The Pioneer RS232 codeset expects bool and int types only. For example to set the listening mode to "pure direct", the item has to be int and you set it to the value "8". -Full item examples are included as separate yaml files for Pioneer and Denon devices. In general the items are setup the same independent of the AV device model. The example include the tested items/commands and allow easy copy/paste. +Full item examples are included as separate yaml files for Pioneer and Denon devices. In general the items are setup the same independent of the AV device model. The examples include the tested items/commands and allow easy copy/paste. + +Speakers Items are special and should be set up the way mentioned in the following example. 1 and 2 correspond to the value the speaker command expects. #### Example @@ -98,6 +100,22 @@ Pioneer: avdevice_zone1@pioneer_one: power enforce_updates: 'no' knx_dpt: 1 + + Speakers: + type: num + visu_acl: rw + avdevice_zone1: speakers + + SpeakerA: + type: bool + visu_acl: rw + avdevice_zone1_speakers: 1 + + SpeakerB: + type: bool + visu_acl: rw + avdevice_zone1_speakers: 2 + ``` ### model.txt @@ -152,8 +170,10 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; ### Troubleshooting 1.) Have a look at the smarthome logfile. If you can't figure out the reason for your problem, change the verbose level in logging.yaml. You can use level 10 (=DEBUG), 9 (VERBOSE1) and 8 (VERBOSE2) as debugging levels. + 2.) Concerning send and response entries in the textfile, make sure the number of stars correspond to the way your device wants to receive the command or sends the response. Example 1: Your Pioneer receiver expects the value for the volume as three digits. So the command needs three stars. If you now set the item to a value with only two digits, like 90, the plugin converts the command automatically to have a leading 0. Example 2: Your Denon receiver responds with values like ON, OFF or STANDBY to power commands. Replace every character with a star! ON = 2 stars, OFF = 3 stars, etc. Example 3: Sending or receiving strings of different length like "CD", "GAME", etc. should be set up with one star only. Set the responsetype accordingly! -3.) Set the response type in the textfile to the correct value. The plugin tries to anticipate the correct value but that doesn't always work. The sleep timer of Denon devices is a wonderfully sick example: You can set values betwwen 1 and 120 to set the timer in minutes. If you want to turn it off, the receiver expects the value "OFF" instead of a zero. The plugin fixes that problem if you set the responsetype to bool|num. As soon as you set the item to 0, it magically converts that value to "OFF" and the other way around when receiving "OFF". + +3.) Set the response type in the textfile to the correct value. The plugin tries to anticipate the correct value but that doesn't always work. The sleep timer of Denon devices is a wonderfully sick example: You can set values betwwen 1 and 120 to set the timer in minutes. If you want to turn it off, the receiver expects the value "OFF" instead of a zero. The plugin fixes that problem if you set the responsetype to bool|num. As soon as you set the item to 0, it magically converts that value to "OFF" and the other way around when receiving "OFF". From 29cc4e3ebfd8da481b669a79733307fff5d54d35 Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 23 Dec 2017 18:26:18 +0100 Subject: [PATCH 11/11] backend: Adjusted version number --- backend/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/__init__.py b/backend/__init__.py index 8896cd413..60b86f061 100755 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -50,7 +50,7 @@ class BackendServer(SmartPlugin): the update functions for the items """ - PLUGIN_VERSION='1.4.8' + PLUGIN_VERSION='1.4.9' def __init__(self, sh, updates_allowed='True', developer_mode="no", pypi_timeout=5):