Skip to content
Snippets Groups Projects
Commit 9d1952bc authored by owagner's avatar owagner
Browse files

V0.3 - 2015-03-22 - owagner

  - fixed division by zero when switching TV channels
  - now supports command/notify to send notifications
  - now supports command/play to start playback of files or items
  - now supports command/playbackstate to control the playback state
  
parent 50214602
Branches
Tags v0.3
No related merge requests found
...@@ -30,13 +30,13 @@ Settings ...@@ -30,13 +30,13 @@ Settings
The addon has three settings: The addon has three settings:
* the MQTT broker's IP address (defaults to 127.0.0.1) * the MQTT broker's IP address (defaults to 127.0.0.1)
* the MQTT broker's port. This defaults to 1883, which is standard. * the MQTT broker's port. This defaults to 1883, which is the MQTT standard port for unencrypted connections.
* the topic prefix which to use in all published and subscribed topics. Defaults to "kodi/". * the topic prefix which to use in all published and subscribed topics. Defaults to "kodi/".
Topics Topics
------ ------
The addon publishes on the following topics: The addon publishes on the following topics (prefixed with the configured topic prefix):
* connected: 2 if the addon is currently connected to the broker, 0 otherwise. This topic is set to 0 with a MQTT will. * connected: 2 if the addon is currently connected to the broker, 0 otherwise. This topic is set to 0 with a MQTT will.
* status/playbackstate: a JSON-encoded object with the fields * status/playbackstate: a JSON-encoded object with the fields
...@@ -53,9 +53,23 @@ The addon publishes on the following topics: ...@@ -53,9 +53,23 @@ The addon publishes on the following topics:
- "kodi_details": an object with further details about the current playback items. This is effectivly the result - "kodi_details": an object with further details about the current playback items. This is effectivly the result
of a JSON-RPC call Player.GetItem with the properties "title", "streamdetails" and "file" of a JSON-RPC call Player.GetItem with the properties "title", "streamdetails" and "file"
The addon listens to the following topics (prefixed with the configured topic prefix):
* command/notify: Either a simple string, or a JSON encoded object with the fields "message" and "title". Shows
a popup notification in Kodi
* command/play: Either a simple string which is a filename or URL, or a JSON encoded object which correspondents
to the Player.Open() JSON_RPC call
* command/playbackstate: A simple string or numeric with the values:
- "0" or "stop" to stop playback
- "1" or "resume" to resume playback (when paused)
- "2" or "pause" to stop playback (when playing)
- "next" to play the next track
- "previous" to play the previous track
See also See also
-------- --------
- JSON-RPC API v6 in Kodi: http://kodi.wiki/view/JSON-RPC_API/v6
- Project overview: https://github.com/mqtt-smarthome - Project overview: https://github.com/mqtt-smarthome
......
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="service.mqtt" name="MQTT Adapter" version="0.2" provider-name="owagner"> <addon id="service.mqtt" name="MQTT Adapter" version="0.3" provider-name="owagner">
<requires> <requires>
<import addon="xbmc.python" version="2.19.0"/> <import addon="xbmc.python" version="2.19.0"/>
</requires> </requires>
......
V0.3 - 2015-03-22 - owagner
- fixed division by zero when switching TV channels
- now supports command/notify to send notifications
- now supports command/play to start playback of files or items
- now supports command/playbackstate to control the playback state
V0.2 - 2015-03-22 - owagner V0.2 - 2015-03-22 - owagner
- refactored as a Kodi addon - refactored as a Kodi addon
\ No newline at end of file
...@@ -17,6 +17,11 @@ def sendrpc(method,params): ...@@ -17,6 +17,11 @@ def sendrpc(method,params):
xbmc.log("MQTT: JSON-RPC call "+method+" returned "+res) xbmc.log("MQTT: JSON-RPC call "+method+" returned "+res)
return json.loads(res) return json.loads(res)
#
# Publishes a MQTT message. The topic is built from the configured
# topic prefix and the suffix. The message itself is JSON encoded,
# with the "val" field set, and possibly more fields merged in.
#
def publish(suffix,val,more): def publish(suffix,val,more):
global topic,mqc global topic,mqc
robj={} robj={}
...@@ -28,6 +33,10 @@ def publish(suffix,val,more): ...@@ -28,6 +33,10 @@ def publish(suffix,val,more):
xbmc.log("MQTT: Publishing @"+fulltopic+": "+jsonstr) xbmc.log("MQTT: Publishing @"+fulltopic+": "+jsonstr)
mqc.publish(fulltopic,jsonstr,qos=0,retain=True) mqc.publish(fulltopic,jsonstr,qos=0,retain=True)
#
# Set and publishes the playback state. Publishes more info if
# the state is "playing"
#
def setplaystate(state,detail): def setplaystate(state,detail):
global activeplayerid global activeplayerid
if state==1: if state==1:
...@@ -42,6 +51,9 @@ def setplaystate(state,detail): ...@@ -42,6 +51,9 @@ def setplaystate(state,detail):
def convtime(ts): def convtime(ts):
return("%02d:%02d:%02d" % (ts/3600,(ts/60)%60,ts%60)) return("%02d:%02d:%02d" % (ts/3600,(ts/60)%60,ts%60))
#
# Publishes playback progress
#
def publishprogress(): def publishprogress():
global player global player
if not player.isPlaying(): if not player.isPlaying():
...@@ -50,15 +62,16 @@ def publishprogress(): ...@@ -50,15 +62,16 @@ def publishprogress():
tt=player.getTotalTime() tt=player.getTotalTime()
if pt<0: if pt<0:
pt=0 pt=0
if tt>0:
progress=(pt*100)/tt progress=(pt*100)/tt
else:
progress=0
state={"kodi_time":convtime(pt),"kodi_totaltime":convtime(tt)} state={"kodi_time":convtime(pt),"kodi_totaltime":convtime(tt)}
publish("progress",round(progress,1),state) publish("progress",round(progress,1),state)
def reportprogress(): #
global monitor # Publish more details about the currently playing item
while not monitor.waitForAbort(30): #
publishprogress()
def publishdetails(): def publishdetails():
global player,activeplayerid global player,activeplayerid
if not player.isPlaying(): if not player.isPlaying():
...@@ -67,6 +80,9 @@ def publishdetails(): ...@@ -67,6 +80,9 @@ def publishdetails():
publish("title",res["result"]["item"]["title"],{"kodi_details":res["result"]["item"]}) publish("title",res["result"]["item"]["title"],{"kodi_details":res["result"]["item"]})
publishprogress() publishprogress()
#
# Notification subclasses
#
class MQTTMonitor(xbmc.Monitor): class MQTTMonitor(xbmc.Monitor):
def onSettingsChanged(self): def onSettingsChanged(self):
global mqc global mqc
...@@ -102,6 +118,54 @@ class MQTTPlayer(xbmc.Player): ...@@ -102,6 +118,54 @@ class MQTTPlayer(xbmc.Player):
def onPlayBackSpeedChanged(speed): def onPlayBackSpeedChanged(speed):
setplaystate(1,"speed") setplaystate(1,"speed")
def onQueueNextItem():
xbmc.log("MQTT onqn");
#
# Handles commands
#
def processnotify(data):
try:
params=json.loads(data)
except ValueError:
parts=data.split(None,2)
params={"title":parts[0],"message":parts[1]}
sendrpc("GUI.ShowNotification",params)
def processplay(data):
try:
params=json.loads(data)
sendrpc("Player.Open",params)
except ValueError:
player.play(data)
def processplaybackstate(data):
if data=="0" or data=="stop":
player.stop()
elif data=="1" or data=="resume":
if not player.isPlaying():
player.pause()
elif data=="2" or data=="pause":
if player.isPlaying():
player.pause()
elif data=="next":
player.playnext()
elif data=="previous":
player.playprevious()
def processcommand(topic,data):
if topic=="notify":
processnotify(data)
elif topic=="play":
processplay(data)
elif topic=="playbackstate":
processplaybackstate(data)
else:
xbmc.log("MQTT: Unknown command "+topic)
#
# Handles incoming MQTT messages
#
def msghandler(mqc,userdata,msg): def msghandler(mqc,userdata,msg):
try: try:
global topic global topic
...@@ -122,6 +186,10 @@ def disconnecthandler(mqc,userdata,rc): ...@@ -122,6 +186,10 @@ def disconnecthandler(mqc,userdata,rc):
time.sleep(5) time.sleep(5)
mqc.reconnect() mqc.reconnect()
#
# Starts connection to the MQTT broker, sets the will
# and subscribes to the command topic
#
def startmqtt(): def startmqtt():
global topic,mqc global topic,mqc
mqc=mqtt.Client() mqc=mqtt.Client()
...@@ -137,14 +205,16 @@ def startmqtt(): ...@@ -137,14 +205,16 @@ def startmqtt():
mqc.publish(topic+"connected",2,qos=1,retain=True) mqc.publish(topic+"connected",2,qos=1,retain=True)
mqc.loop_start() mqc.loop_start()
#
# Addon initialization and shutdown
#
if (__name__ == "__main__"): if (__name__ == "__main__"):
global monitor,player global monitor,player
xbmc.log('MQTT: MQTT Adapter Version %s started' % __version__) xbmc.log('MQTT: MQTT Adapter Version %s started' % __version__)
monitor=MQTTMonitor() monitor=MQTTMonitor()
player=MQTTPlayer() player=MQTTPlayer()
progressthread=threading.Thread(target=reportprogress)
progressthread.start()
startmqtt() startmqtt()
monitor.waitForAbort() while not monitor.waitForAbort(30):
publishprogress()
mqc.loop_stop(True) mqc.loop_stop(True)
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment