IP controlled relay board

If you have a question or need help, this is the place to be.
Peter M
Posts: 45
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Wed May 20, 2020 8:29 am

Here's the latest -

Code: Select all

import requests

data = '''\
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <s:Body>
        <u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
            <ObjectID>Q:0</ObjectID>
            <BrowseFlag>BrowseDirectChildren</BrowseFlag>
            <Filter>dc:title,dc:creator</Filter>
             <StartingIndex>{starting_index}</StartingIndex>
            <RequestedCount>10</RequestedCount>
            <SortCriteria></SortCriteria>
        </u:Browse>
    </s:Body>
</s:Envelope>
'''

starting_index = eg.event.payload.split('=')[-1]
data = data.format(starting_index=starting_index )

headers = {
    'Content-Type': 'text/html; charset=UTF-8',
    'SOAPACTION': 'urn:schemas-upnp-org:service:ContentDirectory:1#Browse',
    'Content-Length': len(data)
}

response = requests.post('http://192.168.0.32:1400/MediaServer/ContentDirectory/Control', data=data, headers=headers)

from xml.etree import ElementTree

data = response.content

# this function strips namespace information
def strip_namespaces(in_data):
    lines = []
    line = ''

    for char in list(in_data):
        if char == '>':
            line += char
            lines += [line]
            line = ''
            continue
        elif char == '<' and line:
            lines += [line]
            line = ''

        line += char

    if line:
        lines += [line]

    for i, line in enumerate(lines):
        if '<' not in line:
            continue

        while 'xmlns=' in line:
            beg, end = line.split('xmlns=', 1)
            end = end.split('"', 2)[-1].strip()
            line = beg + end

        while 'xmlns:' in line:
            beg, end = line.split('xmlns:', 1)
            xmlns, end = end.split('=', 1)
            end = end.split('"', 2)[-1].strip()
            line = beg + end

            while xmlns + ':encodingStyle=' in line:
                beg, end = line.split(xmlns + ':encodingStyle=', 1)
                end = end.split('"', 2)[-1].strip()
                line = beg + end

            lines[i] = line

            for j, lne in enumerate(lines[i:]):
                if '<' not in lne:
                    continue
                lne = lne.replace('<' + xmlns + ':', '<')
                lne = lne.replace('</' + xmlns + ':', '</')

                lines[i + j] = lne

    out_data = ''.join(lines)
    return ''.join(line for line in out_data.split('\n'))

# strip the namespace data here
data = strip_namespaces(data)

# create an xml object from the stripped data
xml = ElementTree.fromstring(data)

# locate the elements that we are looking for
body = xml.find('Body')
browse_response = body.find('BrowseResponse')
result = browse_response.find('Result')

# data is stored in the text area of the result field
data = result.text

# strip the namespaces from the result data
data = strip_namespaces(data)

# turn the result data into an xml object
xml = ElementTree.fromstring(data.encode('utf-8'))

track = 1
for item in xml:
    message = 'artist' + str(track) + ':' + item.find('creator').text + ':'
    eg.plugins.BroadcastListener.Broadcast(message, u'', 33339)

    message = 'title' + str(track) + ':' + item.find('title').text + ':'
    eg.plugins.BroadcastListener.Broadcast(message, u'', 33339)

    if track == 1:
        message = 'artist:' + item.find('creator').text + ':'
        message = message.replace('!', '%21')
        message = message.replace('&', '%26')
        message = message.replace(';', '%3B')
        eg.plugins.BroadcastListener.Broadcast(message, u'', 33339)
        
        message = 'album:' + item.find('album').text + ':'
        message = message.replace('!', '%21')
        message = message.replace('&', '%26')
        message = message.replace(';', '%3B')
        eg.plugins.BroadcastListener.Broadcast(message, u'', 33339)
        
#    print 'res:', item.find('res').text
#    print 'albumArtURI:', item.find('albumArtURI').text
#    print 'class:', item.find('class').text

    track = track + 1
        
while track < 11:
    message = 'artist' + str(track) + ':  :'
    eg.plugins.BroadcastListener.Broadcast(message, u'', 33339)

    message = 'title' + str(track) + ':  :'
    eg.plugins.BroadcastListener.Broadcast(message, u'', 33339)
    
    track = track + 1

Cheers,
Peter

User avatar
kgschlosser
Site Admin
Posts: 5341
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: IP controlled relay board

Post by kgschlosser » Thu May 21, 2020 4:56 am

give this whirly bird a twirl.

Code: Select all

import requests

data = '''\
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <s:Body>
        <u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
            <ObjectID>Q:0</ObjectID>
            <BrowseFlag>BrowseDirectChildren</BrowseFlag>
            <Filter>dc:title,dc:creator</Filter>
             <StartingIndex>{starting_index}</StartingIndex>
            <RequestedCount>10</RequestedCount>
            <SortCriteria></SortCriteria>
        </u:Browse>
    </s:Body>
</s:Envelope>
'''

starting_index = eg.event.payload.split('=')[-1]
data = data.format(starting_index=starting_index)

headers = {
    'Content-Type': 'text/html; charset=UTF-8',
    'SOAPACTION': 'urn:schemas-upnp-org:service:ContentDirectory:1#Browse',
    'Content-Length': len(data)
}

response = requests.post(
    'http://192.168.0.32:1400/MediaServer/ContentDirectory/Control',
    data=data, 
    headers=headers
)

from xml.etree import ElementTree

data = response.content


# this function strips namespace information
def strip_namespaces(in_data):
    lines = []
    line = ''

    for char in list(in_data):
        if char == '>':
            line += char
            lines += [line]
            line = ''
            continue
        elif char == '<' and line:
            lines += [line]
            line = ''

        line += char

    if line:
        lines += [line]

    for i, line in enumerate(lines):
        if '<' not in line:
            continue

        while 'xmlns=' in line:
            beg, end = line.split('xmlns=', 1)
            end = end.split('"', 2)[-1].strip()
            line = beg + end

        while 'xmlns:' in line:
            beg, end = line.split('xmlns:', 1)
            xmlns, end = end.split('=', 1)
            end = end.split('"', 2)[-1].strip()
            line = beg + end

            while xmlns + ':encodingStyle=' in line:
                beg, end = line.split(xmlns + ':encodingStyle=', 1)
                end = end.split('"', 2)[-1].strip()
                line = beg + end

            lines[i] = line

            for j, lne in enumerate(lines[i:]):
                if '<' not in lne:
                    continue
                lne = lne.replace('<' + xmlns + ':', '<')
                lne = lne.replace('</' + xmlns + ':', '</')

                lines[i + j] = lne

    out_data = ''.join(lines)
    return ''.join(line for line in out_data.split('\n'))


# strip the namespace data here
data = strip_namespaces(data)

# create an xml object from the stripped data
xml = ElementTree.fromstring(data)

# locate the elements that we are looking for
body = xml.find('Body')
browse_response = body.find('BrowseResponse')
result = browse_response.find('Result')

# data is stored in the text area of the result field
data = result.text

# strip the namespaces from the result data
data = strip_namespaces(data)

# So i added the xml decleration line which has an encoding attribute.
# I am hoping this is going to solve the issue you are having. 
# if it does not this is bacause the encoding that is being used
# by your computer running EG differs from the encoding that is being used by
# your media server. we may have to do some additional encoding and decoding 
# to give it a kick in the ass to work, but lets give this a shot first.
data = '<?xml version="1.0" encoding="UTF-8" ?>' + data
# turn the result data into an xml object
xml = ElementTree.fromstring(data)


# OK so here I subclassed str to build a custom formatter that 
# will remove any special characters if needed.
class SpecialFormat(str):

    def format(self, *args, **kwargs):
        if 'replace' in kwargs:
            args = '**??**'.join(str(itm) for itm in args)
            for pattern, value in (
                    ('!', '%21'),
                    ('&', '%26'),
                    (';', '%3B'),
            ):
                args = args.replace(pattern, value)
            args = args.split('**??**')

        return str.format(self, *args)

# because you were doing quite a bit of adding strings together
# and also because you had these 3 packate you are sending it
# is more efficient code to declare the packet a single time 
# and then plug in the information we need. the {0} and {1}
# mean argument 1 and argument 2 for the method format()
artist = SpecialFormat('artist{0}:{1}:')
title = SpecialFormat('title{0}:{1}:')
album = SpecialFormat('album{0}:{1}:')

# just a code reducing function. I set 
# the payload to None because you are not 
# sending any payload data.
def send(msg):
    eg.plugins.BroadcastListener.Broadcast(msg, None, 33339)


# reduction of code using a different iteration 
# technique to get the track number.
# I also used that new send function along with using format() 
# to reduce the amount of code needed here.
for track, item in enumerate(xml, start=1):
    send(artist.format(track, item.find('creator').text))
    send(title.format(track, item.find('title').text))

    if not track:
        send(artist.format('', item.find('creator').text, replace=True))
        send(album.format('', item.find('album').text, replace=True))
        # print 'res:', item.find('res').text
        # print 'albumArtURI:', item.find('albumArtURI').text
        # print 'class:', item.find('class').text

for track in range(track, 11):
    send(artist.format(track, '  '))
    send(title.format(track, '  '))

If you like the work I have been doing then feel free to Image

Peter M
Posts: 45
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Fri May 22, 2020 7:43 am

A couple of problems.

1. It's no longer sending artist and album, and instead its sending two artist10 and title10 with the second ones blank -

udp.artist1:k.d. lang:
udp.title1:Season of Hollow Soul:
udp.artist2:k.d. lang:
udp.title2:Constant Craving:
udp.artist3:Kate Bush:
udp.title3:Wuthering Heights:
udp.artist4:Kate Bush:
udp.title4:Feel It:
udp.artist5:Kylie Minogue:
udp.title5:Butterfly:
udp.artist6:Kylie Minogue:
udp.title6:Light Years:
udp.artist7:Kylie Minogue:
udp.title7:The One:
udp.artist8:Leona Lewis:
udp.title8:Run:
udp.artist9:Lighthouse Family:
udp.title9:Free/One:
udp.artist10:Lighthouse Family:
udp.title10:Whatever Gets You Through the Day:
udp.artist10: :
udp.title10: :

2. Accented characters are still tripping it up -

Traceback (most recent call last):
Python script "63", line 117, in <module>
xml = ElementTree.fromstring(data)
File "xml\etree\ElementTree.pyc", line 963, in XML
File "xml\etree\ElementTree.pyc", line 1245, in feed
UnicodeEncodeError: 'ascii' codec can't encode character u'\xeb' in position 479: ordinal not in range(128)

Cheers,
Peter

Peter M
Posts: 45
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Fri May 22, 2020 8:42 am

When there are less than 10 items in the queue the repeat is always on the last one. Here it's artist5 and title5 -

udp.artist1:Hunters & Collectors:
udp.title1:True Tears of Joy:
udp.artist2:Hunters & Collectors:
udp.title2:Where Do You Go?:
udp.artist3:Hunters & Collectors:
udp.title3:Back in the Hole:
udp.artist4:Hunters & Collectors:
udp.title4:Holy Grail:
udp.artist5:Hunters & Collectors:
udp.title5:Throw Your Arms Around Me:
udp.artist5: :
udp.title5: :
udp.artist6: :
udp.title6: :
udp.artist7: :
udp.title7: :
udp.artist8: :
udp.title8: :
udp.artist9: :
udp.title9: :
udp.artist10: :
udp.title10: :

Peter M
Posts: 45
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Wed May 27, 2020 12:35 pm

I made a couple of minor changes to this section -

Code: Select all

for track, item in enumerate(xml, start=1):
    send(artist.format(track, item.find('creator').text))
    send(title.format(track, item.find('title').text))

    if track ==1:
        send(artist.format('', item.find('creator').text, replace=True))
        send(album.format('', item.find('album').text, replace=True))
        # print 'res:', item.find('res').text
        # print 'albumArtURI:', item.find('albumArtURI').text
        # print 'class:', item.find('class').text

for track in range(track+1, 11):
    send(artist.format(track, '  '))
    send(title.format(track, '  '))
and it fixed problem 1.

The accented chars are still a problem.

Cheers,
Peter

User avatar
kgschlosser
Site Admin
Posts: 5341
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: IP controlled relay board

Post by kgschlosser » Wed May 27, 2020 9:45 pm

let me see the error you are getting now after the changes have been made. I am wondering if the problem may have moved to a new location.
If you like the work I have been doing then feel free to Image

Peter M
Posts: 45
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Thu May 28, 2020 1:58 pm

Here's the latest code -

Code: Select all

import requests

data = '''\
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <s:Body>
        <u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
            <ObjectID>Q:0</ObjectID>
            <BrowseFlag>BrowseDirectChildren</BrowseFlag>
            <Filter>dc:title,dc:creator</Filter>
             <StartingIndex>{starting_index}</StartingIndex>
            <RequestedCount>10</RequestedCount>
            <SortCriteria></SortCriteria>
        </u:Browse>
    </s:Body>
</s:Envelope>
'''

starting_index = eg.event.payload.split('=')[-1]
data = data.format(starting_index=starting_index)

headers = {
    'Content-Type': 'text/html; charset=UTF-8',
    'SOAPACTION': 'urn:schemas-upnp-org:service:ContentDirectory:1#Browse',
    'Content-Length': len(data)
}

response = requests.post(
    'http://192.168.0.32:1400/MediaServer/ContentDirectory/Control',
    data=data, 
    headers=headers
)

from xml.etree import ElementTree

data = response.content


# this function strips namespace information
def strip_namespaces(in_data):
    lines = []
    line = ''

    for char in list(in_data):
        if char == '>':
            line += char
            lines += [line]
            line = ''
            continue
        elif char == '<' and line:
            lines += [line]
            line = ''

        line += char

    if line:
        lines += [line]

    for i, line in enumerate(lines):
        if '<' not in line:
            continue

        while 'xmlns=' in line:
            beg, end = line.split('xmlns=', 1)
            end = end.split('"', 2)[-1].strip()
            line = beg + end

        while 'xmlns:' in line:
            beg, end = line.split('xmlns:', 1)
            xmlns, end = end.split('=', 1)
            end = end.split('"', 2)[-1].strip()
            line = beg + end

            while xmlns + ':encodingStyle=' in line:
                beg, end = line.split(xmlns + ':encodingStyle=', 1)
                end = end.split('"', 2)[-1].strip()
                line = beg + end

            lines[i] = line

            for j, lne in enumerate(lines[i:]):
                if '<' not in lne:
                    continue
                lne = lne.replace('<' + xmlns + ':', '<')
                lne = lne.replace('</' + xmlns + ':', '</')

                lines[i + j] = lne

    out_data = ''.join(lines)
    return ''.join(line for line in out_data.split('\n'))


# strip the namespace data here
data = strip_namespaces(data)

# create an xml object from the stripped data
xml = ElementTree.fromstring(data)

# locate the elements that we are looking for
body = xml.find('Body')
browse_response = body.find('BrowseResponse')
result = browse_response.find('Result')

# data is stored in the text area of the result field
data = result.text

# strip the namespaces from the result data
data = strip_namespaces(data)

# So i added the xml decleration line which has an encoding attribute.
# I am hoping this is going to solve the issue you are having. 
# if it does not this is bacause the encoding that is being used
# by your computer running EG differs from the encoding that is being used by
# your media server. we may have to do some additional encoding and decoding 
# to give it a kick in the ass to work, but lets give this a shot first.
data = '<?xml version="1.0" encoding="UTF-8" ?>' + data
# turn the result data into an xml object
xml = ElementTree.fromstring(data)


# OK so here I subclassed str to build a custom formatter that 
# will remove any special characters if needed.
class SpecialFormat(str):

    def format(self, *args, **kwargs):
        if 'replace' in kwargs:
            args = '**??**'.join(str(itm) for itm in args)
            for pattern, value in (
                    ('!', '%21'),
                    ('&', '%26'),
                    (';', '%3B'),
            ):
                args = args.replace(pattern, value)
            args = args.split('**??**')

        return str.format(self, *args)

# because you were doing quite a bit of adding strings together
# and also because you had these 3 packate you are sending it
# is more efficient code to declare the packet a single time 
# and then plug in the information we need. the {0} and {1}
# mean argument 1 and argument 2 for the method format()
artist = SpecialFormat('artist{0}:{1}:')
title = SpecialFormat('title{0}:{1}:')
album = SpecialFormat('album{0}:{1}:')

# just a code reducing function. I set 
# the payload to None because you are not 
# sending any payload data.
def send(msg):
    eg.plugins.BroadcastListener.Broadcast(msg, None, 33339)


# reduction of code using a different iteration 
# technique to get the track number.
# I also used that new send function along with using format() 
# to reduce the amount of code needed here.
for track, item in enumerate(xml, start=1):
    send(artist.format(track, item.find('creator').text))
    send(title.format(track, item.find('title').text))

    if track ==1:
        send(artist.format('', item.find('creator').text, replace=True))
        send(album.format('', item.find('album').text, replace=True))
        # print 'res:', item.find('res').text
        # print 'albumArtURI:', item.find('albumArtURI').text
        # print 'class:', item.find('class').text

for track in range(track+1, 11):
    send(artist.format(track, '  '))
    send(title.format(track, '  '))
and here's the error message -

Traceback (most recent call last):
Python script "65", line 117, in <module>
xml = ElementTree.fromstring(data)
File "xml\etree\ElementTree.pyc", line 963, in XML
File "xml\etree\ElementTree.pyc", line 1245, in feed
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 1775: ordinal not in range(128)

Cheers,
Peter

User avatar
kgschlosser
Site Admin
Posts: 5341
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: IP controlled relay board

Post by kgschlosser » Fri May 29, 2020 4:02 am

give this one a shot. for the life of me I can't remember if it needs to be encoded or decoded. But we will soon know.

Code: Select all

import requests

data = '''\
        <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
            <s:Body>
                <u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
                    <ObjectID>Q:0</ObjectID>
                    <BrowseFlag>BrowseDirectChildren</BrowseFlag>
                    <Filter>dc:title,dc:creator</Filter>
                     <StartingIndex>{starting_index}</StartingIndex>
                    <RequestedCount>10</RequestedCount>
                    <SortCriteria></SortCriteria>
                </u:Browse>
            </s:Body>
        </s:Envelope>
        '''

starting_index = eg.event.payload.split('=')[-1]
data = data.format(starting_index=starting_index)

headers = {
    'Content-Type': 'text/html; charset=UTF-8',
    'SOAPACTION': 'urn:schemas-upnp-org:service:ContentDirectory:1#Browse',
    'Content-Length': len(data)
}

response = requests.post(
    'http://192.168.0.32:1400/MediaServer/ContentDirectory/Control',
    data=data,
    headers=headers
)

from xml.etree import ElementTree

data = response.content


# this function strips namespace information
def strip_namespaces(in_data):
    lines = []
    line = ''

    for char in list(in_data):
        if char == '>':
            line += char
            lines += [line]
            line = ''
            continue
        elif char == '<' and line:
            lines += [line]
            line = ''

        line += char

    if line:
        lines += [line]

    for i, line in enumerate(lines):
        if '<' not in line:
            continue

        while 'xmlns=' in line:
            beg, end = line.split('xmlns=', 1)
            end = end.split('"', 2)[-1].strip()
            line = beg + end

        while 'xmlns:' in line:
            beg, end = line.split('xmlns:', 1)
            xmlns, end = end.split('=', 1)
            end = end.split('"', 2)[-1].strip()
            line = beg + end

            while xmlns + ':encodingStyle=' in line:
                beg, end = line.split(xmlns + ':encodingStyle=', 1)
                end = end.split('"', 2)[-1].strip()
                line = beg + end

            lines[i] = line

            for j, lne in enumerate(lines[i:]):
                if '<' not in lne:
                    continue
                lne = lne.replace('<' + xmlns + ':', '<')
                lne = lne.replace('</' + xmlns + ':', '</')

                lines[i + j] = lne

    out_data = ''.join(lines)
    return ''.join(line for line in out_data.split('\n'))


# strip the namespace data here
data = strip_namespaces(data)

# create an xml object from the stripped data
xml = ElementTree.fromstring(data)

# locate the elements that we are looking for
body = xml.find('Body')
browse_response = body.find('BrowseResponse')
result = browse_response.find('Result')

# data is stored in the text area of the result field
data = result.text

# strip the namespaces from the result data
data = strip_namespaces(data)

# So i added the xml decleration line which has an encoding attribute.
# I am hoping this is going to solve the issue you are having.
# if it does not this is bacause the encoding that is being used
# by your computer running EG differs from the encoding that is being used by
# your media server. we may have to do some additional encoding and decoding
# to give it a kick in the ass to work, but lets give this a shot first.
data = '<?xml version="1.0" encoding="UTF-8" ?>' + data
# turn the result data into an xml object
xml = ElementTree.fromstring(data.decode('utf-8'))


# OK so here I subclassed str to build a custom formatter that
# will remove any special characters if needed.
class SpecialFormat(str):

    def format(self, *args, **kwargs):
        if 'replace' in kwargs:
            args = '**??**'.join(str(itm) for itm in args)
            for pattern, value in (
                    ('!', '%21'),
                    ('&', '%26'),
                    (';', '%3B'),
            ):
                args = args.replace(pattern, value)
            args = args.split('**??**')

        return str.format(self, *args)


# because you were doing quite a bit of adding strings together
# and also because you had these 3 packate you are sending it
# is more efficient code to declare the packet a single time
# and then plug in the information we need. the {0} and {1}
# mean argument 1 and argument 2 for the method format()
artist = SpecialFormat('artist{0}:{1}:')
title = SpecialFormat('title{0}:{1}:')
album = SpecialFormat('album{0}:{1}:')


# just a code reducing function. I set
# the payload to None because you are not
# sending any payload data.
def send(msg):
    eg.plugins.BroadcastListener.Broadcast(msg, None, 33339)


# reduction of code using a different iteration
# technique to get the track number.
# I also used that new send function along with using format()
# to reduce the amount of code needed here.
for track, item in enumerate(xml, start=1):
    send(artist.format(track, item.find('creator').text))
    send(title.format(track, item.find('title').text))

    if track == 1:
        send(artist.format('', item.find('creator').text, replace=True))
        send(album.format('', item.find('album').text, replace=True))
        # print 'res:', item.find('res').text
        # print 'albumArtURI:', item.find('albumArtURI').text
        # print 'class:', item.find('class').text

for track in range(track + 1, 11):
    send(artist.format(track, '  '))
    send(title.format(track, '  '))
If you like the work I have been doing then feel free to Image

Peter M
Posts: 45
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Fri May 29, 2020 5:35 am

OK here's the error message from that one -

Traceback (most recent call last):
Python script "66", line 117, in <module>
xml = ElementTree.fromstring(data.decode('utf-8'))
File "encodings\utf_8.pyc", line 16, in decode
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 1223: ordinal not in range(128)

Cheers,
Peter

User avatar
kgschlosser
Site Admin
Posts: 5341
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: IP controlled relay board

Post by kgschlosser » Sat May 30, 2020 12:44 am

next!!!
LOL

Code: Select all

import requests

data = '''\
        <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
            <s:Body>
                <u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
                    <ObjectID>Q:0</ObjectID>
                    <BrowseFlag>BrowseDirectChildren</BrowseFlag>
                    <Filter>dc:title,dc:creator</Filter>
                     <StartingIndex>{starting_index}</StartingIndex>
                    <RequestedCount>10</RequestedCount>
                    <SortCriteria></SortCriteria>
                </u:Browse>
            </s:Body>
        </s:Envelope>
        '''

starting_index = eg.event.payload.split('=')[-1]
data = data.format(starting_index=starting_index)

headers = {
    'Content-Type': 'text/html; charset=UTF-8',
    'SOAPACTION': 'urn:schemas-upnp-org:service:ContentDirectory:1#Browse',
    'Content-Length': len(data)
}

response = requests.post(
    'http://192.168.0.32:1400/MediaServer/ContentDirectory/Control',
    data=data,
    headers=headers
)

from xml.etree import ElementTree

data = response.content


# this function strips namespace information
def strip_namespaces(in_data):
    lines = []
    line = ''

    for char in list(in_data):
        if char == '>':
            line += char
            lines += [line]
            line = ''
            continue
        elif char == '<' and line:
            lines += [line]
            line = ''

        line += char

    if line:
        lines += [line]

    for i, line in enumerate(lines):
        if '<' not in line:
            continue

        while 'xmlns=' in line:
            beg, end = line.split('xmlns=', 1)
            end = end.split('"', 2)[-1].strip()
            line = beg + end

        while 'xmlns:' in line:
            beg, end = line.split('xmlns:', 1)
            xmlns, end = end.split('=', 1)
            end = end.split('"', 2)[-1].strip()
            line = beg + end

            while xmlns + ':encodingStyle=' in line:
                beg, end = line.split(xmlns + ':encodingStyle=', 1)
                end = end.split('"', 2)[-1].strip()
                line = beg + end

            lines[i] = line

            for j, lne in enumerate(lines[i:]):
                if '<' not in lne:
                    continue
                lne = lne.replace('<' + xmlns + ':', '<')
                lne = lne.replace('</' + xmlns + ':', '</')

                lines[i + j] = lne

    out_data = ''.join(lines)
    return ''.join(line for line in out_data.split('\n'))


# strip the namespace data here
data = strip_namespaces(data)

# create an xml object from the stripped data
xml = ElementTree.fromstring(data)

# locate the elements that we are looking for
body = xml.find('Body')
browse_response = body.find('BrowseResponse')
result = browse_response.find('Result')

# data is stored in the text area of the result field
data = result.text

# strip the namespaces from the result data
data = strip_namespaces(data)

# So i added the xml decleration line which has an encoding attribute.
# I am hoping this is going to solve the issue you are having.
# if it does not this is bacause the encoding that is being used
# by your computer running EG differs from the encoding that is being used by
# your media server. we may have to do some additional encoding and decoding
# to give it a kick in the ass to work, but lets give this a shot first.
data = '<?xml version="1.0" encoding="UTF-8" ?>' + data
# turn the result data into an xml object
xml = ElementTree.fromstring(data.encode('utf-8'))


# OK so here I subclassed str to build a custom formatter that
# will remove any special characters if needed.
class SpecialFormat(str):

    def format(self, *args, **kwargs):
        if 'replace' in kwargs:
            args = '**??**'.join(str(itm) for itm in args)
            for pattern, value in (
                    ('!', '%21'),
                    ('&', '%26'),
                    (';', '%3B'),
            ):
                args = args.replace(pattern, value)
            args = args.split('**??**')

        return str.format(self, *args)


# because you were doing quite a bit of adding strings together
# and also because you had these 3 packate you are sending it
# is more efficient code to declare the packet a single time
# and then plug in the information we need. the {0} and {1}
# mean argument 1 and argument 2 for the method format()
artist = SpecialFormat('artist{0}:{1}:')
title = SpecialFormat('title{0}:{1}:')
album = SpecialFormat('album{0}:{1}:')


# just a code reducing function. I set
# the payload to None because you are not
# sending any payload data.
def send(msg):
    eg.plugins.BroadcastListener.Broadcast(msg, None, 33339)


# reduction of code using a different iteration
# technique to get the track number.
# I also used that new send function along with using format()
# to reduce the amount of code needed here.
for track, item in enumerate(xml, start=1):
    send(artist.format(track, item.find('creator').text))
    send(title.format(track, item.find('title').text))

    if track == 1:
        send(artist.format('', item.find('creator').text, replace=True))
        send(album.format('', item.find('album').text, replace=True))
        # print 'res:', item.find('res').text
        # print 'albumArtURI:', item.find('albumArtURI').text
        # print 'class:', item.find('class').text

for track in range(track + 1, 11):
    send(artist.format(track, '  '))
    send(title.format(track, '  '))
If you like the work I have been doing then feel free to Image

Peter M
Posts: 45
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Sat May 30, 2020 5:54 am

Different error -

Traceback (most recent call last):
Python script "67", line 160, in <module>
send(artist.format(track, item.find('creator').text))
Python script "67", line 135, in format
return str.format(self, *args)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xeb' in position 4: ordinal not in range(128)

Cheers,
Peter

Post Reply