Chromecast cannot receive custom messages (CAF Receiver) - chromecast

I am working with react native wrapper for Google Cast SDK and I couldn't send a message from the sender to receiver. I am able to cast media or pause and resume it. The problem is only about custom messages. My custom message listener is never called in the receiver side. Should the message have a specific structure that I am missing? Thanks in advance.
Sender:
GoogleCast.initChannel('urn:x-cast:testChannel');
GoogleCast.sendMessage('urn:x-cast:testChannel', 'testMessage');
Receiver:
const context = cast.framework.CastReceiverContext.getInstance();
const CUSTOM_CHANNEL = 'urn:x-cast:testChannel';
context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
// handle customEvent.
console.log('event received');
});
Edit: I am able to send message from receiver to sender:
Receiver:
context.sendCustomMessage(CUSTOM_CHANNEL , undefined, 'myMessage');
Sender:
GoogleCast.EventEmitter.addListener(GoogleCast.CHANNEL_MESSAGE_RECEIVED, ({undefined, message}) => {
console.log(message);
});

I think this is problem bellow
https://issuetracker.google.com/issues/117136854#comment7
So try this...
Send
let message = {msg: 'testMessage'};
message = JSON.stringify(message);
GoogleCast.sendMessage('urn:x-cast:testChannel', message);
and Receiver
const CHANNEL = 'urn:x-cast:testChannel';
const ctx = cast.framework.CastReceiverContext.getInstance();
const options = new cast.framework.CastReceiverOptions();
const objToSender =
{
type: 'status',
message: 'Playing'
};
options.customNamespaces = Object.assign({});
options.customNamespaces[CHANNEL] = cast.framework.system.MessageType.JSON;
//receiving sender message
ctx.addCustomMessageListener(CHANNEL, customEvent => document.getElementById("main").innerHTML = customEvent.data.msg);
//message to sender app
ctx.sendCustomMessage(CHANNEL, objToSender);
ctx.start(options);

Related

Proto2 encode/decode issues after adding new message

I'm fairly new to protocol buffers but have been trying to learn them as a means of sending data via MQTT. So far, I've been fine with creating proto messages and compiling them for python runtime, until I started to notice incompatibility between versions of my protobufs.
When I add a message type (no changes to existing messages/fields) to my server-side proto definitions without updating my client side proto definitions, decoding messages sent to the server give me non-deterministic results.
Here is an example of what I'm talking about:
Client proto:
message Wrapper {
optional uint32 id = 1;
optional string name = 2;
oneof payload {
Event event = 3;
Command command = 4;
}
}
message Event {
uint32 event_id = 1;
oneof event_payload {
LoginEvent login_event = 2;
LogoffEvent logoff_event = 3;
}
}
Server Proto:
message Wrapper {
optional uint32 id = 1;
optional string name = 2;
oneof payload {
Event event = 3;
Command command = 4;
}
message Event {
uint32 event_id = 1;
oneof event_payload {
LoginEvent login_event = 2;
LogoffEvent logoff_event = 3;
NewUserEvent new_user_event = 4;
}
}
I will encode and send a message from the client:
message Wrapper {
id = 12345;
name = John;
event = {
login_event = ...
}
}
And will decode the message on the server and get:
message Wrapper {
id = 12345;
name = John;
event = {
logoff_event = ...
}
}
NOTE: The decoded message type isn't deterministic and changes between messages
Can someone explain why adding an event type seems to screw up decode? Or any best-practices I should obey to improve version compatibility? Thanks in advance!
This may be a side-effect of the Python implementation rather than a bug.
You don't include the code you're using to (un)marshal the protobufs.
In your example, does logoff_event contain a LogoffEvent message type?
You say non-deterministic? Do you see different event_payload messages types on the server for the same message sent by the client?
What is returned by:
msg = Wrapper() # Your decoded message
assert msg.event.WhichOneof("event_payload")
# or
assert msg.event.HasField("login_event")
See Python Generated Code: OneOf
Update 210927
I'm unable to repro the behavior you observe; it works as expected for me.
Client:
import client_pb2
msg = client_pb2.Wrapper()
msg.id=0
msg.name="Test"
msg.event.event_id=1
msg.event.login_event.y="Hello Freddie"
print(msg)
f=open("message","wb")
f.write(msg.SerializeToString())
f.close()
Yields:
id: 0
name: "Test"
event {
event_id: 1
login_event {
y: "Hello Freddie"
}
}
Server:
import server_pb2
msg = server_pb2.Wrapper()
f=open("message","rb")
msg.ParseFromString(f.read())
f.close
assert msg.event.WhichOneof("event_payload")
assert msg.event.HasField("login_event")
print(msg)
Yields:
id: 0
name: "Test"
event {
event_id: 1
login_event {
y: "Hello Freddie"
}
}

Rust Actix Actor send message to actor

How to send a message to another actor?
pub struct MyWs {
}
impl Actor for MyWs {
type Context = ws::WebsocketContext<Self>;
}
impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for MyWs {
fn handle(&mut self, msg: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
match msg {
Ok(ws::Message::Ping(msg)) => ctx.pong(&msg),
Ok(ws::Message::Text(message)) => {
//considering that here he sent the message to self
ctx.text(message);
//how to do something like this
//find the actor by index (or uuid) and send text
//actors[0].text(message);
//
},
Ok(ws::Message::Binary(bin)) => ctx.binary(bin),
Ok(ws::Message::Close(reason)) => ctx.close(reason),
_ => (),
}
}
}
#[get("/ws")]
pub async fn websocket(req: HttpRequest, stream: web::Payload,) -> actix_web::Result<HttpResponse> {
let resp = ws::start(
MyWs {},
&req,
stream,
);
return resp;
}
Could I make a hashMap of actors?
pub struct MyWs { sessions: HashMap<Uuid, Socket> }
and later
self.sessions.text(message)
I'm new to rust and I don't see a way to save the socket (the context or actor) to find it and send it messages.
You might want to check the official example of a chat room app using actix web.
https://github.com/actix/examples/blob/743af0ff1a9be6fb1cc13e6583108463c89ded4d/websockets/chat/src/main.rs
There are three key points:
create another server actor and get the address of it.
let server = server::ChatServer::new(app_state.clone()).start();
set the server actor's address as application data of HttpServer.
HttpServer::new(move || {
App::new()
.data(app_state.clone())
// copy server actor's address into app
.data(server.clone())
.service(web::resource("/").route(web::get().to(|| {
HttpResponse::Found()
.header("LOCATION", "/static/websocket.html")
.finish()
})))
.route("/count/", web::get().to(get_count))
// websocket
.service(web::resource("/ws/").to(chat_route))
// static resources
.service(fs::Files::new("/static/", "static/"))
})
.bind("127.0.0.1:8080")?
.run()
.await
store the address while starting websocket actor in function chat_route. And then you could use the address to send messages whenever you want
/// Entry point for our websocket route
async fn chat_route(
req: HttpRequest,
stream: web::Payload,
srv: web::Data<Addr<server::ChatServer>>,
) -> Result<HttpResponse, Error> {
ws::start(
WsChatSession {
id: 0,
hb: Instant::now(),
room: "Main".to_owned(),
name: None,
addr: srv.get_ref().clone(),
},
&req,
stream,
)
}

Marshalling objective c to nativescript js

Hello I'm trying to use the following cocoa pod for tcp functionality in ios:
https://cocoapods.org/pods/CocoaAsyncSocket
Im facing problems writing the marshalled js using this library
Here is an example (Objective C):
// The most common way to initialize an instance is simply like this:
socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *err = nil;
if (![socket connectToHost:#"deusty.com" onPort:80 error:&err]) // Asynchronous!
{
// If there was an error, it's likely something like "already connected" or "no delegate set"
NSLog(#"I goofed: %#", err);
}
- (void)socket:(GCDAsyncSocket *)sender didConnectToHost:(NSString *)host port:(UInt16)port
{
NSLog(#"Cool, I'm connected! That was easy.");
}
JSCODE:
// mainQueue var is to get dispatch_get_main_queue
var mainQueue = (function() {
var runloop = CFRunLoopGetMain();
return function(func) {
CFRunLoopPerformBlock(runloop, kCFRunLoopDefaultMode, func);
CFRunLoopWakeUp(runloop);
}
}());
var tcpClient = GCDAsyncSocket.alloc().initWithDelegateDelegateQueue(testerClass,mainQueue);
var e = new interop.Reference();
if (!tcpClient.connectToHostOnPortError('192.168.88.110',3333,e)) {
console.log('Could not connect to mipbook');
console.log(e.value);
}
function socketDidConnectToHost(sock,host,port) {
console.log('connected to host');
}
The connect to port part is working fine, but the delegate instance method is not being called when the connection is successful.
Tried with this:
let delegate = ...
let dispatchQueue = dispatch_queue_create("test_queue", null);
let udp = GCDAsyncSocket.alloc().initWithDelegateDelegateQueue(delegate, dispatchQueue);
And it works fine. Should also work for GCDAsyncSocket.
For some reason dispatch_get_main_queue() is undefined.
Ok, I got it to work
The problem was with marshalling dispatch_get_main_queue(). I got my script to work by editing GDCAsyncSocket.m in the source of the pod used.
GDCAsyncSocket.m:
delegateQueue = dq;
change to
delegateQueue = dispatch_get_main_queue();
this way dispatch_get_main_queue() is no longer needed to be passed from the js side, its value is evaluated in the objective c library.
Here is the working JS code:
var tcpClientDelegate = NSObject.extend({
socketDidConnectToHostPort(sock,host,port) {
console.log('connected to host: '+host);
console.log('connected to port: '+port);
}
}, {
protocols: [GCDAsyncSocketDelegate]
});
var clientInstance = new tcpClientDelegate();
var tcpClient = GCDAsyncSocket.alloc().initWithDelegateDelegateQueue(clientInstance,null);
var e = new interop.Reference();
if (!tcpClient.connectToHostOnPortError('192.168.88.110',3333,e)) {
console.log('Could not connect to mipbook');
console.log(e.value);
}

Opentok sending signal ios

I got a problem with OpenTok, I got a session of OTSession and I want to call the method signalWithType so I can send a chat message.
In the start I have
var session : OTSession?
And then in my method where I want to send chat message from textField I get the error 'Could not find memember 'signalWithType'
func textFieldShouldReturn(textField: UITextField) -> Bool {
self.view.endEditing(true)
let message = sendMessageField.text
sendMessageField.text = ""
var type = ""
var maybeError : OTError?
session?.signalWithType(type, string: message, connection: nil, error: maybeError)
if let error = maybeError {
println(error)
} else {
println("besked blev sendt")
}
return false
}
I can't find out why it says it as I pretty sure I got the right types and that.
I have not have other problems with calling methods from session..

indexOf of undefined error in parsing through cloud

Getting the error in below cloud function.
NSMutableDictionary * params = [NSMutableDictionary new];
params[#"user"] = _sender_ID;
params[#"recipientId"] = _owner_ID;
params[#"message"] = msgToSend;
[PFCloud callFunctionInBackground:#"sendPushToUser" withParameters:params block:^(id object, NSError *error) {
if (!error) {
// Push sent successfully
NSLog(#"msg posted!");
}
}];
error:
Error: TypeError: Cannot call method 'indexOf' of undefined
at main.js:15:35 (Code: 141, Version: 1.2.20)
Code for main.js is below.
Parse.Cloud.define("sendPushToUser", function(request, response) {
var senderUser = request.user;
var recipientUserId = request.params.recipientId;
var message = request.params.message;
// Validate that the sender is allowed to send to the recipient.
// For example each user has an array of objectIds of friends
if (senderUser.get("friendIds").indexOf(recipientUserId) === -1) {
response.error("The recipient is not the sender's friend, cannot send push.");
}
// Validate the message text.
// For example make sure it is under 140 characters
if (message.length > 140) {
// Truncate and add a ...
message = message.substring(0, 137) + "...";
}
// Send the push.
// Find devices associated with the recipient user
var recipientUser = new Parse.User();
recipientUser.id = recipientUserId;
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.equalTo("user", recipientUser);
// Send the push notification to results of the query
Parse.Push.send({
where: pushQuery,
data: {
alert: message
}
}).then(function() {
response.success("Push was sent successfully.")
}, function(error) {
response.error("Push failed to send with error: " + error.message);
});
});
The above is the code written in main.js on cloud got the same from the link below. As far as i have understood from the error is that the problem is with the friendIds that's why it is not calling method 'indexOf'.
Got the idea from this link blog.
It would appear that, contrary to what is asserted in the comments, that senderUser (that is, request.user) does not, in fact, have an array of friends stored in friendIds.
Without any information as to the contents of senderUser (for example, you may have just mis-spelled the name of the field), the best we can do is respond to the error more gracefully by adding this before the if generating the error:
if (senderUser.get("friendIds") === undefined) {
response.error("The sender does not have any friends, cannot send push.");
}

Resources