Detect Office Communicator Audio Call - c#

What im trying to do is a functionality that will advice users that make
audio calls in office communicator over a wireless connection to use a
wired connection instead.
i have been looking around but have not been able to find the info im searching for
Im looking for a way to detect if Office Communicator is in an Audio call.
is there an easy way to do this?

I don't think you'll be able to get exactly what you need with Communicator, but you can get close. (you could probably get even closer, or all the way there, if you were to upgrade to Lync).
You'll need to use the Automation API - documentation here, download here.
First thing to try is catching the users status changes:
MessengerClass _communicator;
public Form1()
{
InitializeComponent();
_communicator = new MessengerClass();
_communicator.OnMyStatusChange += new DMessengerEvents_OnMyStatusChangeEventHandler(_communicator_OnMyStatusChange);
}
void _communicator_OnMyStatusChange(int hr, MISTATUS mMyStatus)
{
AddText(string.Format("My Status changed to '{0}'", mMyStatus));
}
You're looking for a status of MISTATUS_ON_THE_PHONE
The downside of this is that certain statuses will override the MISTATUS_ON_THE_PHONE status. e.g. if the user is set to "Online", and then makes or receives a call, the status will change to MISTATUS_ON_THE_PHONE. But if their status is set to "Do not Disturb" and they make or receive a call, the status will NOT change to MISTATUS_ON_THE_PHONE.
You can maybe work around this a bit by examining the call as it is created. Catching a new conversation window being created is fairly straightforward:
_communicator = new MessengerClass();
_communicator.OnIMWindowCreated += new DMessengerEvents_OnIMWindowCreatedEventHandler(_communicator_OnIMWindowCreated);
Problem is, this will fire for IM and AV conversations, and also for incoming conversations as well as outgoing. There is no way to directly detect whether the call is an outgoing audio call.
You can also catch the "Contact Added" event, this will give you some info about which recipients get added to the conversation, and when. It's possible that the order in which this happens will give you some info as to whether its outgoing or incoming, and you could look for "tel:" uri's being added to tell you if the call is to a phone (although this won't help for communicator to communicator calls)
_communicator.OnIMWindowContactAdded += new DMessengerEvents_OnIMWindowContactAddedEventHandler(_communicator_OnIMWindowContactAdded);
The best thing to do is to have a play around with the events, and see what happens under which circumstances. This code should get you up and running with that.
MessengerClass _communicator;
public Form1()
{
InitializeComponent();
_communicator = new MessengerClass();
_communicator.OnIMWindowCreated += new DMessengerEvents_OnIMWindowCreatedEventHandler(_communicator_OnIMWindowCreated);
_communicator.OnIMWindowDestroyed += new DMessengerEvents_OnIMWindowDestroyedEventHandler(_communicator_OnIMWindowDestroyed);
_communicator.OnIMWindowContactAdded += new DMessengerEvents_OnIMWindowContactAddedEventHandler(_communicator_OnIMWindowContactAdded);
_communicator.OnIMWindowContactRemoved += new DMessengerEvents_OnIMWindowContactRemovedEventHandler(_communicator_OnIMWindowContactRemoved);
_communicator.OnMyStatusChange += new DMessengerEvents_OnMyStatusChangeEventHandler(_communicator_OnMyStatusChange);
}
void _communicator_OnMyStatusChange(int hr, MISTATUS mMyStatus)
{
AddText(string.Format("My Status changed to '{0}'", mMyStatus));
}
void _communicator_OnIMWindowContactRemoved(object pContact, object pIMWindow)
{
AddText(string.Format("{0} - Participant removed - '{1}'", ((IMessengerConversationWndAdvanced)pIMWindow).HWND, ((IMessengerContactAdvanced)pContact).SigninName));
}
void _communicator_OnIMWindowContactAdded(object pContact, object pIMWindow)
{
AddText(string.Format("{0} - Participant added - '{1}'", ((IMessengerConversationWndAdvanced)pIMWindow).HWND, ((IMessengerContactAdvanced)pContact).SigninName));
}
void _communicator_OnIMWindowDestroyed(object pIMWindow)
{
AddText(string.Format("{0} Conversation Closed, duration = {1}", ((IMessengerConversationWndAdvanced)pIMWindow).HWND, (DateTime.Now - _start).ToString()));
}
void _communicator_OnIMWindowCreated(object pIMWindow)
{
try
{
AddText(string.Format("{0} Conversation Created", ((IMessengerConversationWndAdvanced)pIMWindow).HWND));
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private delegate void AddTextDelegate(string text);
private void AddText(string text)
{
if (textBox1.InvokeRequired)
{
textBox1.Invoke(new AddTextDelegate(AddText), text);
return;
}
textBox1.Text += text + "\r\n";
}
By the way, don't forget to accept this as the answer using the "tick", if you feel that it helped :)

Related

Broadcast receiver listening for connectivity change firing at random intervals

I have a Xamarin.Android application that is supposed to sync my data when the device it is running on connects to a WiFi network. To save data and battery I only let this happen whenever it detects a connections.
The only thing is, the application would randomly run the sync service multiple time throughout the day, despite the WiFi connection remaining constant. Now, I can only imagine that the Android system is sending out the broadcast multiple times to remind applications of the connection state or something like that.
I've used a bit of a quick fix, the static bool FirstTime there, but I'm hoping to find a bit more of an elegant solution. Any suggestions?
This is the code I'm using to do it:
[BroadcastReceiver]
[IntentFilter(new string[] { "android.net.conn.CONNECTIVITY_CHANGE" })]
class ConnectivityReceiver : BroadcastReceiver
{
public static bool FirstTime = true;
public override void OnReceive(Context context, Intent intent)
{
if ( intent.Action != null && intent.Action == "android.net.conn.CONNECTIVITY_CHANGE")
{
ConnectivityManager cm = (ConnectivityManager)context.GetSystemService(Context.ConnectivityService);
NetworkInfo info = cm.ActiveNetworkInfo;
if (FirstTime && info != null)
{
FirstTime = false;
Intent background = new Intent(context, typeof(BackgroundDataSyncService));
context.StartService(background);
}else
{
FirstTime = true;
Intent background = new Intent(context, typeof(BackgroundDataSyncService));
context.StopService(background);
}
}
}
}
You have a plugin called Connectivity that can pulled from nuget.
This plugin is compatible with almost every mobile platform and it can be used only in android it you want.
The plugin does all that code for you and you only have to subscribe to connectivity events like:
CrossConnectivity.Current.ConnectivityChanged += (sender, args) =>
{
page.DisplayAlert("Connectivity Changed", "IsConnected: " + args.IsConnected.ToString(), "OK");
};
The plugin has another nice features please take a look at the documentation.
Check the information in your Intent Bundle. I had the same issue.
Whenever the system changes from WiFi to Cellular, or anything else weird happens in the system, the BroadCastReceiver will send out a message.
At first I thought this was a random event.
I also thought I had to use the ConnectivityManager to get the network information.
If you read the Intent Bundle that comes with the OnReceive(Context context, Intent intent), you'll get all kinds of information.
In my tests, I was working with Visual Studio's emulator. I used the built in tools to switch from WiFi to Cell then kill off the signal, as well as change the signal strength.
I found that the BroadcastReceiver reports at least twice; once for the disconnect, and once for the reconnect.
Here is how I read the Bundle.
Bundle extras = intent.Extras;
if (extras != null)
{
foreach (String key in extras.KeySet())
{
Object value = extras.Get(key);
Log.Info("myApp", "intent.extras " + key + " " + value.ToString());
}
}
You'll also find that one part of the Bundle contains the NetworkInfo too.
object netObj = extras.Get("networkInfo");
NetworkInfo netInf = null;
if (netObj != null)
{
netInf = (NetworkInfo)netObj;
}
With this, you can check the status of different network functions.
Log.Info("myApp", "netInf.IsAvailable: " + netInf.IsAvailable.ToString());
Log.Info("myApp", "netInf.IsConnected: " + netInf.IsConnected.ToString());
I truly hope this helps someone.
I've been chasing this for days.
Use Xamarin.Essentials.Connectivity.ConnectivityChanged event. Subscribe to this event.

using EWS Managed API with ASP.NET MVC

I'm trying to create a web app which does many things but the one that I'm currently focused in is the inbox count. I want to use EWS StreamSubscription so that I can get notification for each event and returns the total count of items in the inbox. How can I use this in terms of MVC? I did find some code from Microsoft tutorial that I was gonna test, but I just couldn't figure how I could use it in MVC world i.e. What's the model going to be, if model is the count then how does it get notified every time an event occurs in Exchange Server, etc.
Here's the code I downloaded from Microsoft, but just couldn't understand how I can convert the count to json and push it to client as soon as a new change event occurs. NOTE: This code is unchanged, so it doesn't return count, yet.
using System;
using System.Linq;
using System.Net;
using System.Threading;
using Microsoft.Exchange.WebServices.Data;
namespace StreamingNotificationsSample
{
internal class Program
{
private static AutoResetEvent _Signal;
private static ExchangeService _ExchangeService;
private static string _SynchronizationState;
private static Thread _BackroundSyncThread;
private static StreamingSubscriptionConnection CreateStreamingSubscription(ExchangeService service,
StreamingSubscription subscription)
{
var connection = new StreamingSubscriptionConnection(service, 30);
connection.AddSubscription(subscription);
connection.OnNotificationEvent += OnNotificationEvent;
connection.OnSubscriptionError += OnSubscriptionError;
connection.OnDisconnect += OnDisconnect;
connection.Open();
return connection;
}
private static void SynchronizeChangesPeriodically()
{
while (true)
{
try
{
// Get all changes from the server and process them according to the business
// rules.
SynchronizeChanges(new FolderId(WellKnownFolderName.Inbox));
}
catch (Exception ex)
{
Console.WriteLine("Failed to synchronize items. Error: {0}", ex);
}
// Since the SyncFolderItems operation is a
// rather expensive operation, only do this every 10 minutes
Thread.Sleep(TimeSpan.FromMinutes(10));
}
}
public static void SynchronizeChanges(FolderId folderId)
{
bool moreChangesAvailable;
do
{
Console.WriteLine("Synchronizing changes...");
// Get all changes since the last call. The synchronization cookie is stored in the _SynchronizationState field.
// Only the the ids are requested. Additional properties should be fetched via GetItem calls.
var changes = _ExchangeService.SyncFolderItems(folderId, PropertySet.IdOnly, null, 512,
SyncFolderItemsScope.NormalItems, _SynchronizationState);
// Update the synchronization cookie
_SynchronizationState = changes.SyncState;
// Process all changes
foreach (var itemChange in changes)
{
// This example just prints the ChangeType and ItemId to the console
// LOB application would apply business rules to each item.
Console.Out.WriteLine("ChangeType = {0}", itemChange.ChangeType);
Console.Out.WriteLine("ChangeType = {0}", itemChange.ItemId);
}
// If more changes are available, issue additional SyncFolderItems requests.
moreChangesAvailable = changes.MoreChangesAvailable;
} while (moreChangesAvailable);
}
public static void Main(string[] args)
{
// Create new exchange service binding
// Important point: Specify Exchange 2010 with SP1 as the requested version.
_ExchangeService = new ExchangeService(ExchangeVersion.Exchange2010_SP1)
{
Credentials = new NetworkCredential("user", "password"),
Url = new Uri("URL to the Exchange Web Services")
};
// Process all items in the folder on a background-thread.
// A real-world LOB application would retrieve the last synchronization state first
// and write it to the _SynchronizationState field.
_BackroundSyncThread = new Thread(SynchronizeChangesPeriodically);
_BackroundSyncThread.Start();
// Create a new subscription
var subscription = _ExchangeService.SubscribeToStreamingNotifications(new FolderId[] {WellKnownFolderName.Inbox},
EventType.NewMail);
// Create new streaming notification conection
var connection = CreateStreamingSubscription(_ExchangeService, subscription);
Console.Out.WriteLine("Subscription created.");
_Signal = new AutoResetEvent(false);
// Wait for the application to exit
_Signal.WaitOne();
// Finally, unsubscribe from the Exchange server
subscription.Unsubscribe();
// Close the connection
connection.Close();
}
private static void OnDisconnect(object sender, SubscriptionErrorEventArgs args)
{
// Cast the sender as a StreamingSubscriptionConnection object.
var connection = (StreamingSubscriptionConnection) sender;
// Ask the user if they want to reconnect or close the subscription.
Console.WriteLine("The connection has been aborted; probably because it timed out.");
Console.WriteLine("Do you want to reconnect to the subscription? Y/N");
while (true)
{
var keyInfo = Console.ReadKey(true);
{
switch (keyInfo.Key)
{
case ConsoleKey.Y:
// Reconnect the connection
connection.Open();
Console.WriteLine("Connection has been reopened.");
break;
case ConsoleKey.N:
// Signal the main thread to exit.
Console.WriteLine("Terminating.");
_Signal.Set();
break;
}
}
}
}
private static void OnNotificationEvent(object sender, NotificationEventArgs args)
{
// Extract the item ids for all NewMail Events in the list.
var newMails = from e in args.Events.OfType<ItemEvent>()
where e.EventType == EventType.NewMail
select e.ItemId;
// Note: For the sake of simplicity, error handling is ommited here.
// Just assume everything went fine
var response = _ExchangeService.BindToItems(newMails,
new PropertySet(BasePropertySet.IdOnly, ItemSchema.DateTimeReceived,
ItemSchema.Subject));
var items = response.Select(itemResponse => itemResponse.Item);
foreach (var item in items)
{
Console.Out.WriteLine("A new mail has been created. Received on {0}", item.DateTimeReceived);
Console.Out.WriteLine("Subject: {0}", item.Subject);
}
}
private static void OnSubscriptionError(object sender, SubscriptionErrorEventArgs args)
{
// Handle error conditions.
var e = args.Exception;
Console.Out.WriteLine("The following error occured:");
Console.Out.WriteLine(e.ToString());
Console.Out.WriteLine();
}
}
}
I just want to understand the basic concept as in what can be model, and where can I use other functions.
Your problem is that you are confusing a service (EWS) with your applications model. They are two different things. Your model is entirely in your control, and you can do whatever you want with it. EWS is outside of your control, and is merely a service you call to get data.
In your controller, you call the EWS service and get the count. Then you populate your model with that count, then in your view, you render that model property. It's really that simple.
A web page has no state. It doesn't get notified when things change. You just reload the page and get whatever the current state is (ie, whatever the current count is).
In more advanced applications, like Single Page Apps, with Ajax, you might periodically query the service in the background. Or, you might have a special notification service that uses something like SignalR to notify your SPA of a change, but these concepts are far more advanced than you currently are. You should probably develop your app as a simple stateless app first, then improve it to add ajax functionality or what not once you have a better grasp of things.
That's a very broad question without a clear-cut answer. Your model could certainly have a "Count" property that you could update. The sample code you found would likely be used by your controller.

Backgroundworker Stops Working

I have a WPF project that uses background workers to interfaces with some external hardware (Test & Measure equipment, etc), write to local files, and insert data into a database as it runs. Program flow is basically sequential, the background workers in use are to keep the GUI accessible for the user, and were chosen because I haven't had issues with using them before. We take measurements, do some stuff, log, then repeat. There is a status log on the GUI that displays messages as we go.
All of this works beautifully for hours on end, however, eventually, without fail, it appears that the background worker used to write to the database never calls DoWork.
BackgroundWorker DbLogWorker = new BackgroundWorker();
...
DbLogWorker.DoWork +=
new DoWorkEventHandler(DbLogWorker_DoWork);
DbLogWorker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(
DbLogWorker_RunWorkerCompleted);
ProcessScanData is called when data has been retrieved from one of the pieces of hardware, setting a property and firing a generic property changed event
(disclaimer: some extra code everywhere as I was investigating to see whats going on):
private void Data_DataSetChanged(object pSender, EventArgs pArgs)
{
this.Test.ProcessScanData(OsaVm.Osa.Data.DataSet);
}
...
public void ProcessScanData(SortedList<double,double> pData)
{
...
RaiseLogEvent(MessageType.SystemGeneral, "Logging to database...");
DbLogWorker.RunWorkerAsync(new AsyncDbLogArgs(CurrentChannel, tempdate,
loss1, loss2, loss3,
CurrentTemperature, CurrentPressure, CurrentRoomTemp));
}
private void DbLogWorker_DoWork(object pSender, DoWorkEventArgs pArgs)
{
AsyncDbLogArgs args = (AsyncDbLogArgs)pArgs.Argument;
string filename = string.Empty;
try
{
long datakey = Db.LogScan(CurrentChannel, args.Time,
args.Temperature, args.Pressure, args.RoomTemperature,
args.Loss1, args.Loss2, args.Loss3);
filename = args.Time.ToString(FOLDER_DATETIME_FORMAT) + "_[" + datakey.ToString() + "]";
}
catch (Exception ex)
{
filename = args.Time.ToString(FOLDER_DATETIME_FORMAT) + "_{" + (fileindex++) + "}";
}
pArgs.Result = new Tuple<AsyncDbLogArgs, string>(args, filename);
}
Symptoms:
Everything works fine for anywhere between 1 hour and ~16 hours until eventually we get to a point where we see "Logging to database..." and nothing else ever happens. No more messages, no exceptions (release build on target machine), no database entry...etc. This happens consistently.
I've been scratching my head on this for a while. Any leads will help, I have some workarounds in mind but I'd really like to know whats going on so I can avoid this in the future.
Thanks
Edited back to original code...thought the most recent would help avoid some "how do you know its not firing" questions

C# read/write mifare nfc tag

I've searched a lot but I'm not able to find some C# simple sdk that lets me write and read in a nfc mifare 1k classic tags.
Could you give me some help please?
Thanks a lot.
Just check my library for ACR122u readers. It also supports insert/discard events. It is so simple to use it. Basically you create a class and register two events to that class. Afterwards, call the Watch function. It watches the changes on your device.
//Initializing
NFCReader NFC = new NFCReader();
//Inserted Event
NFC.CardInserted += new NFCReader.CardEventHandler(...Some function);
//Ejected Event
NFC.CardEjected += new NFCReader.CardEventHandler(... Some function);
//Enabling Event Watching
NFC.Watch();
If any change occurs, it calls the related event. You handle what you want to do there.
public void Card_Inserted()
{
try
{
if (NFC.Connect())
{
//Do stuff like NFC.GetCardUID(); ...
}
else
{
//Give error message about connection...
}
}
catch (Exception ex)
{
//Something went wrong
}
}
public void Card_Ejected()
{
//Do stuff...
NFC.Disconnect();
}
See the related repo and links for more information.
Medium introduction tutorial:
https://medium.com/#hakbas/nfcreader-a-very-simple-nfc-library-for-c-that-supports-insert-and-discard-events-93db29f79b5
Github address:
https://github.com/h4kbas/NfcReader

How to wait for an Autoreset event to occur before taking any other action?

This is about the AutoResetEvent in C#. I tried to read other answers but I could not make sense and apply to my scenario. I am not writing any threading application. Just a small application to read/validate a file and update.
So I have this requirement to write some code for reading a fixed length file, validating it and then if it is valid upload it to Database.
I got everything working until I got stuck with the AutoResetEvent. So here is what is happening. Once the data is parsed/read I validate it using Flat File Checker utility in C#. So I called the functions into my application. Here is the snippet.
private AutoResetEvent do_checks = new AutoResetEvent(false);
public bool ValidationComplete = false;
This part goes in initialization code:
this._files.Validated += new EventHandler<SchemaValidatedEventArgs>(FileSetValidated);
public bool ValidateFile()
{
try
{
RunValidation();
return true;
}
catch (Exception e)
{
log.Error("Data Validation failed because :" + e.Message);
return false;
}
}
private void RunValidation()
{
// Use Flat File Checker user interface to create Schema file.
do_checks = _files.RunChecks();
log.Debug("Validation Started");
}
This is the method that is getting called asnchronusly during the validation process:
public void FileSetValidated(Object sender, SchemaValidatedEventArgs e)
{
try
{
ValidationComplete = e.Result;
if (IsDataValid)
{
log.Debug("Data is validated and found to be valid.");
}
else
{
log.Debug("Data is validated and found to be Invalid");
}
}
finally
{
do_checks.Set();
}
}
What is happening is that even before I get any value set into ValidationComplete the code is checked for Validation complete and because it is set by default to false, it returns false. The code in the FileSetValidated gets executed after that so the database update never happens.
The reason is that I cannot change the code because the Flat File Checker only accepts an AutoResetEvent as a return variable in RunChecks method.
******Here is what I did now*******
private AutoResetEvent do_checks;
public bool ValidateFile()
{
try
{
string extFilePath = surveyFile.ExtFilePath;
File.Copy(extFilePath, localTempFolder + "ExtractFile.Dat");
RunValidation();
if (!do_checks.WaitOne(TimeSpan.FromSeconds(30))) {
// throw new ApplicationException("Validation took more than expected!");
}
return true;
}
catch (Exception e)
{
log.Error("Data Validation failed because :" + e.Message);
return false;
}
}
private void RunValidation()
{
// Use Flat File Checker user interface to create Schema file.
do_checks = _files.RunChecks();
do_checks.WaitOne();
log.Debug("Validation Started");
}
Also I moved the part where data about validation gets passed on towards the beginning of the event handler so atleast that part gets executed. This helped but I am not sure if it is correct.
I have never worked with that lib, so I just downloaded it and looked into the code.
First of all, as "500 - Internal Server Error" already mentioned, it seems that part of the code is missing, at least "try" in the FileSetValidated method. I don't see any place where you are waiting for the event via WaitOne.
You don't need to create do_checks by yourself, because _files.RunChecks() creates AutoResetEven for this particular file's processing. So if you are using the same field for that event - you will get issue if you will need to process few files at the same time. So keep separate event for each file, in any case I don't see reason to keep that references as members if you don't want to stop processing in the middle (if you will call do_checks.Set() during processing, it will cancel processing without finishing it).
As I see in the lib code, you should not call do_checks.Set() in the FileSetValidated method, because it will be set, once processing will be done, so you can just write:
var do_checks = _files.RunChecks();
do_checks.WaitOne();
Feel free to share if that helped.
UPDATE:
I am not able to check that lib now to undestand why do_checks is set after starting processing, but I can suggest you to use your initial code with next RunValidation method:
private void RunValidation()
{
do_checks.Reset(); //reset state
_files.RunChecks(); //don't store event from the lib
log.Debug("Validation Started");
do_checks.WaitOne(); //Wait for FileSetValidated to set this event
}
Before exiting the ValidateFile function you need to wait for the validation to complete (wait on the AutoResetEvent) and return the validation result.
Try something like this:
public bool ValidateFile()
{
//try
{
RunValidation();
//Allocate enough time for the validation to occur but make sure
// the application doesn't block if the _files.Validated event doesn't get fired
if(!do_checks.WaitOne(TimeSpan.FromSeconds(10)))
{
throw ApplicationException("Validation took more than expected!");
}
return ValidationComplete;
}
//I would not catch the exception since having an error doesn't mean that the file
//is invalid. Catch it upper in the call stack and inform the user that the validation
//could not be performed because of the error
//catch (Exception e)
//{
// log.Error("Data Validation failed because :" + e.Message);
// return false;
//}
}

Categories

Resources