According to the Google Anymote Protocol documentation, a GoogleTV device can be discovered by sending mDNS packets.
A GoogleTV device should respond by identifying itself with the string "_anymote._tcp.local".
However, when I send out a mDNS packet, I receive a response with NSZGT1-6017678.local.
Unless the documentation is incorrect, I don't see a way to identify the device as a GTV device.
Is there something I am missing?
For example, only the airplay string actually returns any device in the following code:
String airplay = "_airplay._tcp.local.";
String gtv1 = "_anymote._tcp.local.";
String gtv2 = "_anymote._tcp.local";
JmDNS jmDNS = JmDNS.create();
jmDNS.addServiceListener(gtv1, new ServiceListener() {
public void serviceResolved(ServiceEvent event) {}
public void serviceRemoved(ServiceEvent event) {}
public void serviceAdded(ServiceEvent event) {
System.out.println("Service added: " + event.getName() + " " + event.getInfo().getName());
}
});
Apparently mDNS is not used for discovering devices, although it can be, there's just no way to filter out just GTV devices that I have found.
Instead a message is broadcast on the network on port 9101. See the following implementation:
http://code.google.com/p/google-tv-remote/source/browse/src/com/google/android/apps/tvremote/BroadcastDiscoveryClient.java
Related
I'm trying to receive data from a gadget with OSC Protocol, and with a port that I defined, I can receive the message in the Protokol android app. I want to receive messages in my app. I think the OSCpackage for flutter is not properly working, or maybe I made a wrong!
This is receive function:
int defaultPort = 12345;
void receiveOsc(List<String> args) {
final port = defaultPort;
final socket = OSCSocket(serverPort: port);
print(socket);
socket.listen((msg) {
print("${msg.toString()}");
socket.reply(OSCMessage('/received', arguments: []));
});
}
i Want to get messages in string format in my defined port.
I have managed to basically connect with my friend over internet, by forwarding my IP address from my router settings... this is not viable because there are few people willing to do what I did to play games with their friends. So how to actually do UDP hole punching (basically what I did manually to my router) in unity using the mirror networking solution...
A common solution to this problem is WebRTC, which takes care of the hole punching under the hood. Unity maintains this package which implements WebRTC. They also provide a great tutorial on how to use it. The nuts and bolts of it are:
using UnityEngine;
using Unity.WebRTC;
public class MyPlayerScript : MonoBehaviour
{
RTCPeerConnection localConnection, remoteConnection;
RTCDataChannel sendChannel, receiveChannel;
private void Awake()
{
// Initialize WebRTC
WebRTC.Initialize();
// Create local peer
localConnection = new RTCPeerConnection();
sendChannel = localConnection.CreateDataChannel("sendChannel");
channel.OnOpen = handleSendChannelStatusChange;
channel.OnClose = handleSendChannelStatusChange;
// Create remote peer
remoteConnection = new RTCPeerConnection();
remoteConnection.OnDataChannel = ReceiveChannelCallback;
// register comms paths
localConnection.OnIceCandidate = e => {
!string.IsNullOrEmpty(e.candidate)
|| remoteConnection.AddIceCandidate(ref e);
}
remoteConnection.OnIceCandidate = e => {
!string.IsNullOrEmpty(e.candidate)
|| localConnection.AddIceCandidate(ref e);
}
localConnection.OnIceConnectionChange = state => {
Debug.Log(state);
}
}
//handle begin
IEnumerator Call(){
var op1 = localConnection.CreateOffer();
yield return op1;
var op2 = localConnection.SetLocalDescription(ref op1.desc);
yield return op2;
var op3 = remoteConnection.SetRemoteDescription(ref op1.desc);
yield return op3;
var op4 = remoteConnection.CreateAnswer();
yield return op4;
var op5 = remoteConnection.setLocalDescription(op4.desc);
yield return op5;
var op6 = localConnection.setRemoteDescription(op4.desc);
yield return op6;
}
//handle send messages
void SendMessage(string message)
{
sendChannel.Send(message);
}
void SendBinary(byte[] bytes)
{
sendChannel.Send(bytes);
}
//handle receive messages
void ReceiveChannelCallback(RTCDataChannel channel)
{
receiveChannel = channel;
receiveChannel.OnMessage = HandleReceiveMessage;
}
void HandleReceiveMessage(byte[] bytes)
{
var message = System.Text.Encoding.UTF8.GetString(bytes);
Debug.Log(message);
}
//handle end
private void OnDestroy()
{
sendChannel.Close();
receiveChannel.Close();
localConnection.Close();
remoteConnection.Close();
WebRTC.Finalize();
}
}
I have also found a useful way to do this using mirror and the epic free relay for this. Thanks so much for the other answers, it really helped understand better what I needed to search and use!
You can use Photon Bolt or Photon Fusion to let players host a game on their local machine like minecraft, etc. Photon provides relay as well as tries to use STUN to establish direct peer to peer connection to the host via UDP. PUN2 is also a good choice, although I like Photon Bolt/Fusion better - it's less of a simple RPC framework and more programmer oriented. Also, PUN does not do any STUN direct peer connection, it will always be relayed. Photon Bolt and Fusion will first attempt a STUN direct peer connection and then fallback to relay if necessary. It's been around for years and is the best choice.
Sure you can develop a Unity game with Mirror (although without a relay built in) but it's not nearly as easy to setup and use as Photon Bolt/Fusion and they don't provide a relay. As someone mentioned, you might be able to hack something together in some way but yeah - not recommended.
Ugh, yeah don't use WebRTC for a Unity game (or probably anything other than streaming music/video like it was made for to be honest).
Unity's MLAPI is "under development" and their last API was suddenly dropped "deprecated", so I wouldn't use that.
I'm working on a UWP application which should communicate via TCP/UDP to a remote device. My issue is that the UWP app successfully sends UDP messages to the remote device, but does not receive the replies.
Here follows the code extracted from the app (simplified):
async Task TestUdpIP()
{
// Writer to the DatagramSocket
DataWriter writer;
using (var udpClient = new DatagramSocket())
{
try
{
// UDP Socket binding
udpClient.MessageReceived += UdpClient_MessageReceived;
var controllerName = new Windows.Networking.HostName(controllerIpAddress.ToString());
await udpClient.BindEndpointAsync(controllerName, controllerIpPort.ToString());
var remoteHostName = new Windows.Networking.HostName(hostIpAddres.ToString());
await udpClient.ConnectAsync(remoteHostName, remoteHostPort.ToString());
// Create a message to send
string message = "Some message";
// Reset the counter of messages received back from the remote robot
messagesReceived = 0;
// Send the message
writer = new DataWriter(udpClient.OutputStream);
writer.WriteString(message);
await writer.StoreAsync();
// Wait for robot status messages
await Task.Delay(5000);
}
catch
{
}
}
}
void UdpClient_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
// Just increment the number of messages received
messagesReceived++;
}
However the UdpClient_MessageReceived handler does not fire. I'm sure that UDP messages are correctly sent from the UWP app and that the remote device replies back as shown in the following screenshot from Wireshark (the test has been taken on the same PC where the UWP app is running)
.
(IP Address, Port) details are shown in the following list to better explain the picture above
UWP application: (192.168.1.108, 19000) to send and receive.
Remote device: (192.168.1.152, 15999) to receive and (192.168.1.152, 54697) to send
Note: this is a similar question, where the answer says that for whatever reason the DatagramSocket should fire some messages before being able to receive. In my example a message is sent out however the message received handler does not fire anyway.
Note: The UWP app has been granted the internet (client) and the internet (client and server) capabilities
Note: I've tried also this (more readable) approach to bind the inbound/outbound datagram socket on the UWP app obtaining the same results:
// UDP Socket binding
var controllerName = new HostName(controllerIpAddress.ToString());
var remoteHostName = new HostName(hostIpAddres.ToString());
EndpointPair endpointpar = new EndpointPair(controllerName,
controllerIpPort.ToString(),
remoteHostName,
remoteHostPort.ToString());
udpClient.MessageReceived += UdpClient_MessageReceived;
await udpClient.ConnectAsync(endpointpar);
Where is the issue? Many thanks!
Please try to also add the Private Networks (Client & Server) capability in your app's manifest.
On other hand, you can try the Official DatagramSocket sample to see whether the both devices can communicate with each other.
After some experimenting, I came out with the idea of using two different DatagramSocket instances: one to send out UDP messages, and one to listen for incoming messages. With this code, I've been able to send UDP messages to the remote device (as before) and also I've been able to receive UDP messages from the remote device.
async Task TestUdpIP_DifferentPorts()
{
// Writer to the DatagramSocket
DataWriter writer;
// Inbound and outbound DatagramSocket
DatagramSocket udpListener = new DatagramSocket();
DatagramSocket udpSender = new DatagramSocket();
try
{
// String containing the serializaed message
string serializedMessage = "Some message";
var controllerName = new HostName(controllerIpAddress.ToString());
var remoteHostName = new HostName(hostIpAddres.ToString());
// Bind listener
udpListener.MessageReceived += UdpClient_MessageReceived;
await udpListener.BindEndpointAsync(controllerName, controllerIpPort.ToString());
// Connect sender
await udpSender.ConnectAsync(remoteHostName, remoteHostPort.ToString());
// Reset the counter of messages received back from the remote robot
messagesReceived = 0;
// Send the message
writer = new DataWriter(udpSender.OutputStream);
writer.WriteString(JsonConvert.SerializeObject(message));
await writer.StoreAsync();
// Wait for robot status messages
await Task.Delay(1000);
}
catch (Exception ex)
{
// Some exception handling
}
udpSender.Dispose();
udpListener.Dispose();
}
void UdpClient_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
// Just increment the number of messages received
messagesReceived++;
}
With this approach only the IP port (or service name) of the inbound listener needs to be specified. The framework will choose the next available outbound IP port.
Note: If I understand well the DatagramSocket.ConnectAsync(EndpointPair) documentation, the same DatagramSocket instance can be used to send and listen for incoming message, so I could not figure out the need for two different instances. From the documentation:
This ConnectAsync(EndPointPair) method on a DatagramSocket is used to define the local and remote endpoint where datagrams will be sent when using the OutputStream property. This method also restricts remote IP addresses of packets that will be accepted to the remote hostname in the endpointPair parameter. Only incoming packets that match the remote endpoint in the endpointPair parameter will trigger the MessageReceived event on the DatagramSocket.
We are looking to integrate an IP camera (h.264 RTSP stream) with an asterisk PBX system for use in a school for distributed education (so a remote teacher can "dial in and teach").
Ideally we would like to be able to create a SIP client as an autoanswer pbx extension.
We are considering running a *nix box that can use a network video stream as a source for video, mix a separate audio source and present a SIP endpoint.
I understand that SIP express router may be able to:
"call an external C script, which could parse and change the SDP info within the SIP headers of clients it porxy's with, and change address of where it expects to recieve media from."
but I'm thinking it may be easier to look for a way to present an h.264 rtsp stream as /dev/videoX and use a standard SIP client.
If anyone has any pointers or any ideas for research I'd be really appreciative :-)
Thanks for reading!
W
p.s. there are IP cameras out there that claim to have SIP clients, but all I have seen only offer SIP for establishing a bi-directional audio session.
I don't know whether you found the correct answer to this question or not after all this time, but maybe I can give you some advice with VoIP and IP camera management and it would help anybody who has the same problem.
Your goal (if I understand your problem correctly) is basically creating a conference call solution which answers all the incoming calls and attach the IP camera video to all of these calls. I currently work at a company called Ozeki and - I don't know if there's an open-source solution for your problem or not - I'm going to show you an example code with SIP account registration, IP camera connection and answer all the incoming calls with the camera video.
So here is the source code:
public partial class Form1 : Form
{
private IIPCamera _camera;
private DrawingImageProvider _imageProvider;
private MediaConnector _connector;
private VideoViewerWF _videoViewerWf;
private ISoftPhone _softphone;
private IPhoneLine _phoneLine;
private IPhoneCall _call;
private PhoneCallAudioSender _audioSender;
private PhoneCallVideoSender _videoSender;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
_softphone = SoftPhoneFactory.CreateSoftPhone(5000, 10000);
_softphone.IncomingCall += softphone_IncomingCall;
_connector = new MediaConnector();
_videoSender = new PhoneCallVideoSender();
_audioSender = new PhoneCallAudioSender();
_imageProvider = new DrawingImageProvider();
_videoViewerWf = new VideoViewerWF();
SetVideoViewer();
}
private void SetVideoViewer()
{
CameraBox.Controls.Add(_videoViewerWf);
_videoViewerWf.Size = new Size(260, 180);
_videoViewerWf.BackColor = Color.Black;
_videoViewerWf.TabStop = false;
_videoViewerWf.FlipMode = FlipMode.None;
_videoViewerWf.Location = new Point(35, 30);
_videoViewerWf.Name = "_videoViewerWf";
}
private void Register(bool registrationRequired, string displayName, string userName, string authenticationId, string registerPassword, string domainHost)
{
try
{
var account = new SIPAccount(registrationRequired, displayName, userName, authenticationId, registerPassword, domainHost);
_phoneLine = _softphone.CreatePhoneLine(account);
_phoneLine.RegistrationStateChanged += phoneLine_RegistrationStateChanged;
_softphone.RegisterPhoneLine(_phoneLine);
}
catch (Exception ex)
{
label_Phoneline.Text = ex.Message;
}
}
private void phoneLine_RegistrationStateChanged(object sender, RegistrationStateChangedArgs e)
{
InvokeGuiThread(() => label_Phoneline.Text = e.State.ToString());
}
private void softphone_IncomingCall(object sender, VoIPEventArgs<iphonecall> e)
{
if (_camera != null)
{
_call = e.Item;
_call.CallStateChanged += call_CallStateChanged;
ConnectToCall();
_call.Answer();
}
}
private void ConnectToCall()
{
_videoSender.AttachToCall(_call);
_audioSender.AttachToCall(_call);
_connector.Connect(_camera.VideoChannel, _videoSender);
_connector.Connect(_camera.AudioChannel, _audioSender);
}
private void call_CallStateChanged(object sender, CallStateChangedArgs e)
{
InvokeGuiThread(() => label_Call.Text = e.State.ToString());
if (e.State == CallState.Completed)
if (_call != null)
{
_call.CallStateChanged -= call_CallStateChanged;
_connector.Disconnect(_camera.VideoChannel, _videoSender);
_connector.Disconnect(_camera.AudioChannel, _audioSender);
}
}
private void button_Connect_Click(object sender, EventArgs e)
{
_camera = IPCameraFactory.GetCamera("cameraIPAddress:8080", "admin", "admin");
_connector.Connect(_camera.VideoChannel, _imageProvider);
_videoViewerWf.SetImageProvider(_imageProvider);
_videoViewerWf.Start();
_camera.Start();
}
private void button_SIPRegister_Click(object sender, EventArgs e)
{
Register(true, "100", "100", "100", "100", "PBXAddress");
}
private void InvokeGuiThread(Action action)
{
BeginInvoke(action);
}
}
And the (example) GUI:
If you click on Connect button then the IPCameraFactory.GetCamera() will be called which is for connecting to the specified camera using the arguments (RTSP/RTP/HTTP messages in the background).
The Register button calls the Register() method to register your SIP account to the PBX. You can check the registration status at the Status label.
If there is an incoming call then the answer will occur automatically and the camera video and audio channel will attach to the call. So the caller will see and hear you.
Note:
Most of the IP camera microphones have really bad quality so you may connect your own microphone to the call. It's really simple too.
Create a Microphone object:
Microphone microphone = Microphone.GetDefaultDevice();
if (microphone != null)
microphone.Start();
And if there's an incoming call then connect this microphone to the call:
_connector.Connect(microphone, _audioSender);
And that's it. I hope I could help you!
live555 has some open-source implementations like openRTSP and playSIP which could help with your requirements.
Is it possible to intercept an SMS coming from a certain number and direct it to a certain application on the iPhone/Android where it will be processed?
Thanks.
In Android, what you can do is register a BroadcastReceiver to be notified that an SMS has been received, mark the message as read in the SMS Content Provider and then delete that specific message from the content provider. This will prevent any other applications from being able to read the message once you have deleted it and no notifications will be shown in the notification space. That said, I have no idea what will happen to the applications that receive the Intent indicating that a message has been received but then cannot access it in the database. This could result in unpredictable behavior as a result of a number of race conditions.
Yes. It is possible in Android. I'm doing it in an app I'm developing.
What you need to do is:
public class SMSService extends BroadcastReceiver {
public static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private String phoneNumber;
private String sms;
private Context context;
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
if (intent.getAction().equals(SMS_RECEIVED)) {
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++) {
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
// get sms message
sms = msgs[i].getMessageBody();
// get phone number
phoneNumber = msgs[i].getOriginatingAddress();
if (phoneNumber.equals("Some other phone number")){
// the sms will not reach normal sms app
abortBroadcast();
Thread thread = new Thread(null,
doBackgroundThreadProcessing, "Background");
thread.start();
}
}
}
}
}
private Runnable doBackgroundThreadProcessing = new Runnable() {
// do whatever you want
};
IMPORTANT:
In manifest file you have to define SMS priority with an high number. I believe the max is 100.
<!-- SMS Service -->
<service android:name=".SMSService" />
<receiver android:name=".SMSService">
<intent-filter android:priority="100">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
For Android the answer is no. You can implement a BroadcastReceiver that is called whenever the device receives an SMS text message but cannot keep other applications (e.g. the built-in Messaging app) from receiving them too.
For Android the answer is Yes.
android.provider.Telephony.SMS_RECEIVED event is an ordered broadcast and you can tune the priority. This means your application will receive the event before everyone else. And you can cancel Broadcast for the rest of Broadcast Receivers.
You can find more information here: stackoverflow.com/can-we-delete-an-sms-in-android-before-it-reaches-the-inbox/
In Android, once you received an SMS message in your application, you can use an Intent object to pass the details of the message to another activity/application for further processing. If you need to pass the message to your own application, use the sendBroadcast() method to broadcast the Intent object. In your activity, you would just need to use the registerReceiver() method to listen for the broadcast.
Hope it helps!
Wei-Meng Lee