belltown
Roku Guru
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-17-2017
02:39 PM
Re: FInd box on LAN
If you decide to go down the SSDP avenue, here's some BrightScript code you may be able to adapt to discover your Pi on the network. The code scans for all Rokus on the network so it can send them a wake-up request every hour. I left it running on my previously-unused Roku HD to prevent other Rokus on the network returning to the Home Screen after Roku implemented that "feature".
You'll need to change the search target, ST: roku:ecp, to correspond to what your Pi server uses.
You'll need code on your Pi that listens to port 1900 for the M-SEARCH request and responds appropriately. The code doesn't have to run in your Pi server; it can be running as a separate service in the Pi.
You'll need to change the search target, ST: roku:ecp, to correspond to what your Pi server uses.
You'll need code on your Pi that listens to port 1900 for the M-SEARCH request and responds appropriately. The code doesn't have to run in your Pi server; it can be running as a separate service in the Pi.
Sub Main ()
SLEEP_TIME_MINS = 60
Q = Chr (34)
CR = Chr (13)
LF = Chr (10)
port = CreateObject ("roMessagePort")
uiMsg = ""
uiMsg = uiMsg + "Keep this channel running to prevent" + LF
uiMsg = uiMsg + "all Rokus on this network" + LF
uiMsg = uiMsg + "returning to the Home Screen" + LF
uiMsg = uiMsg + LF + LF + "Press any key to exit"
ui = CreateObject ("roImageCanvas")
ui.SetMessagePort (port)
ui.SetLayer (0, {Color: "#303030"})
ui.SetLayer (1, {Text: uiMsg, TextAttrs: {Color: "#EBEBEB", Font: "Large", HAlign: "HCenter", VAlign: "VCenter"}})
ui.Show ()
ssdpStr = ""
ssdpStr = ssdpStr + "M-SEARCH * HTTP/1.1" + CR + LF
ssdpStr = ssdpStr + "HOST: 239.255.255.250:1900" + CR + LF
ssdpStr = ssdpStr + "MAN: " + Q + "ssdp:discover" + Q + CR + LF
ssdpStr = ssdpStr + "ST: roku:ecp" + CR + LF
ssdpStr = ssdpStr + "MX: 2" + CR + LF
ssdpStr = ssdpStr + CR + LF
ssdpAddr = CreateObject ("roSocketAddress")
ssdpAddr.SetAddress ("239.255.255.250:1900")
ssdp = CreateObject ("roDatagramSocket")
ssdp.SetMessagePort (port)
ssdp.SetSendToAddress (ssdpAddr)
ssdp.NotifyReadable (True)
ssdp.SendStr (ssdpStr)
ecpAddrList = {}
ut = CreateObject ("roUrlTransfer")
ut.SetPort (port)
ts = CreateObject ("roTimespan")
sleepTimeMs = SLEEP_TIME_MINS * 60 * 1000
While True
elapsed = ts.TotalMilliseconds ()
If elapsed >= sleepTimeMs
ts.Mark ()
elapsed = 0
For Each ecpAddr In ecpAddrList
ping (ut, ecpAddr)
End For
ssdp.SendStr (ssdpStr)
End If
msg = Wait (sleepTimeMs - elapsed, port)
If Type (msg) = "roSocketEvent"
If msg.GetSocketId () = ssdp.GetId ()
If ssdp.IsReadable ()
recvStr = ssdp.ReceiveStr (4096)
ma = CreateObject ("roRegex", "\r\nLocation:\s*(.*?)\s*\r\n", "i").Match (recvStr)
If ma.Count () = 2
ecpAddr = ma [1]
If Not ecpAddrList.DoesExist (ecpAddr)
ecpAddrList.AddReplace (ecpAddr, 0)
ping (ut, ecpAddr)
End If
End If
End If
End If
Else If Type (msg) = "roImageCanvasEvent"
If msg.IsRemoteKeyPressed ()
key = msg.GetIndex ()
If key <> 9200 And key <> 9300 ' Alarm Clock Key Press/Release '
Exit While
End If
End If
End If
End While
End Sub
Sub ping (ut As Object, ecpAddr As String)
ecpReq = ecpAddr + "keypress/Lit_%E2%8F%B0" ' Alarm Clock (U+23F0) '
ut.SetUrl (ecpReq)
ut.PostFromString("")
End Sub

squirreltown
Roku Guru
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-17-2017
03:16 PM
Re: FInd box on LAN
Awesome, thank you.
Kinetics Screensavers
EnTerr
Roku Guru
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-17-2017
03:45 PM
Re: FInd box on LAN
"squirreltown" wrote:
As was inevitable, I've built a thing that is too complex, uses too much bandwidth, and is too artsy to be a screensaver so I've decided it's an installation. The Pi is a web server, holds all the files and does Imagemagick processing. So anything I can do to make it slicker while demonstrating it seems worth the effort. I think I will try @belltown 's way first, but what you describe sounds like second choice for sure, If I get there I'll ask again about how I might go about that.
I see... well here is a 3rd option 🙂 - you can have RaspberryPi discover your Roku via SSDP (a few lines in Python, say) and then notify your channel about its own IP address via ECP /launch or /input. That way you won't have to find and implement UPnP server on R-Pi, something which (put understatedly) is an overkill

squirreltown
Roku Guru
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-18-2017
02:27 PM
Re: FInd box on LAN
Ok, so I made it work this way. Python file on Pi is setup as a looping service, sends the Pi i.p. to any roku device via ECP/input. The only issue is that the Python socket function that actually finds the roku ip seems to randomly find the boxes. i have 4 rokus, and it will find all of them within a few seconds, but it's random, if I had a large network it would be an issue. I'm going to try the more complex way but this looked like fruit i could reach.
Kinetics Screensavers
renojim
Community Streaming Expert
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-18-2017
04:33 PM
Re: FInd box on LAN
Would something like this combined with belltown's code be useful? I was going to go through the Python code I have (fauxmo) that allows Alexa (Amazon Echo) to discover my Dockstar to see how it works, but then I stumbled upon that code. I haven't tried it, but seems like it should work for SSDP discovery.
-JT
-JT
Roku Community Streaming Expert
Help others find this answer and click "Accept as Solution."
If you appreciate my answer, maybe give me a Kudo.
I am not a Roku employee.
Help others find this answer and click "Accept as Solution."
If you appreciate my answer, maybe give me a Kudo.
I am not a Roku employee.

squirreltown
Roku Guru
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-19-2017
06:06 AM
Re: FInd box on LAN
"renojim" wrote:
Would something like this combined with belltown's code be useful? I was going to go through the Python code I have (fauxmo) that allows Alexa (Amazon Echo) to discover my Dockstar to see how it works, but then I stumbled upon that code. I haven't tried it, but seems like it should work for SSDP discovery.
-JT
Hey thanks, that looks interesting too. I'm just learning python, and obviously the great thing about non-Brightscript languages is you can find enough examples in the wild to cobble together whatever you are trying to build.
Kinetics Screensavers
EnTerr
Roku Guru
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-19-2017
10:50 AM
Re: FInd box on LAN
Deploying yet another UPnP server so that one box can find another? We are so wielding a microscope to hammer a nail here.
Hmm, how exactly does this fn "actually find" the Roku IPs? I vaguely suspect something barbaric going on :twisted:
"squirreltown" wrote:
The only issue is that the Python socket function that actually finds the roku ip seems to randomly find the boxes.
Hmm, how exactly does this fn "actually find" the Roku IPs? I vaguely suspect something barbaric going on :twisted:

squirreltown
Roku Guru
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-19-2017
11:23 AM
Re: FInd box on LAN
EnTerr:Hmm, how exactly does this fn "actually find" the Roku IPs? I vaguely suspect something barbaric going on :twisted:
Since you are going to read this, mind telling me why it doesn't work with python3? 😉
Since you are going to read this, mind telling me why it doesn't work with python3? 😉
import requests
import curses
import socket
import string
import urllib
DISCOVER_GROUP = ('239.255.255.250', 1900)
DISCOVER_MESSAGE = '''\
M-SEARCH * HTTP/1.1\r\n\
Host: %s:%s\r\n\
Man: "ssdp:discover"\r\n\
ST: roku:ecp\r\n\r\n\
''' % DISCOVER_GROUP
def find_roku():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(DISCOVER_MESSAGE, DISCOVER_GROUP)
data = s.recv(1024)
s.close()
return data
def get_ip_address():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 80))
return s.getsockname()[0]
def keypress(url, key):
request_url = url + key
requests.post(request_url)
class HTTPResponse(object):
def __init__(self, response_text):
response = response_text.split('\r\n')
status_line = response[0].split()
self.http_version = status_line[0]
self.status_code = status_line[1]
self.status = status_line[2]
self.headers = {}
for line in response[1:]:
line = line.split()
if len(line) == 2:
header_name = line[0][:-1]
header_value = line[1]
self.headers[header_name.lower()] = header_value.lower()
def main():
value = get_ip_address()
print ('Searching for a Roku device...')
while True:
response_text = find_roku()
response = HTTPResponse(response_text)
url=response.headers['location']
print ('Found Roku@'+url[7:-6])
send = 'input?ip='+value
keypress(url, send)
if __name__ == '__main__':
main()
Kinetics Screensavers
EnTerr
Roku Guru
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-19-2017
12:53 PM
Re: FInd box on LAN
"squirreltown" wrote:...
Since you are going to read this, mind telling me why it doesn't work with python3? 😉
Not bad actually, where did you get the code?
Re Python 3 - no clue, i haven't moved to Py3k and just go with what comes in OSX (2.7). Generally code is compatible with minor tweaks though (e.g. py2 "print foo" -> py3 add parentheses "print(foo)")
For posterity here is something i whipped today being presumptuous you did not have the SSDP discovery code:
#!/usr/bin/python
def get_ecp_urls():
import socket, re
from time import time
# send a SSDP M-SEARCH looking for a Roku
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
MCAST_GRP = '239.255.255.250' # local network ssdp multicast address
qry = 'M-SEARCH * HTTP/1.1|HOST: %s:1900|MAN: "ssdp:discover"|ST: roku:ecp||' % MCAST_GRP
qry = qry.replace('|','\r\n')
sock.sendto(qry, (MCAST_GRP, 1900))
rokus = set()
sock.settimeout(0.1)
clk = time()
while time() < clk + 1: # wait for a whopping second to hear back
try:
dat, ip = sock.recvfrom(1024)
rokus.update(re.findall('\r\nLOCATION:\s*(.*)\r\n', dat, re.I))
except socket.timeout: pass
except socket.error, err: print "SSDP ERROR:", err
return sorted(rokus)
# demo run
print(get_ecp_urls())

squirreltown
Roku Guru
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-19-2017
01:26 PM
Re: FInd box on LAN
"EnTerr" wrote:
Not bad actually, where did you get the code?
One example for the network stuff, another for grabbing the local ip and I re-wrote main(). The roku returns it's serial # in the response.headers so it's easy to keep track that way if needed.
Kinetics Screensavers