Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

decode JSON data from message #176

Closed
wants to merge 1 commit into from
Closed

Conversation

rschaten
Copy link

I don't have much experience with MQTT or with mqttwarn, so I'd be happy to learn that I'm doing something wrong and this pull isn't necessary. However, it works for me. :-)

I configured an XBMC target in mqttwarn.ini. I want to send a message with a title and an image, as shown in #53 (got my home phone system to talk MQTT, by the way):

mosquitto_pub -t xbmc/command/notify -m '{"message": "Call from <number>", "title": "Phone is ringing!", "image": "/storage/phone-icon.png"}'

XBMC shows a notification, but the message text contains the undecoded JSON data. In xbmc.py, this data is delivered in item.message, so I wrote these few lines to decode it.

Again: this works for me. I didn't find another way, I'd like to see a working example.

@jpmens
Copy link
Collaborator

jpmens commented Mar 22, 2016

Thanks for this, which sounds useful. I don't think we can take it as it stands, though, because you're clobbering the passed title from the configuration; furthermore, you're not protecting against the payload not containing JSON.

However, I'll wait to see what @sumnerboy12 says about this.

@sumnerboy12
Copy link
Collaborator

Yes I agree with @jpmens - what you need to do is write a simple function which pulls out the attributes from your JSON payload and updates the title and message (and image) fields that are passed to the XBMC target.

By doing this it also means the message can be delivered to any mqttwarn target.

See here for details.

@rschaten
Copy link
Author

OK, obviously I'm doing something wrong here. I would be very happy if you show me the right way, @sumnerboy12. I tried breaking this down to the most simple problem, so I try using it without any function or template (I already used a template to form the message for XBMC), and without my phone system.

This is the relevant part from my mqttwarn.ini:

[config:xbmc]
targets = { 'nuc' : [ '192.168.0.12:80' ] }

[xbmctest]
topic = xbmctest
targets = xbmc:nuc

Having that configured, I try using it like this:

mosquitto_pub -t xbmctest -m '{"title":"TITLE","message":"MESSAGE"}'

This results in XBMC displaying a message with the title MQTTWARN (uppercase, because of my theme) and the message {"title":"TITLE","message":"MESSAGE"}.

To find out what's going on here, I simply printed the item in services/xbmc.py, right before title, message and image are assigned. This is what I get:

<topic: 'xbmctest'
 target: u'nuc'
 service: u'xbmc'
 title: 'mqttwarn'
 data: {'_dtepoch': 1458811662, '_dtiso': '2016-03-24T09:27:42.745806Z', u'title':u'TITLE', 'topic': 'xbmctest', '_dthhmm': '10:27', u'message': u'MESSAGE', 'payload': '{"title":"TITLE","message":"MESSAGE"}', '_dthhmmss': '10:27:42'}
 image: ''
 payload: '{"title":"TITLE","message":"MESSAGE"}'
 priority: 0
 addrs: ['192.168.0.12:80']
 message: '{"title":"TITLE","message":"MESSAGE"}'
 config: {}
 section: u'xbmctest'>

This made me think that the JSON has do be decoded before title and message can be extracted.

It seems to work for @sumnerboy12, so my hope that this pull-request isn't necessary seems to be fulfilled. I just would like to learn how to use this module.

Aside from that, I agree with @jpmens: I should have protected against non-JSON messages. And I probably should have tried decoding item.payload, not item.message. Shame on me. :-/

@sumnerboy12
Copy link
Collaborator

You will need a custom function, which when called for this target can decode the JSON payload, extract the title and message, and update the dict (you printed above). There is an example on the page I linked above, which may not be exactly what you want but you should get the drift. By default there is no post processing of the payload, and it is copied across as the message, i.e. what you are seeing above.

@rschaten
Copy link
Author

OK, I'm beginning to feel a little stupid, here. Even more than usual...

Now I tried a function. To keep it simple, I try setting fixed values for title and message:

def xbmctest(topic, data, srv=None):
    return dict(title='TITLE', message='MESSAGE')

In mqttwarn.ini I configured this:

[xbmctest]
topic = xbmctest
alldata = xbmctest()
targets = xbmc:nuc

Instead of alldata, I also tried using datamap and format.
With alldata and datamap, my returned dict is merged into item.data, but item.title is still 'mqttwarn' and item.message is still the message that I sent, it doesn't get changed.
With format, the returned dict is converted to JSON and put into item.message, while item.title stays 'mqttwarn'.

In a desperate try, I even tried returning a fixed string from my function:

def xbmctest(topic, data, srv=None):
    return 'FIXEDSTRING'

As expected, this is in 'item.message' when I use format = xbmctest(), it doesn't get mentioned if I use alldata or datamap.

Can you please show me how to write the function so that I can overwrite item.title? I would have expected a simple return dict(title='TITLE') to do that, but obviously I'm wrong...

Oh, and I really want to thank you for dealing with my problems: Thanks a lot!

@sumnerboy12
Copy link
Collaborator

Ok, taking a step back, forgetting about functions, can you try this;

title = {title}
format = {message}

@rschaten
Copy link
Author

Thank you very much! I really didn't get the concept how this is supposed to work. Well, I'm not sure if I got it now, but: it works!

I thought that the function or the jinja2-template (that's what I tried before even creating the pull request) are supposed to create the title and the message that end up in services/xbmc.py's item.title or item.message. Now, it looks as if the function/template should modify the given data, so that for example the title can still be assigned like title = {somedata} in mqttwarn.ini.

In case somebody else has the same problem (or if anybody wants to show me that I'm still doing it wrong), I'll just show what I did:

This lives in my mqttwarn.ini:

[config:xbmc]
targets = { 'nuc' : [ '192.168.0.12:80' ] }

[phonecall2xbmc]
topic = compact3000/json/start
alldata = phonecall2xbmc()
title = {xbmctitle}
format = {xbmcmessage}
image = /storage/phone-icon.png
targets = xbmc:nuc, file:mylog

And in localfunctions.py, basically this:

import json

def phonecall2xbmc(topic, data, srv=None):
    payload = json.loads(data['payload'])
    # some dirty reformatting, creating xbmctitle and xbmcmessage strings
    return dict(xbmctitle = xbmctitle, xbmcmessage = xbmcmessage)

Finally, I'm happy with this software again. I'm sure I will have much more fun with it in the future.

@sumnerboy12
Copy link
Collaborator

Glad you got there in there end!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants