Gear To Device Communication - Samsung Galaxy Gear

Hi All,
I'm very new to app development. I have created an app on my Note3 and a client on the Gear but im not sure how to get them talking. Does any one know if there is a Samsung api for doing this or can I just use BLE. Also does any one have a good BLE tutorial?
Thanks in advance.

taylordw said:
Hi All,
I'm very new to app development. I have created an app on my Note3 and a client on the Gear but im not sure how to get them talking. Does any one know if there is a Samsung api for doing this or can I just use BLE. Also does any one have a good BLE tutorial?
Thanks in advance.
Click to expand...
Click to collapse
We are still waiting for sdk to be released

taylordw said:
Hi All,
I'm very new to app development. I have created an app on my Note3 and a client on the Gear but im not sure how to get them talking. Does any one know if there is a Samsung api for doing this or can I just use BLE. Also does any one have a good BLE tutorial?
Thanks in advance.
Click to expand...
Click to collapse
I don't see how you could use Bluetooth protocols for this kind of architecture. You can try to open a Bluetoothsocket and use your own script language to do the talking. http://developer.android.com/reference/android/bluetooth/BluetoothSocket.html
But I would wait for a SDK. Sony also has a SDK for their watches. It makes developing a lot easier with intent-based APIs

BluetoothSocket
appelflap said:
I don't see how you could use Bluetooth protocols for this kind of architecture. You can try to open a Bluetoothsocket and use your own script language to do the talking.
But I would wait for a SDK. Sony also has a SDK for their watches. It makes developing a lot easier with intent-based APIs
Click to expand...
Click to collapse
Thanks for the pointer, that works! :good:
On the watch:
Code:
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothServerSocket bss = btAdapter.listenUsingRfcommWithServiceRecord("Test", UUID.fromString("c3f10dc0-677b-11e3-949a-0800200c9a66"));
BluetoothSocket bs = bss.accept();
byte[] buf = new byte[1024];
InputStream is = bs.getInputStream();
int read = is.read(buf);
is.close();
bs.close();
On the phone:
Code:
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> devices = btAdapter.getBondedDevices();
BluetoothDevice device = devices.iterator().next();
BluetoothSocket bs = device.createRfcommSocketToServiceRecord(UUID.fromString("c3f10dc0-677b-11e3-949a-0800200c9a66"));
bs.connect();
bs.getOutputStream().write("Hello!".getBytes("UTF-8"));
bs.getOutputStream().flush();
bs.getOutputStream().close();
bs.close();
This is just an example, but it works. Does anyone know if the the Bluetooth GATT APIs might be a better fit, and whether they might be able to control the lifecycle of the app on the watch?

Data Transfer between Samsung Galaxy Note 3 and Samsung Galaxy Gear?
surlydre said:
Thanks for the pointer, that works! :good:
On the watch:
Code:
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothServerSocket bss = btAdapter.listenUsingRfcommWithServiceRecord("Test", UUID.fromString("c3f10dc0-677b-11e3-949a-0800200c9a66"));
BluetoothSocket bs = bss.accept();
byte[] buf = new byte[1024];
InputStream is = bs.getInputStream();
int read = is.read(buf);
is.close();
bs.close();
On the phone:
Code:
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> devices = btAdapter.getBondedDevices();
BluetoothDevice device = devices.iterator().next();
BluetoothSocket bs = device.createRfcommSocketToServiceRecord(UUID.fromString("c3f10dc0-677b-11e3-949a-0800200c9a66"));
bs.connect();
bs.getOutputStream().write("Hello!".getBytes("UTF-8"));
bs.getOutputStream().flush();
bs.getOutputStream().close();
bs.close();
This is just an example, but it works. Does anyone know if the the Bluetooth GATT APIs might be a better fit, and whether they might be able to control the lifecycle of the app on the watch?
Click to expand...
Click to collapse
Did you succeed in getting the Note 3 and Gear talking with this code, Is data transfer also possible? When I tried deploying such a client application on the watch it immediately crashed and so I thought it could be that the Bluetooth session cannot be started because of an existing Bluetooth connection via the Gear Manager.
After reading some content on different sites regarding this(I could not post those links as I got an error while posting), I thought real time data transfer via Bluetooth will not be possible but if you say it works then may be I should check my code, But is there any other way to transfer data by using the existing Bluetooth pairing via the Gear Manager App?

Related

Auto answer v1.5 killed after gb 2.3.4

1st gingerbread update killed app
2nd update if I update will kill app
I emailed the developer
[email protected]
Sorry I can't give you a better answer, but I've been extremely busy over the past few weeks, and I just haven't had the time. The app is open source, so if you are a developer (or know a developer), feel free to try a fix. Matt
I sent him this a couple of weeks ago
Android Bridge â–¼ T U E S D A Y , M A Y 1 7 , 2 0 1 1how to answer an incoming call in android 2.3 Today, I was researching on a how to answer incoming call in android 2.3 automatically. My first thought was using "ITelephony.aidl" and call the answerRingingCall(). When i looked into more details answerRingingCall() function all requires MODIFY_PHONE_STATE permission which is marked as a as "signatureOrSystem" which is mentioned here http://android.git.kernel.org/?p=platform/ frameworks/ base.git;a=commit;h=f4ece2086f3b7060edc4b93 a12f04c9af648867a and here http://code.google.com/p/android/issues/ detail?id=15031 bummer. Then thought of a another work-around and bluetooth headset popuped to my mind. In this all I had to do was to call start new intent with ACTION_UP. It worked! here is the soulution BroadcastReceiver PhoneState = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (!intent.getAction().equals("android.intent.action .PHONE_STATE")) return; String state = intent.getStringExtra(TelephonyManager.EXTRA_ STATE); if (state.equals(TelephonyManager.EXTRA_STATE_ RINGING)) { String number = intent.getStringExtra(TelephonyManager.EXTRA_ INCOMING_NUMBER); Intent answer = new Intent(Intent.ACTION_MEDIA_BUTTON); answer.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK)); sendOrderedBroadcast(answer, null); } return; }}; // Update on 2011-09-27 In Android 2.3.3 HTC Sensation this piece of code does not work. Reason is in 2.3.3 I found a HeadsetObserver listening for actual bluetooth plug-in event. So you need to send a Intent pretending there is a headset connected already. To fix this problem you need to send the ACTION_HEADSET_PLUG Intent before calling the above code. Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON); buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK)); context.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED"); // froyo and beyond trigger on buttonUp instead of buttonDown Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON); buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK)); context.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED"); Intent headSetUnPluggedintent = new Intent(Intent.ACTION_HEADSET_PLUG); headSetUnPluggedintent.addFlags(Intent.FLAG_ RECEIVER_REGISTERED_ONLY); headSetUnPluggedintent.putExtra("state", 0); headSetUnPluggedintent.putExtra("name", "Headset"); // TODO: Should we require a permission? sendOrderedBroadcast(headSetUnPluggedinten t, null);
http://androidbridge.blogspot.com/2011/05/how-to-answer-incoming-call-in-android.html?m=1
I'm not a developer so how would you insert this fix
Bottomline can someone please take a crack at helping this guy out
Sent from my ADR6400L using xda premium

[Q] Modifying notification

Hi folks,
even though there are many nice 3rd party twitter clients available they are all missing an important feature: push notifications using GCM. The original Twitter app offers GCM based notifications but the app itself is more or less crap.
Therefore I thought about utilizing the original Twitter app for receiving GCM messages which create the Android notifications and then modify these notifications so that another (3rd party) app is started when clicking on them. I already managed to hook into the NotificationManager:
Code:
XposedHelpers.findAndHookMethod(android.app.NotificationManager.class, "notify", String.class, int.class, Notification.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("NotificationManager.beforeHookedMethod(): param=" + param);
for (Object o : param.args) {
if (o instanceof Notification) {
Notification n = (Notification) o;
XposedBridge.log("NotificationManager.beforeHookedMethod(): notification=" + n);
}
}
}
}
);
At this stage, where simple things as changing Notification.tickeText work, I tried the following:
1) Creating a new PendingIntent and assigning it to Notification.contentIntent:
Code:
Intent LaunchIntent = context.getPackageManager().getLaunchIntentForPackage("it.mvilla.android.fenix");
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, LaunchIntent, 0);
n.contentIntent = contentIntent;
This fails due to the fact that I did not succeed in getting my hand on a Context instance. Does anyone have got an idea on how to get a Context instance or can provide another possibility for creating the PendingIntend without a Context?
2) As the previous did not work due to a missing Context I tried to change the LauchIntent of the existing Notification. But I was not able to find the correct place - I did not even find the original LaunchIntent when studying the sources or even by dumping the notification by reflection.
I also started investigating on how to hook into the Twitter app itself. But as the source code is (of course) not public and additionally is obfuscated this seems to be even more complicated. In addition hooking into the NotificationManager is more generic and would allow - when adding configuration - the redirection also for other sources and targets.
As you see, I am somehow stucked. But I'm not hopeless respectively cannot imaging that it should not be possible. So now it's up to you to feed me with the correct ideas
So far and thanks in advance,
yaan04
yaan04 said:
1) Creating a new PendingIntent and assigning it to Notification.contentIntent:
This fails due to the fact that I did not succeed in getting my hand on a Context instance. Does anyone have got an idea on how to get a Context instance or can provide another possibility for creating the PendingIntend without a Context?
Click to expand...
Click to collapse
AndroidAppHelper.currentApplication() should do the trick. Otherwise see this, though if AndroidAppHelper fails most of these probably will, too.
yaan04 said:
2) As the previous did not work due to a missing Context I tried to change the LauchIntent of the existing Notification. But I was not able to find the correct place - I did not even find the original LaunchIntent when studying the sources or even by dumping the notification by reflection.
Click to expand...
Click to collapse
LaunchIntent?
yaan04 said:
I also started investigating on how to hook into the Twitter app itself. But as the source code is (of course) not public and additionally is obfuscated this seems to be even more complicated. In addition hooking into the NotificationManager is more generic and would allow - when adding configuration - the redirection also for other sources and targets.
Click to expand...
Click to collapse
Android API calls won't be obfuscated. Try searching for "NotificationManager" for example and see where it's used.
Yeah, AndroidAppHelper.currentApplication() provides a usable Context instance \o/
Thanks, GermainZ. Now I can go on...

[Q] problem with class static value

have some problems with static values used as flags.
for example I need to hook 2 methods in different FRAMEWORK classes during initZygote. (no problem with system apps during handleLoadPackage)
I hook method in first class, set static value and waiting when another method of another class will be triggered.
once another method is invoked, flag always has it's initial state.
it looks like each hook method processed in different class instances.
i tried volatile type, tried to synchronize - nothing help.
unreliable remedy:
1. register broadcast receiver inside hook method.
2. send action to own service
3. send broadcast from own service.
4. catch broadcast with receiver.
BUT it is not battery cost efficient solution in my case. And mostly I receive broadcast message when hooking method already processed and returned value. Otherwise I need to wait when service will process request and send broadcast. But it is not usable.
is there any solution?
Code:
public class XMain implements IXposedHookInitPackageResources, IXposedHookZygoteInit, IXposedHookLoadPackage
{
private static boolean isNeedToRun = false;
public void initZygote(StartupParam startupParam) throws Throwable
{
findAndHookMethod("com.class1", null, "method1", int.class, new XC_MethodHook()
{
@Override
protected void beforeHookedMethod(final MethodHookParam param) throws Throwable
{
isNeedToRun = true;
}
});
findAndHookMethod("com.class2", null, "method2", int.class, new XC_MethodHook()
{
@Override
protected void beforeHookedMethod(final MethodHookParam param) throws Throwable
{
if (isNeedToRun) param.setResult(null); // always FALSE even if previous hook set as TRUE
}
});
}
}
Why do you think that using a broadcast receiver is not battery efficient?
GermainZ said:
Why do you think that using a broadcast receiver is not battery efficient?
Click to expand...
Click to collapse
I do not want to invoke service and send broadcast very often (several thousands times during normal battery one cycle charge)
I just want use easiest way by storing flag inside class and worried that users will find the module in the list of gluttonous applications.
Falseclock said:
Code:
if (isNeedToRun) param.setResult(null); // always FALSE even if previous hook set as TRUE
Click to expand...
Click to collapse
You're probably not considering the fact that different processes will each have its own "isNeededToRun" variable.
Whenever new processes (system_process, apps, etc.) are forked from zygote, each of them will have its own independent state which includes this static variable. From then on they will be completely separate things even if it's a variable with the same name, don't get confused by that.
Try adding a Log.i(...) call to write something in both methods, and then check the logcat for the pid in which the messages are logged. I bet you'll see that different pids are writing and reading, and you can't expect them to be doing it in the same global variable.
Tungstwenty said:
You're probably not considering the fact that different processes will each have its own "isNeededToRun" variable.
Whenever new processes (system_process, apps, etc.) are forked from zygote, each of them will have its own independent state which includes this static variable. From then on they will be completely separate things even if it's a variable with the same name, don't get confused by that.
Try adding a Log.i(...) call to write something in both methods, and then check the logcat for the pid in which the messages are logged. I bet you'll see that different pids are writing and reading, and you can't expect them to be doing it in the same global variable.
Click to expand...
Click to collapse
Yes, I realized this. But under handleLoadPackage everything work perfect.
Any suggestion to solve situation?
Falseclock said:
Yes, I realized this. But under handleLoadPackage everything work perfect.
Any suggestion to solve situation?
Click to expand...
Click to collapse
handleLoadPackage is executed after the fork, in the new process. Not sure what exactly you hooked when you tried that way, but probably both callbacks were executed in the same app/process.
You have the typical problem that requires some kind of inter-process communication (IPC). Most common examples for IPC in Android are broadcasts and services. Files might also be an option (especially with observers), but probably not when you need to change the value very frequently.

Can Xposed framework intercept all intetnt from/to an application?

Hi Everybody,
I want to write an intent sniffer application that can intercept intents (Implicit and Explicit Intents ) and analysis it's data
Now i want to ask can Xposed framework intercept intents from or to an application? and also i want to know can i read the data that is transferred through intents with Xposed framework?
Thanks
Hello
Like little snitch for mac ?
Regards
karmoussa said:
Hello
Like little snitch for mac ?
Regards
Click to expand...
Click to collapse
Sure. hook sendBroadcast(INTENT).
pyler said:
Sure. hook sendBroadcast(INTENT).
Click to expand...
Click to collapse
This is for broadcast intent! i want to hook explicit intent too! is it possible?
then get first param of sendBroadcast and then.
Intent i = (Intent) param.args[0];
String specificAction = i.getAction();
if ("bla bla".equals(specificAction)) {
your code...
}
msalehi1991 said:
Hi Everybody,
I want to write an intent sniffer application that can intercept intents (Implicit and Explicit Intents ) and analysis it's data
Now i want to ask can Xposed framework intercept intents from or to an application? and also i want to know can i read the data that is transferred through intents with Xposed framework?
Thanks
Click to expand...
Click to collapse
did you ever manage to make this app? have been looking for something like this, the closest i have come to is autoshare
1.5 years later..
Any update?
I am interested, too
Me too!
you may have a look to this module - Intent interceptor by the author of Sorcery Icon pack
https://github.com/sorcererXW/IntentInterceptor

Plex / Python / Chromecast

So, I'm trying to cast plex content to my chromecast using a python script on the server. Using PlexAPI I can connect to the server and navigate my content just fine. Using pychromecast, I can connect python to my chromecast. Using the Plex Media Controller, I can even use .play() to bring the basic plex background up on the chromecast. What I -can't- seem to do is tell the plex on the chromecast WHAT to play from python... or to even actually start playing any media that isn't already playing there; it just sits there. Anyone have any insights?
Alright, well here's where I am: As near as I can tell, there's no way to tell the Plex Chromecast Receiver to play a title/file/anything, even once it's up. I can, of course, use PlexAPI to do things like poll for the oldest unwatched episode of something. Therefore, I'm currently tinkering with getting the episode file with PlexAPI and then sending to the chromecast with stream2chromecast. This lets me transcode, at least, to make the right video play (with audio even). Unfortunately, when transcoding, the "pause"/"continue" functions of stream2chromecast don't work. Not sure what's up with that, but it's on their end.
EvenGhost was being a pita and kept crashing on me for some reason, so I gave up on it and wrote a Tornado server into the python script. Not ideal, nor do I really want a webserver up and running at home, but it is what it is for the moment.
So the current flow goes "Google Home -> IFTTT -> Maker -> Tornado Server (python code inside) -> Chromecast.
Using this, I can now say "Okay Google, Chromecast the latest episode of MayGyver"... and in a few seconds the oldest unwatched episode from my Plex server will start to play on my TV. (I can also say, "Okay Google, chromecast stop" and it will stop.)
Sadly, because I'm sidestepping Plex for the actual playing, it doesn't show up under "now playing". Nor does it mark the episode as watched if you finish it.
Alright, well. Today's progress update. Rather than continue the external tracking path, I've dropped back to attempting to make it play to the Plex app on the Chromecast. I originally thought this impossible, but I did manage to make some progress.
I still cannot make a video play via this method, but I -am- able to bring up the "Details" page of any given movie or episode or whatever onto the Chromecast. I accomplished this by digging into the pychromecast Controllers and its notes about custom namespaces. I did the whole "net-internals/#capture" thing the github mentions to explore the namespace. Digging through, that gave me what commands are being sent to the Chromecast when I cast from my browser. I translated the two commands there (SHOWDETAILS and LOAD) into the Plex Controller. I was somewhat surprised when ShowDetails actually worked.... but then shatteringly disappointed when LOAD did not.
I feel like I'm so close on this now, but still missing a piece of the puzzle.
Nice work. You've converted me - I was just using the standard media controller to access the respective Plex url. The tips above helped guide me in the right direction. So thanks - and keep posting your progress. I'll see what I can figure out as well. I assume you already sorted out the transient access tokens that look to be required?
Ok I got the play working via Python.
I use this API - github.com/mjs7231/python-plexapi
The key things I had to do:
1. Grab a transient token for the request
Code:
server.query('/security/token?type=delegation&scope=all').attrib('token')
2. And I created a playQueue id for the request
Code:
server.createPlayQueue(video).playQueueID
3. The LOAD command must be run in the namespace:
Code:
urn:x-cast:com.google.cast.media
not
Code:
urn:x-cast:plex
I just switched namespaces in my PlexController (as I built a custom LOAD message) to prove it would work
mcneishh said:
Ok I got the play working via Python.
I use this API - github.com/mjs7231/python-plexapi
The key things I had to do:
1. Grab a transient token for the request
Code:
server.query('/security/token?type=delegation&scope=all').attrib('token')
2. And I created a playQueue id for the request
Code:
server.createPlayQueue(video).playQueueID
3. The LOAD command must be run in the namespace:
Code:
urn:x-cast:com.google.cast.media
not
Code:
urn:x-cast:plex
I just switched namespaces in my PlexController (as I built a custom LOAD message) to prove it would work
Click to expand...
Click to collapse
Can you provide some more details on how you did the LOAD command part? That's the part I'm having the most trouble with.
Ah, I had NOT indeed worked out the transient token bit. I felt like maybe I needed to fetch one, but hadn't quite worked out how. Are you sending a SETSTREAM and a LOAD or just a LOAD to actually get things playing? If a SETSTREAM, is that going to the plex namespace or the media namespace?
linc-thra said:
Ah, I had NOT indeed worked out the transient token bit. I felt like maybe I needed to fetch one, but hadn't quite worked out how. Are you sending a SETSTREAM and a LOAD or just a LOAD to actually get things playing? If a SETSTREAM, is that going to the plex namespace or the media namespace?
Click to expand...
Click to collapse
How did you go about sending the commands to the chromecast? I've spent most of the day trying to figure out pychromecast, but I'm not having much luck. I just cannot figure out how to expand the namespace to add a new plex module. I feel like if I could get anything to send it would be a huge leap in the right direction...
MechaTech84 said:
How did you go about sending the commands to the chromecast? I've spent most of the day trying to figure out pychromecast, but I'm not having much luck. I just cannot figure out how to expand the namespace to add a new plex module. I feel like if I could get anything to send it would be a huge leap in the right direction...
Click to expand...
Click to collapse
I'm headed out to dinner and won't be back for a while, BUT, it requires editing the plex.py file in the controller folder of pychromecast. I JUST got it to start playing and the like myself thanks to mcneishh's hints. I'm attaching a basic functional PlexApiController:
http://pastebin.com/qeLYZpW4
I'll try to improve it later.
An example of how to use this:
Code:
import pychromecast.controllers.plexapi as px
import pychromecast
from plexapi.myplex import MyPlexAccount
account = MyPlexAccount.signin('<USERNAME>', '<PASSWORD')
plex = account.resource('<SERVER_NAME>').connect()
pxr = px.PlexController()
cast = pychromecast.Chromecast("<CHROMECASTIP")
cast.register_handler(pxr)
pxr.namespace = 'urn:x-cast:com.google.cast.sse'
white = plex.library.section("TV Shows").get("White Collar")
epi = white.seasons()[0].episodes()[0]
pxr.play_media(epi,plex)
My bad, that first code line should be
Code:
import pychromecast.controllers.plex as px
if you edit the existing plex.py file, I think. I had made my own at plexapi.py so as not to lose the original.
Is there a reason why you are trying to do this and not use the Plex App? Is it just a coding experiment or is there some reason why you want to bypass the Plex app?
Asphyx said:
Is there a reason why you are trying to do this and not use the Plex App? Is it just a coding experiment or is there some reason why you want to bypass the Plex app?
Click to expand...
Click to collapse
There is a reason. Now that this is working, I have tied it to my Google home without waiting a year for Plex to get their support sorted. I can now say, "Okay Google, watch Westworld season 1 episode 1" and it will start playing the appropriate episode on my Chromecast from Plex.
Ahhhh...Good reason!
I agree Plex Devs are pretty slow at keeping up with the world around it.
MechaTech84 said:
Can you provide some more details on how you did the LOAD command part? That's the part I'm having the most trouble with.
Click to expand...
Click to collapse
I grabbed the relevant byte code cleaning it up I ended up with:
Code:
{"type":"LOAD","requestId":481982064,"sessionId":"81c3b38d-b2f4-4c33-929a-5365af184d70","media":
{"contentId":"/library/metadata/105","streamType":"BUFFERED","contentType":"video","customData":
{"offset":0,"directPlay":true,"directStream":true,"subtitleSize":100,"audioBoost":100,"server":
{
"machineIdentifier":"9a35df949e05bc86d0aa792c56e3db68c0c36250","transcoderVideo":true,"transcoderVideoRemuxOnly":false,"transcoderAudio":true,"version":"1.1.4.2757","myPlexSubscription":true,"isVerifiedHostname":false,"protocol":"http","address":"10.1.3.200","port":"32400","accessToken":"transient-74cce00a-4048-4fcc-a571-38f2fd9a2acf"
},
"user":{"username":"XXXXXXXX"},
"containerKey":"/playQueues/1635?own=1&window=200"
}
},
"autoplay":true,"currentTime":0
}
I haven't finished the method but here's what I have all the variables (except the last 2) are currently hardcoded.
Code:
def play_item(self, key, content_data, play_data, server_data, user_data, access_token, play_queue_id):
key = "/library/metadata/105"
requestId = self._socket_client._request_id
sessionId = self._socket_client.session_id
play_data = {"offset":0,"directPlay":True,"directStream":True,"subtitleSize":100,"audioBoost":100}
server_data = {"machineIdentifier":"9a35df949e05bc86d0aa792c56e3db68c0c36250","transcoderVideo":True,"transcoderVideoRemuxOnly":False,"transcoderAudio":True,"version":"1.1.4.2757","myPlexSubscription":True,"isVerifiedHostname":False,"protocol":"http","address":"10.1.3.200","port":"32400"}
user_data = {"username":"XXXXXX"}
content_data = {"streamType":"BUFFERED","contentType":"video"}
msg = {MESSAGE_TYPE:TYPE_LOAD,'requestId':requestId,'sessionId':sessionId}
msg['media'] = {'contentId':key}
msg['media'].update(content_data)
msg['media']['customData'] = play_data.copy()
msg['media']['customData']['server'] = server_data.copy()
msg['media']['customData']['server']['accessToken'] = access_token
msg['media']['customData']['user'] = user_data.copy()
msg['media']['customData']['containerKey'] = '/playQueues/%s?own=1&window=200' % play_queue_id
msg.update({'autoplay':True, 'currentTime':0})
self.namespace = 'urn:x-cast:com.google.cast.media'
self.send_message(msg)
self.namesapce = 'urn:x-cast:plex'
Here's my full controller code.
I'm not 100% sure that I have the right session and request Ids, but assume they are the most likely to use.
Hopefully this helps.
Code:
MESSAGE_TYPE = 'type'
TYPE_SHOWDETAILS = 'SHOWDETAILS'
TYPE_LOAD = 'LOAD'
class MyPlexController(PlexController):
def __init__(self):
super().__init__()
def receive_message(self, message, data):
logging.info('PlexController: I received this message: {}'.format(data))
return True # indicate you handled this message
def send_message(self, data, inc_session_id=False, callback_function=None):
logging.info('PlexController: I send this message: {}'.format(data))
super().send_message(data, inc_session_id, callback_function)
def show_details(self, key, content_data, server_data, user_data, access_token):
key = "/library/metadata/105"
server_data = {"machineIdentifier":"9a35df949e05bc86d0aa792c56e3db68c0c36250","transcoderVideo":True,"transcoderVideoRemuxOnly":False,"transcoderAudio":True,"version":"1.1.4.2757","myPlexSubscription":True,"isVerifiedHostname":False,"protocol":"http","address":"10.1.3.200","port":"32400"}
user_data = {"username":"XXXXXX"}
content_data = {"streamType":"BUFFERED","contentType":"video"}
msg = {MESSAGE_TYPE:TYPE_SHOWDETAILS}
msg['media'] = {'contentId':key}
msg['media'].update(content_data)
msg['media']['customData'] = {}
msg['media']['customData']['server'] = server_data.copy()
msg['media']['customData']['server']['accessToken'] = access_token
msg['media']['customData']['user'] = user_data.copy()
self.send_message(msg)
# {"type":"SHOWDETAILS","media":
# {"contentId":"/library/metadata/105","streamType":"BUFFERED","contentType":"video","customData":
# {"server":
# {"machineIdentifier":"9a35df949e05bc86d0aa792c56e3db68c0c36250","transcoderVideo":true,"transcoderVideoRemuxOnly":false,"transcoderAudio":true,"version":"1.1.4.2757","myPlexSubscription":true,"isVerifiedHostname":false,"protocol":"http","address":"10.1.3.200","port":"32400","accessToken":"transient-73832b14-e2bf-4943-b97d-468b9ae85a34"},
# "user": {"username":"XXXXXX"}
# }
# }
# }
def play_item(self, key, content_data, play_data, server_data, user_data, access_token, play_queue_id):
key = "/library/metadata/105"
requestId = self._socket_client._request_id
sessionId = self._socket_client.session_id
play_data = {"offset":0,"directPlay":True,"directStream":True,"subtitleSize":100,"audioBoost":100}
server_data = {"machineIdentifier":"9a35df949e05bc86d0aa792c56e3db68c0c36250","transcoderVideo":True,"transcoderVideoRemuxOnly":False,"transcoderAudio":True,"version":"1.1.4.2757","myPlexSubscription":True,"isVerifiedHostname":False,"protocol":"http","address":"10.1.3.200","port":"32400"}
user_data = {"username":"XXXXXX"}
content_data = {"streamType":"BUFFERED","contentType":"video"}
msg = {MESSAGE_TYPE:TYPE_LOAD,'requestId':requestId,'sessionId':sessionId}
msg['media'] = {'contentId':key}
msg['media'].update(content_data)
msg['media']['customData'] = play_data.copy()
msg['media']['customData']['server'] = server_data.copy()
msg['media']['customData']['server']['accessToken'] = access_token
msg['media']['customData']['user'] = user_data.copy()
msg['media']['customData']['containerKey'] = '/playQueues/%s?own=1&window=200' % play_queue_id
msg.update({'autoplay':True, 'currentTime':0})
self.namespace = 'urn:x-cast:com.google.cast.media'
self.send_message(msg)
self.namesapce = 'urn:x-cast:plex'
# {"type":"LOAD","requestId":481982064,"sessionId":"81c3b38d-b2f4-4c33-929a-5365af184d70","media":
# {"contentId":"/library/metadata/105","streamType":"BUFFERED","contentType":"video","customData":
# {"offset":0,"directPlay":true,"directStream":true,"subtitleSize":100,"audioBoost":100,"server":
# {
# "machineIdentifier":"9a35df949e05bc86d0aa792c56e3db68c0c36250","transcoderVideo":true,"transcoderVideoRemuxOnly":false,"transcoderAudio":true,"version":"1.1.4.2757","myPlexSubscription":true,"isVerifiedHostname":false,"protocol":"http","address":"10.1.3.200","port":"32400","accessToken":"transient-74cce00a-4048-4fcc-a571-38f2fd9a2acf"
# },
# "user":{"username":"XXXXXX"},
# "containerKey":"/playQueues/1635?own=1&window=200"
# }
# },
# "autoplay":true,"currentTime":0
# }
linc-thra said:
Ah, I had NOT indeed worked out the transient token bit. I felt like maybe I needed to fetch one, but hadn't quite worked out how. Are you sending a SETSTREAM and a LOAD or just a LOAD to actually get things playing? If a SETSTREAM, is that going to the plex namespace or the media namespace?
Click to expand...
Click to collapse
I just used a LOAD.
For SETSTREAM I'm using the following in my controller (using the Plex namespace).
Code:
def _send_command(self, chromecast, command):
chromecast.register_handler(self)
mc = chromecast.media_controller
if mc.status is None or mc.status.media_session_id is None:
raise PlexControllerException('No media_session_id was found unable to send command {}'.format(command))
command['mediaSessionId'] = mc.status.media_session_id
self.send_message(command, inc_session_id=True)
def set_quality(self, chromecast, bitrate): self._send_command(chromecast, {"type":"SETQUALITY","bitrate":bitrate})
def set_subtitles(self, chromecast, subtitle_id): self._send_command(chromecast, {"type":"SETSTREAM","stream":{"type":"subtitles","id":subtitle_id}})
def disable_subtitles(self, chromecast): self._send_command(chromecast, {"type":"SETSTREAM","stream":{"type":"subtitles","id":0}})
def set_audio(self, chromecast, audio_id): self._send_command(chromecast, {"type":"SETSTREAM","stream":{"type":"audio","id":audio_id}})
def set_video(self, chromecast, video_id): self._send_command(chromecast, {"type":"SETSTREAM","stream":{"type":"video","id":video_id}})
You can get the resprective Ids from via the plexapi
Code:
videostreams = [s.id for s in video.videoStreams]
audiostreams = [s.id for s in video.audioStreams]
subtitlestreams = [s.id for s in video.subtitleStreams]
linc-thra said:
I'm headed out to dinner and won't be back for a while, BUT, it requires editing the plex.py file in the controller folder of pychromecast. I JUST got it to start playing and the like myself thanks to mcneishh's hints. I'm attaching a basic functional PlexApiController:
http://pastebin.com/qeLYZpW4
I'll try to improve it later.
An example of how to use this:
Code:
import pychromecast.controllers.plexapi as px
import pychromecast
from plexapi.myplex import MyPlexAccount
account = MyPlexAccount.signin('<USERNAME>', '<PASSWORD')
plex = account.resource('<SERVER_NAME>').connect()
pxr = px.PlexController()
cast = pychromecast.Chromecast("<CHROMECASTIP")
cast.register_handler(pxr)
pxr.namespace = 'urn:x-cast:com.google.cast.sse'
white = plex.library.section("TV Shows").get("White Collar")
epi = white.seasons()[0].episodes()[0]
pxr.play_media(epi,plex)
Click to expand...
Click to collapse
Hi, thanks a lot for your code! I managed to connect to the Chromecast using pychromecast and to plexapi, but unfortunately every time I try to play something I get "unable to cast this media is currently unavailable" on my Chromecast. Starting it manually works.
Do you have any ideas?
bluebird11 said:
Hi, thanks a lot for your code! I managed to connect to the Chromecast using pychromecast and to plexapi, but unfortunately every time I try to play something I get "unable to cast this media is currently unavailable" on my Chromecast. Starting it manually works.
Do you have any ideas?
Click to expand...
Click to collapse
Hmmm... not really, other than possibly you're calling or referencing the episode wrong from plexapi?
linc-thra said:
Hmmm... not really, other than possibly you're calling or referencing the episode wrong from plexapi?
Click to expand...
Click to collapse
Hmm, I'm getting it with the following code:
Code:
movies = plex.library.section('Movies')
for video in movies.search(unwatched=True):
print(video.title)
epi = plex.library.section('Movies').get(video.title)
break
Another question: Do I need to connect a client first? I.e. do I have to connect to Plex with a browser or the app before I can do anything?
bluebird11 said:
Hmm, I'm getting it with the following code:
Code:
movies = plex.library.section('Movies')
for video in movies.search(unwatched=True):
print(video.title)
epi = plex.library.section('Movies').get(video.title)
break
Another question: Do I need to connect a client first? I.e. do I have to connect to Plex with a browser or the app before I can do anything?
Click to expand...
Click to collapse
To answer your second question first: No, the controller should connect itself just find with no browser involved. The first question is more complicated... mainly because your code works for me.... so long as you are trying to get the first unwatched movie in the movie section. I didn't have any marked as "unwatched" to start with and it fell over, but once I marked one as unwatched, that code ran for me fine.
linc-thra said:
To answer your second question first: No, the controller should connect itself just find with no browser involved. The first question is more complicated... mainly because your code works for me.... so long as you are trying to get the first unwatched movie in the movie section. I didn't have any marked as "unwatched" to start with and it fell over, but once I marked one as unwatched, that code ran for me fine.
Click to expand...
Click to collapse
Thanks for the reply, it works now. Connecting directly to the plex server in the local network doesn't seem to work. What worked is connecting over plex.tv as shown here... I thought that it doesn't matter.
Anyway, what I was hoping for is that after connecting it would show up as a device / client in the Plex app so I could control it from there (and from amazon echo), but it doesn't show up Do you think that would be possible? If I connect manually from a browser it shows up as "Plex Web (Chrome)".

Categories

Resources