Skip to content

Commit

Permalink
Merge pull request #745 from Morg42/kodi
Browse files Browse the repository at this point in the history
kodi: replace with kodi sdp version
  • Loading branch information
Morg42 authored Oct 27, 2023
2 parents 50ba058 + be85af0 commit ddc926e
Show file tree
Hide file tree
Showing 14 changed files with 2,404 additions and 1,035 deletions.
2 changes: 1 addition & 1 deletion denon/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def on_data_received(self, by, data, command=None):
# command can be a string (classic single command) or
# - new - a list of strings if multiple commands are identified
# in that case, work on all strings
commands = self._commands.get_command_from_reply(data)
commands = self._commands.get_commands_from_reply(data)
if not commands:
if self._discard_unknown_command:
self.logger.debug(f'data "{data}" did not identify a known command, ignoring it')
Expand Down
2 changes: 1 addition & 1 deletion epson/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def on_data_received(self, by, data, command=None):
# command can be a string (classic single command) or
# - new - a list of strings if multiple commands are identified
# in that case, work on all strings
commands = self._commands.get_command_from_reply(data)
commands = self._commands.get_commands_from_reply(data)
if not commands:
if self._discard_unknown_command:
self.logger.debug(f'data "{data}" did not identify a known command, ignoring it')
Expand Down
1,017 changes: 291 additions & 726 deletions kodi/__init__.py
100755 → 100644

Large diffs are not rendered by default.

File renamed without changes.
843 changes: 843 additions & 0 deletions kodi/_pv_1_6_1/__init__.py

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions kodi/_pv_1_6_1/commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 'commandname': {'method': command for JSON-RPC, 'set': writa, 'get': use retval, param': names of params, 'values': param values,ID=playerid,VAL=data,tuple="eval" 'bounds': optional bounds, tuple is range, list is valid items}

commands = {
'update': {'special': True, 'set': True}, # call-only item to trigger update of all status fields
'player': {'special': True, 'set': False}, # stores player_id
'state': {'special': True, 'set': False}, # stores kodi state
'media': {'special': True, 'set': False}, # stores media type
'title': {'special': True, 'set': False}, # stores media title
'streams': {'special': True, 'set': False}, # stores available audio streams
'subtitles': {'special': True, 'set': False}, # stores available subtitles
'macro': {'special': True, 'set': True}, # triggers macro evaluation

'ping': {'method': 'JSONRPC.Ping', 'set': False, 'get': True, 'params': None, 'values': None, 'bounds': None},
'get_status_au': {'method': 'Application.GetProperties', 'set': False, 'get': True, 'params': ['properties'], 'values': [['volume', 'muted']], 'bounds': None},
'get_players': {'method': 'Player.GetPlayers', 'set': False, 'get': True, 'params': None, 'values': None, 'bounds': None},
'get_actplayer': {'method': 'Player.GetActivePlayers', 'set': False, 'get': True, 'params': None, 'values': None, 'bounds': None},
'get_status_play':{'method': 'Player.GetProperties', 'set': False, 'get': True, 'params': ['playerid', 'properties'], 'values': ['ID', ['type', 'speed', 'time', 'percentage', 'totaltime', 'position', 'currentaudiostream', 'audiostreams', 'subtitleenabled', 'currentsubtitle', 'subtitles', 'currentvideostream', 'videostreams']], 'bounds': None},
'get_item': {'method': 'Player.GetItem', 'set': False, 'get': True, 'params': ['playerid', 'properties'], 'values': ['ID', ['title', 'artist']], 'bounds': None},
'get_favourites': {'method': 'Favourites.GetFavourites', 'set': False, 'get': True, 'params': ['properties'], 'values': [['window', 'path', 'thumbnail', 'windowparameter']],'bounds': None},

'playpause': {'method': 'Player.PlayPause', 'set': True, 'get': False, 'params': ['playerid', 'play'], 'values': ['ID', 'toggle'], 'bounds': None},
'seek': {'method': 'Player.Seek', 'set': True, 'get': False, 'params': ['playerid', 'value'], 'values': ['ID', 'VAL'], 'bounds': (0.0, 100.0)},
'audio': {'method': 'Player.SetAudioStream', 'set': True, 'get': False, 'params': ['playerid', 'stream'], 'values': ['ID', 'VAL'], 'bounds': None},
'speed': {'method': 'Player.SetSpeed', 'set': True, 'get': False, 'params': ['playerid', 'speed'], 'values': ['ID', 'VAL'], 'bounds': [-32,-16,-8,-4,-2,-1,1,2,4,8,16,32]},
'subtitle': {'method': 'Player.SetSubtitle', 'set': True, 'get': False, 'params': ['playerid', 'subtitle', 'enable'], 'values': ['ID', 'VAL', ('False if "VAL"=="off" else True',)], 'bounds': None},
'stop': {'method': 'Player.Stop', 'set': True, 'get': False, 'params': ['playerid'], 'values': ['ID'], 'bounds': None},
'goto': {'method': 'Player.GoTo', 'set': True, 'get': False, 'params': ['playerid', 'to'], 'values': ['ID', 'VAL'], 'bounds': ['previous','next']},
'power': {'method': 'System.Shutdown', 'set': True, 'get': False, 'params': None, 'values': None, 'bounds': None},
'quit': {'method': 'Application.Quit', 'set': True, 'get': False, 'params': None, 'values': None, 'bounds': None},
'mute': {'method': 'Application.SetMute', 'set': True, 'get': False, 'params': ['mute'], 'values': ['VAL'], 'bounds': None},
'volume': {'method': 'Application.SetVolume', 'set': True, 'get': False, 'params': ['volume'], 'values': ['VAL'], 'bounds': (0, 100)},
'action': {'method': 'Input.ExecuteAction', 'set': True, 'get': False, 'params': ['action'], 'values': ['VAL'], 'bounds': ['left','right','up','down','select','back','menu','info','pause','stop','skipnext','skipprevious','fullscreen','aspectratio','stepforward','stepback','osd','showsubtitles','nextsubtitle','cyclesubtitle','audionextlanguage','number1','number2','number3','number4','number5','number6','number7','number8','number9','fastforward','rewind','play','playpause','volumeup','volumedown','mute','enter']},
}

# 'macroname': [ [cmd1, val1], [cmd2, val2], [cmd3, val3], ...]. -- cmd can be one of commands.keys() or 'wait' to wait 'val' seconds
macros = {
'resume': [['action', 'play'], ['wait', 1], ['action', 'select']],
'beginning': [['action', 'play'], ['wait', 1], ['action', 'down'], ['action', 'select']]
}
299 changes: 299 additions & 0 deletions kodi/_pv_1_6_1/plugin.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
# Metadata for the classic-plugin
plugin:
# Global plugin attributes
type: interface # plugin type (gateway, interface, protocol, system, web)
description:
de: 'Anbindung von Kodi (ehemals XBMC)'
en: 'Connecting Kodi (formerly XBMC)'
requirements:
de: 'Es ist eine Kodi Installation v12 oder höher notwendig, bei der in den Einstellungen "Allow programs on other systems to control Kodi" aktiviert ist.'
en: 'You need one or more Kodi (12 a.k.a. Frodo or above) with system-settings-service "Allow programs on other systems to control Kodi" enabled.'
maintainer: Morg, onkelandy
tester: psilo
state: ready
keywords: mediacenter kodi xmbc
documentation: http://smarthomeng.de/user/plugins/kodi/user_doc.html
support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1364598-supportthread-für-kodi-plugin

# Following entries are for Smart-Plugins:
version: 1.6.1 # Plugin version
sh_minversion: 1.4 # minimum shNG version to use this plugin
# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest)
multi_instance: True
classname: Kodi # class containing the plugin
restartable: True

parameters:
# Definition of parameters to be configured in etc/plugin.yaml
host:
type: ip
mandatory: True
description:
de: 'Hostname oder IP-Adresse des Kodi-Systems'
en: 'Hostname or IP address of the Kodi system'

port:
type: int
valid_min: 1
valid_max: 65535
default: 9090
description:
de: 'Netzwerkport für die Steuerung des Kodi-Systems'
en: 'Network port for remote controlling the Kodi system'

autoreconnect:
type: bool
default: False
description:
de: 'Erneute Verbindungsversuche bei Verlust der Verbindung alle 30 Sekunden'
en: 'Try to reconnect after connection loss every 30 seconds.'

connect_retries:
type: int
default: 10
description:
de: 'Anzahl der Verbindungsversuche'
en: 'Amount of connection retries'

connect_cycle:
type: int
default: 5
description:
de: 'Pause zwischen Verbindungsversuchen'
en: 'Pause between connection retries'

command_timeout:
type: int
default: 5
description:
de: 'Zeit, nach der ein unbeantworteter Befehl erneut gesendet wird'
en: 'Time to resend command which were not answered'

command_repeat:
type: int
default: 2
description:
de: 'Anzahl der Wiederholversuche für unbeantwortete Befehle'
en: 'Repeat count for resending commands which were not answered'

item_attributes:
# Definition of item attributes defined by this plugin

kodi_item:
type: str
valid_list: ['quit', 'mute', 'volume', 'action', 'seek', 'audio', 'speed', 'subtitle', 'playpause', 'stop', 'goto', 'power', 'subtitles', 'streams', 'media', 'title', 'player', 'state', 'update', 'macro', 'get_favourites']
description:
de: 'Der Attributwert hängt von der gewünschten Funktion ab. Siehe Dokumentation für Details.'
en: 'The attribute value is dependant on the wanted function. Look at the documentation for details.'

item_structs:
info:
name: Vorlage-Struktur für Kodi Infos, die nicht aktiv verändert werden können.

state:
kodi_item@instance: state
type: str
visu_acl: ro

media:
kodi_item@instance: media
type: str
visu_acl: ro

title:
kodi_item@instance: title
type: str
visu_acl: ro

audiostreams:
kodi_item@instance: streams
type: list
visu_acl: ro

subtitles:
kodi_item@instance: subtitles
type: list
visu_acl: ro

player:
kodi_item@instance: player
type: num
visu_acl: ro

control:
name: Vorlage-Struktur für Kodi Befehle zum Steuern

update:
kodi_item@instance: update
type: bool
visu_acl: rw
enforce_updates: true
autotimer: 1 = false = latest

play:
type: bool
eval: sh...playpause() and not sh...stop()
enforce_updates: true
eval_trigger:
- ..stop
- ..playpause

play_cmd:
type: bool
enforce_updates: true
eval: sh....input('play') if not (sh...property.last_update_by.lower()[:4] in ('kodi', 'init', 'eval')) else None
eval_trigger: ..

pause:
type: bool
eval: not sh...playpause() and not sh...stop()
enforce_updates: true
eval_trigger:
- ..stop
- ..playpause

pause_cmd:
type: bool
enforce_updates: true
eval: sh....input('pause') if not (sh...property.last_update_by.lower()[:4] in ('kodi', 'init', 'eval')) else None
eval_trigger: ..

stop:
kodi_item@instance: stop
type: bool
visu_acl: rw
enforce_updates: true

playpause:
kodi_item@instance: playpause
type: bool
visu_acl: rw
enforce_updates: true

previous:
type: bool
eval: sh...input('skipprevious')
enforce_updates: true

next:
type: bool
eval: sh...input('skipnext')
enforce_updates: true

seek:
kodi_item@instance: seek
type: num
visu_acl: rw
enforce_updates: true

speed:
kodi_item@instance: speed
type: num
visu_acl: rw
enforce_updates: true

volume:
kodi_item@instance: volume
type: num
visu_acl: rw
enforce_updates: true

mute:
kodi_item@instance: mute
type: bool
visu_acl: rw
enforce_updates: true

macro:
kodi_item@instance: macro
type: str
visu_acl: rw
enforce_updates: true

on_off:
kodi_item@instance: power
enforce_updates: true
type: bool
visu_acl: rw

input:
kodi_item@instance: action
type: str
visu_acl: rw
enforce_updates: true

favourites:
kodi_item@instance: get_favourites
type: dict
visu_acl: rw
enforce_updates: true

audiostream:
kodi_item@instance: audio
type: foo
visu_acl: rw
enforce_updates: true

subtitle:
kodi_item@instance: subtitle
type: foo
visu_acl: rw
enforce_updates: true

examples:
name: Vorlage-Struktur mit weiteren Beispielen

select:
type: bool
eval: sh...input('select')
enforce_updates: True

contextmenu:
type: str
eval: sh...input('contextmenu')
enforce_updates: True

home:
type: bool
eval: sh...input('home')
enforce_updates: true


logic_parameters: NONE
# Definition of logic parameters defined by this plugin

plugin_functions:
# Definition of function interface of the plugin

notify:
type: str
description:
de: "Diese Funktion ermöglicht es, Mitteilungen an Kodi zu schicken. Beispiel: sh.kodi.notify('Door', 'Ding Dong'). 'kodi' ist dabei der Name der jeweiligen Plugin-Instanz und kein Item-Name."
en: "This function provies the functionallity to send notification messages to Kodi. Example: sh.kodi.notify('Door', 'Ding Dong'). 'kodi' is the name of the respective plugin instance, not an item name."

parameters:
title:
type: str
description:
de: 'Überschrift der Mitteilung'
en: 'Message header'

message:
type: str
description:
de: 'Text der Mitteilung'
en: 'Message body'

image:
type: str
default: None*
description:
de: 'URL des anzuzeigenden Bildes (z.B.: "http://smarthome.local/img/phone.png")'
en: 'URL of the image to display (e.g. "http://smarthome.local/img/phone.png")'

display_time:
type: int
default: 10000
description:
de: 'Dauer der Anzeige in msec'
en: 'Duration of image display in msec'
Loading

0 comments on commit ddc926e

Please sign in to comment.