diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/AudioCodecBaseMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/AudioCodecBaseMessenger.cs
new file mode 100644
index 00000000..7eb3d5aa
--- /dev/null
+++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/AudioCodecBaseMessenger.cs
@@ -0,0 +1,120 @@
+using System;
+using System.Linq;
+using Newtonsoft.Json.Linq;
+using PepperDash.Essentials.Devices.Common.AudioCodec;
+using PepperDash.Essentials.Devices.Common.Codec;
+
+namespace PepperDash.Essentials.AppServer.Messengers
+{
+ ///
+ /// Provides a messaging bridge for an AudioCodecBase device
+ ///
+ public class AudioCodecBaseMessenger : MessengerBase
+ {
+ ///
+ /// Device being bridged
+ ///
+ public AudioCodecBase Codec { get; private set; }
+
+ ///
+ /// Constuctor
+ ///
+ ///
+ ///
+ ///
+ public AudioCodecBaseMessenger(string key, AudioCodecBase codec, string messagePath)
+ : base(key, messagePath, codec)
+ {
+ Codec = codec ?? throw new ArgumentNullException("codec");
+ codec.CallStatusChange += Codec_CallStatusChange;
+ }
+
+ ///
+ protected override void RegisterActions()
+
+ {
+ base.RegisterActions();
+
+ AddAction("/fullStatus", (id, content) => SendAtcFullMessageObject(id));
+
+ AddAction("/audioDialerStatus", (id, content) => SendAtcFullMessageObject(id));
+
+ AddAction("/dial", (id, content) =>
+ {
+ var msg = content.ToObject>();
+
+ Codec.Dial(msg.Value);
+ });
+
+ AddAction("/endCallById", (id, content) =>
+ {
+ var msg = content.ToObject>();
+
+ var call = GetCallWithId(msg.Value);
+ if (call != null)
+ Codec.EndCall(call);
+ });
+
+ AddAction("/endAllCalls", (id, content) => Codec.EndAllCalls());
+ AddAction("/dtmf", (id, content) =>
+ {
+ var msg = content.ToObject>();
+
+ Codec.SendDtmf(msg.Value);
+ });
+
+ AddAction("/rejectById", (id, content) =>
+ {
+ var msg = content.ToObject>();
+
+ var call = GetCallWithId(msg.Value);
+
+ if (call != null)
+ Codec.RejectCall(call);
+ });
+
+ AddAction("/acceptById", (id, content) =>
+ {
+ var msg = content.ToObject>();
+ var call = GetCallWithId(msg.Value);
+ if (call != null)
+ Codec.AcceptCall(call);
+ });
+ }
+
+ ///
+ /// Helper to grab a call with string ID
+ ///
+ ///
+ ///
+ private CodecActiveCallItem GetCallWithId(string id)
+ {
+ return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id);
+ }
+
+ private void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
+ {
+ SendAtcFullMessageObject();
+ }
+
+ ///
+ /// Helper method to build call status for vtc
+ ///
+ ///
+ private void SendAtcFullMessageObject(string id = null)
+ {
+ var info = Codec.CodecInfo;
+
+ PostStatusMessage(JToken.FromObject(new
+ {
+ isInCall = Codec.IsInCall,
+ calls = Codec.ActiveCalls,
+ info = new
+ {
+ phoneNumber = info?.PhoneNumber
+ }
+ }), id
+ );
+ }
+ }
+}
\ No newline at end of file