diff --git a/Nasal/debug/emesary.deb.nas b/Nasal/debug/emesary.deb.nas
new file mode 100644
index 000000000..b237a5d6d
--- /dev/null
+++ b/Nasal/debug/emesary.deb.nas
@@ -0,0 +1,50 @@
+#-------------------------------------------------------------------------------
+# emesary.deb.nas - emesary debug helpers
+#-------------------------------------------------------------------------------
+var _emesaryDebugN = props.getNode("/_debug/emesary/",1);
+var _emesaryDebugEnableN = _emesaryDebugN.getNode("enabled",1);
+_emesaryDebugEnableN.setBoolValue(_emesaryDebugEnableN.getValue());
+
+var __setup = func {
+    var debugRecipient = emesary.Recipient.new("Debug");
+
+    debugRecipient.Receive = func(ntf) {
+        _emesaryDebugEnableN.getValue() or return;
+        
+        if (!isa(ntf, emesary.Notification)) {
+            logprint(DEV_ALERT, "debugRecipient: argument is not a emesary.Notification!");
+            return emesary.Transmitter.ReceiptStatus_Fail; 
+        }
+        # ignore FrameNotification as it would flood the log/console at frame rate
+        if (ntf.NotificationType != "FrameNotification") {
+            print("debugRecipient: type=", ntf.NotificationType, " id=", ntf.Ident);
+            debug.dump(keys(ntf));
+            # count notifications
+            if (isstr(ntf.NotificationType)) {
+                var cnt = _emesaryDebugN.getChild(ntf.NotificationType, 0, 1);
+                if (isstr(ntf.Ident)) {
+                    cnt = cnt.getNode(ntf.Ident, 1);
+                }
+                if (cnt.getValue() == nil) {
+                    cnt.setIntValue(0);
+                }
+                cnt.increment();
+            }
+        }
+        return emesary.Transmitter.ReceiptStatus_NotProcessed; 
+    }
+
+    emesary.GlobalTransmitter.Register(debugRecipient);
+
+    # send a test message
+    var debugNotification = emesary.Notification.new("debug", "test");
+    emesary.GlobalTransmitter.NotifyAll(debugNotification);
+
+    #add monitoring
+    emesary._transmitters.addCallback(func (k, v) {
+        emesary._transmitters.keys2props(_emesaryDebugN);
+    });
+    emesary._transmitters.keys2props(_emesaryDebugN);
+}
+
+settimer(__setup,0);
\ No newline at end of file
diff --git a/Nasal/emesary.nas b/Nasal/emesary.nas
index 0583c138a..35f5621d9 100644
--- a/Nasal/emesary.nas
+++ b/Nasal/emesary.nas
@@ -22,56 +22,101 @@
  #
  #  Copyright © 2016 Richard Harrison           Released under GPL V2
  #
+ #---------------------------------------------------------------------------
+ # Classes in this file:
+ # Transmitter
+ # Notification
+ # Recipient
  #---------------------------------------------------------------------------*/
 
 var __emesaryUniqueId = 14; # 0-15 are reserved, this way the global transmitter will be 15.
 
+# add registry so we can find a transmitter by name in genericEmesaryGlobalTransmitterTransmit 
+var _transmitters = Hash.new("transmitters");
+
+var _registerTransmitter = func (key, t) {
+    _transmitters.set(key, t);
+}
+var getTransmitter = func (key) {
+    return _transmitters.get(key);
+}
+
 # Transmitters send notifications to all recipients that are registered.
 var Transmitter =
 {
     ReceiptStatus_OK : 0,          # Processing completed successfully
     ReceiptStatus_Fail : 1,        # Processing resulted in at least one failure
-    ReceiptStatus_Abort : 2,       # Fatal error, stop processing any further recipieints of this message. Implicitly failed.
-    ReceiptStatus_Finished : 3,    # Definitive completion - do not send message to any further recipieints
+    ReceiptStatus_Abort : 2,       # Fatal error, stop processing any further recipients of this message. Implicitly failed.
+    ReceiptStatus_Finished : 3,    # Definitive completion - do not send message to any further recipients
     ReceiptStatus_NotProcessed : 4,# Return value when method doesn't process a message.
     ReceiptStatus_Pending : 5,     # Message sent with indeterminate return status as processing underway
     ReceiptStatus_PendingFinished : 6,# Message definitively handled, status indeterminate. The message will not be sent any further
 
     # create a new transmitter. shouldn't need many of these
+    # _ident:   string; name of the transmitter, used in debug messages
     new: func(_ident)
     {
-        var new_class = { parents: [Transmitter]};
-        new_class.Recipients = [];
-        new_class.Ident = _ident;
-        new_class.Timestamp = nil;
-        new_class.MaxMilliseconds = 1;
+        if (!isscalar(_ident)) {
+            logprint(LOG_ALERT, "Transmitter.new: argument must be a scalar!")
+        }
         __emesaryUniqueId += 1;
-        new_class.UniqueId = __emesaryUniqueId;
+        var new_class = { 
+            parents : [Transmitter],
+            Recipients : [],
+            Ident : _ident,
+            Timestamp : nil,
+            MaxMilliseconds : 1,
+            UniqueId: __emesaryUniqueId,
+        };
+        _registerTransmitter(_ident, new_class);
         return new_class;
     },
+    
     OverrunDetection: func(max_ms=0){
-          if (max_ms){
-              if (me.Timestamp == nil)
+        if (isnum(max_ms) and max_ms) {
+            if (me.Timestamp == nil)
                 me.Timestamp = maketimestamp();
-              me.MaxMilliseconds = max_ms;
-#print("Set overrun detection ",me.Ident, " to ", me.MaxMilliseconds);
-          } else {
-              #              me.Timestamp = nil;
-              me.MaxMilliseconds = 0;
-#print("Disable  overrun detection ",me.Ident);
-          }
-      }
- ,
+            me.MaxMilliseconds = max_ms;
+            logprint(LOG_INFO, "Set overrun detection ",me.Ident, " to ", me.MaxMilliseconds);
+            return 1;
+        } else {
+            # me.Timestamp = nil;
+            me.MaxMilliseconds = 0;
+            logprint(LOG_INFO, "Disable  overrun detection ",me.Ident);
+            return 0;
+        }
+    },
 
     # Add a recipient to receive notifications from this transmitter
     Register: func (recipient)
     {
+        # not inheriting from Recipient is maybe strange but will not crash
+        if (!isa(recipient, Recipient))
+        {
+            logprint(LOG_INFO, "Transmitter.Register: argument is not a Recipient object");
+        }
+        #not having a Receive function is an error
+        if (!isfunc(recipient["Receive"]))
+        {
+            logprint(DEV_ALERT, "Transmitter.Register: Error, argument has no Receive method!");
+            return 0;
+        }
+        foreach (var r; me.Recipients)
+        {
+            if (r == recipient) {
+                logprint(DEV_ALERT, "Transmitter.Register: Recipient already registered!");
+                return 1;
+            }
+        }        
         append(me.Recipients, recipient);
+        return 1;
     },
+    
     DeleteAllRecipients: func
     {
         me.Recipients = [];
     },
+    
     # Stops a recipient from receiving notifications from this transmitter.
     DeRegister: func(todelete_recipient)
     {
@@ -111,10 +156,12 @@ var Transmitter =
     #  - Fail > message not handled. A status of Abort from a recipient will result in our status
     #           being fail as Abort means that the message was not and cannot be handled, and
     #           allows for usages such as access controls.
+    # message:  hash; Notification passed to the Receive() method of registered recipients
     NotifyAll: func(message)
     {
-        if (message == nil){
-            print("Emesary: bad notification nil");
+        if (!isa(message, Notification))
+        {
+            logprint(DEV_ALERT, "Transmitter.NotifyAll: argument must be a Notification!");
             return Transmitter.ReceiptStatus_NotProcessed;
         }
         me._return_status = Transmitter.ReceiptStatus_NotProcessed;
@@ -134,9 +181,12 @@ var Transmitter =
                     foreach(var line; err) {
                         print(line);
                     }
-                    print("Recipient ",recipient.Ident, " has been removed from transmitter (", me.Ident, ") because of the above error");
+                    logprint(LOG_ALERT, "Recipient ",recipient.Ident, 
+                        " has been removed from transmitter (", me.Ident,
+                        ") because of the above error");
                     me.DeRegister(recipient);
-                    return Transmitter.ReceiptStatus_Abort;#need to break the foreach due to having modified what its iterating over.
+                    #need to break the foreach due to having modified what its iterating over.
+                    return Transmitter.ReceiptStatus_Abort; 
                 }
                 if (me.Timestamp != nil) {
                     recipient.TimeTaken = me.Timestamp.elapsedUSec()/1000.0;
@@ -166,20 +216,26 @@ var Transmitter =
                 }
                 elsif(me._rstat == Transmitter.ReceiptStatus_Abort)
                 {
+                    # this is a final results, e.g. no more recipients will be
+                    # notified but the result is returned as NotifyAll result.
                     return Transmitter.ReceiptStatus_Abort;
                 }
                 elsif(me._rstat == Transmitter.ReceiptStatus_Finished)
                 {
+                    # this is a final results, e.g. no more recipients will be
+                    # notified but the result is returned as NotifyAll result.
                     return Transmitter.ReceiptStatus_OK;
                 }
             }
         }
-        if (me.MaxMilliseconds and me.TimeTaken > me.MaxMilliseconds ){
-            printf("Overrun: %s ['%s'] %1.2fms max (%d)",me.Ident,message.NotificationType, me.TimeTaken,me.MaxMilliseconds);
-#            print("Overrun: ",me.Ident, "['",message.NotificationType,"']", " ", me.TimeTaken,"ms  (max ",me.MaxMilliseconds," ms)");
+        if (me.MaxMilliseconds and me.TimeTaken > me.MaxMilliseconds) {
+            logprint(LOG_WARN, sprintf("Overrun: %s ['%s'] %1.2fms max (%d)",
+                me.Ident, message.NotificationType, me.TimeTaken, me.MaxMilliseconds));
             foreach (var recipient; me.Recipients) {
-                if (recipient.TimeTaken)
-                  printf(" -- Recipient %25s %7.2f ms",recipient.Ident, recipient.TimeTaken);
+                if (recipient.TimeTaken) {
+                  logprint(LOG_WARN, sprintf(" -- Recipient %25s %7.2f ms",
+                    recipient.Ident, recipient.TimeTaken));
+                }
             }
         }
         return me._return_status;
@@ -222,102 +278,158 @@ var QueuedTransmitter =
      }
 };
 
-#
-#
-# Base class for Notifications. By convention a Notification has a type and a value.
-#   SubClasses can add extra properties or methods.
-# Properties:
-# Ident : Generic message identity. Can be an ident, or for simple messages a value that needs transmitting.
-# NotificationType  : Notification Type
-# IsDistinct : non zero if this message supercedes previous messages of this type.
-#              Distinct messages are usually sent often and self contained
-#              (i.e. no relative state changes such as toggle value)
-#              Messages that indicate an event (such as after a pilot action)
-#              will usually be non-distinct. So an example would be gear/up down
-#              or ATC acknowledgements that all need to be transmitted
+
+#---------------------------------------------------------------------------
+# Notification - base class 
+# By convention a Notification has a type and a value. Derived classes can add 
+# extra properties or methods.
+# 
+# NotificationType: Notification Type
+# Ident:      Can be an ident, or for simple messages a value that needs transmitting.
+# IsDistinct: non zero if this message supercedes previous messages of this type.
+#             Distinct messages are usually sent often and self contained
+#             (i.e. no relative state changes such as toggle value)
+#             Messages that indicate an event (such as after a pilot action)
+#             will usually be non-distinct. So an example would be gear/up down
+#             or ATC acknowledgements that all need to be transmitted
 # The IsDistinct is important for any messages that are bridged over MP as
-# only the most recently sent distinct message will be transmitted over MP
+# only the most recently sent distinct message will be transmitted over MP.
+# Example: 
+# position update, where only current position is relevant -> IsDistinct=1; 
+# 0 = queue all messages for MP bridging 
+# 1 = queue only latest message (replace any old message of same type+ident)
+#        
+var TypeIdUnspecified = 1;
 var NotificationAutoTypeId = 1;
 var Notification =
 {
     new: func(_type, _ident, _typeid=0)
     {
-        var new_class = { parents: [Notification]};
-        new_class.Ident = _ident;
-        new_class.NotificationType = _type;
-        new_class.IsDistinct = 1;
-        new_class.FromIncomingBridge = 0;
-        new_class.Callsign = nil;
-
-        new_class.GetBridgeMessageNotificationTypeKey = func {
-            return me.NotificationType~"."~me.Ident;
-        };
-        if (_typeid == 0)
-        {
-            _typeid = NotificationAutoTypeId;
-            NotificationAutoTypeId = NotificationAutoTypeId + 1;
+        if (!isscalar(_type)) {
+            logprint(DEV_ALERT, "Notification.new: _type must be a scalar!");
+            return nil;
         }
-        new_class.TypeId = _typeid;
+        if (!isscalar(_ident)) {
+            logprint(DEV_ALERT, "Notification.new: _ident is not scalar but ", typeof(_ident));
+            return nil;
+        }
+        
+        if (_typeid == 0) {
+            NotificationAutoTypeId += 1;
+            # IDs >= 16 are reserved; see http://wiki.flightgear.org/Emesary_Notifications
+            if (NotificationAutoTypeId == 16) {
+                logprint(LOG_ALERT, "Notification: AutoTypeID limit exceeded: "~NotificationAutoTypeId);
+                return nil;
+            }
+            _typeid = NotificationAutoTypeId;
+        }
+
+        var new_class = { 
+            parents: [Notification],
+            NotificationType: _type,
+            Ident: _ident,
+            IsDistinct: 1,          #1: MP bridge only latest notification 
+            FromIncomingBridge: 0,
+            Callsign: nil,
+            TypeId: _typeid,        # used in MP bridged
+        };
         return new_class;
     },
+    
+    setType: func(_type) {
+        if (!isscalar(_type)) {
+            logprint(DEV_ALERT, "Notification.new: _type must be a scalar!");
+            return nil;
+        }
+        me.NotificationType = _type;
+        return me;
+    },
+    
+    setIdent: func(_ident) {
+        if (!isscalar(_ident)) {
+            logprint(DEV_ALERT, "Notification.new: _ident is not scalar but ", typeof(_ident));
+            return nil;
+        }
+        me.Ident = _ident;
+        return me;
+    },
+    
+    GetBridgeMessageNotificationTypeKey: func {
+        return me.NotificationType~"."~me.Ident;
+    },
 };
 
-# Inherit or implement class with the same signatures to receive messages.
+#---------------------------------------------------------------------------
+# Recipient - base class for receiving notifications.
+#
+# You have to implement the Receive method
+# The Receive method must return a sensible ReceiptStatus_* code
 var Recipient =
 {
     new: func(_ident)
     {
-        var new_class = { parents: [Recipient]};
         if (_ident == nil or _ident == "")
         {
             _ident = id(new_class);
-            print("Emesary Error: Ident required when creating a recipient, defaulting to ",_ident);
+            logprint(LOG_WARN, "Emesary Error: Ident required when creating a recipient, defaulting to ", _ident);
         }
-        Recipient.construct(_ident, new_class);
-    },
-    construct: func(_ident, new_class)
-    {
-        new_class.Ident = _ident;
-        new_class.RecipientActive = 1;
         __emesaryUniqueId += 1;
-        new_class.UniqueId = __emesaryUniqueId;
-        new_class.Receive = func(notification)
-        {
-            # warning if required function not 
-            print("Emesary Error: Receive function not implemented in recipient ",me.Ident);
-            return Transmitter.ReceiptStatus_NotProcessed;
+        var new_class = {
+            parents: [Recipient],
+            Ident: _ident,
+            RecipientActive: 1,
+            UniqueId: __emesaryUniqueId,
         };
         return new_class;
     },
+    
+    Receive: func(notification)
+    {
+        logprint(DEV_ALERT, "Emesary Error: Receive function not implemented in recipient ", me.Ident);
+        return Transmitter.ReceiptStatus_NotProcessed;
+    },
+    
+    setReceive: func(f)
+    {
+        if (isfunc(f)) { me.Receive = f; }
+        else { logprint(DEV_ALERT, "Recipient.addReceive: argument must be a function!"); }
+        return me;
+    },
 };
 
 #
-# Instantiate a Global Transmitter, this is a convenience and a known starting point. Generally most classes will
-# use this transmitters, however other transmitters can be created and merely use the global transmitter to discover each other
+# Instantiate a Global Transmitter, this is a convenience and a known starting point. 
+# Generally most classes will use this transmitters, however other transmitters 
+# can be created and merely use the global transmitter to discover each other.
 var GlobalTransmitter =  Transmitter.new("GlobalTransmitter");
 
 #
 # Base method of transferring all numeric based values.
 # Using the same techinque as base64 - except this is base248 because we can use a much wider range of characters.
-# 
+#
 var BinaryAsciiTransfer = 
 {
-    alphabet : chr(1)~chr(2)~chr(3)~chr(4)~chr(5)~chr(6)~chr(7)~chr(8)~chr(9)~chr(10)~chr(11)~chr(12)~chr(13)
-               ~chr(14)~chr(15)~chr(16)~chr(17)~chr(18)~chr(19)~chr(20)~chr(21)~chr(22)~chr(23)~chr(24)~chr(25)
-               ~chr(26)~chr(27)~chr(28)~chr(29)~chr(30)~chr(31)~chr(34)
-               ~"%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}"
-               ~chr(128)~chr(129)~chr(130)~chr(131)~chr(132)~chr(133)~chr(134)~chr(135)~chr(136)~chr(137)~chr(138)
-               ~chr(139)~chr(140)~chr(141)~chr(142)~chr(143)~chr(144)~chr(145)~chr(146)~chr(147)~chr(148)~chr(149)
-               ~chr(150)~chr(151)~chr(152)~chr(153)~chr(154)~chr(155)~chr(156)~chr(157)~chr(158)~chr(159)~chr(160)
-               ~chr(161)~chr(162)~chr(163)~chr(164)~chr(165)~chr(166)~chr(167)~chr(168)~chr(169)~chr(170)~chr(171)
-               ~chr(172)~chr(173)~chr(174)~chr(175)~chr(176)~chr(177)~chr(178)~chr(179)~chr(180)~chr(181)~chr(182)
-               ~chr(183)~chr(184)~chr(185)~chr(186)~chr(187)~chr(188)~chr(189)~chr(190)~chr(191)~chr(192)~chr(193)
-               ~chr(194)~chr(195)~chr(196)~chr(197)~chr(198)~chr(199)~chr(200)~chr(201)~chr(202)~chr(203)~chr(204)
-               ~chr(205)~chr(206)~chr(207)~chr(208)~chr(209)~chr(210)~chr(211)~chr(212)~chr(213)~chr(214)~chr(215)
-               ~chr(216)~chr(217)~chr(218)~chr(219)~chr(220)~chr(221)~chr(222)~chr(223)~chr(224)~chr(225)~chr(226)
-               ~chr(227)~chr(228)~chr(229)~chr(230)~chr(231)~chr(232)~chr(233)~chr(234)~chr(235)~chr(236)~chr(237)
-               ~chr(238)~chr(239)~chr(240)~chr(241)~chr(242)~chr(243)~chr(244)~chr(245)~chr(246)~chr(247)~chr(248)
-               ~chr(249)~chr(250)~chr(251)~chr(252)~chr(253)~chr(254)~chr(255),
+    #excluded chars 32 (<space>), 33 (!), 35 (#), 36($), 126 (~), 127 (<del>)
+    alphabet : 
+                 chr(1) ~chr(2) ~chr(3) ~chr(4) ~chr(5) ~chr(6) ~chr(7) ~chr(8) ~chr(9)
+        ~chr(10)~chr(11)~chr(12)~chr(13)~chr(14)~chr(15)~chr(16)~chr(17)~chr(18)~chr(19)
+        ~chr(20)~chr(21)~chr(22)~chr(23)~chr(24)~chr(25)~chr(26)~chr(27)~chr(28)~chr(29)
+        ~chr(30)~chr(31)                ~chr(34)
+        ~"%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}"
+            ~chr(128)~chr(129)
+        ~chr(130)~chr(131)~chr(132)~chr(133)~chr(134)~chr(135)~chr(136)~chr(137)~chr(138)~chr(139)
+        ~chr(140)~chr(141)~chr(142)~chr(143)~chr(144)~chr(145)~chr(146)~chr(147)~chr(148)~chr(149)
+        ~chr(150)~chr(151)~chr(152)~chr(153)~chr(154)~chr(155)~chr(156)~chr(157)~chr(158)~chr(159)
+        ~chr(160)~chr(161)~chr(162)~chr(163)~chr(164)~chr(165)~chr(166)~chr(167)~chr(168)~chr(169)
+        ~chr(170)~chr(171)~chr(172)~chr(173)~chr(174)~chr(175)~chr(176)~chr(177)~chr(178)~chr(179)
+        ~chr(180)~chr(181)~chr(182)~chr(183)~chr(184)~chr(185)~chr(186)~chr(187)~chr(188)~chr(189)
+        ~chr(190)~chr(191)~chr(192)~chr(193)~chr(194)~chr(195)~chr(196)~chr(197)~chr(198)~chr(199)
+        ~chr(200)~chr(201)~chr(202)~chr(203)~chr(204)~chr(205)~chr(206)~chr(207)~chr(208)~chr(209)
+        ~chr(210)~chr(211)~chr(212)~chr(213)~chr(214)~chr(215)~chr(216)~chr(217)~chr(218)~chr(219)
+        ~chr(220)~chr(221)~chr(222)~chr(223)~chr(224)~chr(225)~chr(226)~chr(227)~chr(228)~chr(229)
+        ~chr(230)~chr(231)~chr(232)~chr(233)~chr(234)~chr(235)~chr(236)~chr(237)~chr(238)~chr(239)
+        ~chr(240)~chr(241)~chr(242)~chr(243)~chr(244)~chr(245)~chr(246)~chr(247)~chr(248)~chr(249)
+        ~chr(250)~chr(251)~chr(252)~chr(253)~chr(254)~chr(255),
     # base248: powers of 2 (i.e. po2(x) = f(248 ^ x); 
     # 0 based list so the first item is really[1]; i.e. 124 which is 248/2 as po2 is the magnitude excluding sign
     po2: [1, 124, 30752, 7626496, 1891371008, 469060009984, 116326882476032, 28849066854055936], 
@@ -356,7 +468,7 @@ var BinaryAsciiTransfer =
     decodeNumeric : func(str, length, factor, pos)
     {
 		var irange = int(BinaryAsciiTransfer.po2[length]/factor);
-		var power = length - 1;
+        var power = length-1;
         BinaryAsciiTransfer.retval.value = 0;
         BinaryAsciiTransfer.retval.pos = pos;
 
@@ -523,6 +635,61 @@ var TransferCoord =
         return dv;
     }
 };
+
+# genericEmesaryGlobalTransmitterTransmit  allowes to use the emesary.GlobalTransmitter via fgcommand
+# which in turn allows using it in XML bindings, e.g.
+#   <binding>
+#       <command>emesary-transmit</command>
+#       <type>cockpit-switch</type>
+#       <ident>eicas-page-select</ident>
+#       <page>hydraulic</page>
+#   </binding>
+#
+var genericEmesaryGlobalTransmitterTransmit  = func(node)
+{
+    var transmitter = emesary.GlobalTransmitter;
+    var t = node.getNode("transmitter",1).getValue();
+    if (t != nil) {
+        transmitter = emesary.getTransmitter(t);
+        if (transmitter == nil) {
+            logprint(LOG_WARN, "Invalid transmitter "~t);
+            return;
+        }
+    }
+    var type = node.getNode("type").getValue();
+    if (type == nil) {
+        logprint(LOG_WARN, "emesary-transmit requires a type");
+        return;
+    }
+    var ident = node.getNode("ident").getValue();
+    if (ident == nil) {
+        logprint(LOG_WARN, "emesary-transmit requires an ident");
+        return;
+    }    
+    var typeid = node.getNode("typeid",1).getValue() or 0;
+    if (typeid == 0) { 
+        typeid = TypeIdUnspecified;
+        logprint(LOG_WARN, "emesary-transmit using generic typeid ", typeid);
+    }
+    
+    var message = emesary.Notification.new(type, ident, typeid);
+    node.removeChild("type");
+    node.removeChild("id");
+    node.removeChild("typeid");
+
+    # add remaining nodes to the message hash
+    var children = node.getValues();
+    if (children != nil) {
+        foreach (var key; keys(children)) {
+            message[key] = children[key];
+        }
+    }
+    transmitter.NotifyAll(message);
+};
+
+removecommand("emesary-transmit"); #in case of reload
+addcommand("emesary-transmit", genericEmesaryGlobalTransmitterTransmit);
+
 #setprop("/sim/startup/terminal-ansi-colors",0);
 #for(i=-1;i<=1;i+=0.1)
 #print ("i ",i, " --> ", (TransferNorm.decode(TransferNorm.encode(i,2), 2,0)).value);
diff --git a/Nasal/globals.nas b/Nasal/globals.nas
index 895156ecc..64e6922ca 100644
--- a/Nasal/globals.nas
+++ b/Nasal/globals.nas
@@ -41,10 +41,9 @@ var assert = func (condition, message=nil) {
 # (class) object.  Example: isa(someObject, props.Node)
 #
 var isa = func(obj, class) {
-    if(ishash(obj) and obj["parents"] != nil) {
+    if (ishash(obj) and obj["parents"] != nil) {
         foreach(var c; obj.parents) {
-            if(c == class or isa(c, class))
-                return 1;
+            if (c == class or isa(c, class)) return 1;
         }
     }
     return 0;
@@ -58,9 +57,8 @@ var isa = func(obj, class) {
 # tree.
 #
 var fgcommand = func(cmd, node=nil) {
-    if(isa(node, props.Node)) node = node._g;
-    elsif(ishash(node))
-        node = props.Node.new(node)._g;
+    if (isa(node, props.Node)) node = node._g;
+    elsif (ishash(node)) node = props.Node.new(node)._g;
     _fgcommand(cmd, node);
 }
 
@@ -97,8 +95,9 @@ var abs = func(v) { return v < 0 ? -v : v }
 # 0 to wrap the interpolated value properly.
 #
 var interpolate = func(node, val...) {
-    if (isa(node, props.Node)) node = node._g;
-    elsif (!isscalar(node) and !isghost(node))
+    if (isa(node, props.Node)) 
+        node = node._g;
+    elsif (!isscalar(node) and !isghost(node)) 
         die("bad argument to interpolate()");
     _interpolate(node, val);
 }
@@ -189,3 +188,55 @@ settimer(func {
         if(size(file) > 4 and substr(file, -4) == ".nas")
             io.load_nasal(path ~ "/" ~ file, substr(file, 0, size(file) - 4));
 }, 0);
+
+# simple hash class for developers, allows to add callback on write
+Hash = {
+    class_name: "Hash",
+    
+    new: func(name) {
+        var obj = {
+             parents: [me],
+             name: name,
+             _h: {},
+             _callback: func,
+        };    
+        return obj;
+    },
+   
+    set: func (key, value) {
+        me._h[key] = value;
+        me._callback(key, value);
+        return me;
+    },
+    
+    get: func (key) {
+        return me._h[key];
+    },
+   
+    getName: func (key) {
+        return me.name;
+    },
+    
+    getKeys: func () {
+        return keys(me._h);
+    },
+    
+    keys2props: func (p) {
+        if (!isa(p, props.Node)) {
+            p = props.getNode(p,1);
+        }
+        p = p.getNode(me.name,1);
+        foreach (var key; keys(me._h)) {
+            p.getNode(key,1);
+        }
+        return;
+    },
+    
+    # callback for set()
+    addCallback: func (f) {
+        if (isfunc(f)) {
+            me._callback = f;
+        }
+        return me;
+    },
+};
diff --git a/Nasal/notifications.nas b/Nasal/notifications.nas
index 271c876f2..5ff867ad8 100644
--- a/Nasal/notifications.nas
+++ b/Nasal/notifications.nas
@@ -4,7 +4,7 @@
  #
  #	File Type            : Implementation File
  #
- #	Description          : Messages that are applicable across all models and do not specifically relate to a single sysmte
+ #	Description          : Messages that are applicable across all models and do not specifically relate to a single system
  #	                     : - mostly needed when using the mutiplayer bridge
  #
  #	Author               : Richard Harrison (richard@zaretto.com)
@@ -27,6 +27,7 @@ var AircraftControlNotification_Id = 17;
 var GeoEventNotification_Id = 18;
 # event ID 19 reserved for armaments and stores (model defined).
 var PFDEventNotification_Id = 20;
+var ArmamentInFlightNotification = 21;
 
 #
 # PropertySyncNotificationBase is a wrapper class for allow properties to be synchronized between
diff --git a/defaults.xml b/defaults.xml
index e4a9b33f4..87b79325a 100644
--- a/defaults.xml
+++ b/defaults.xml
@@ -1383,6 +1383,9 @@ Started September 2000 by David Megginson, david@megginson.com
     <console>
       <enabled type="bool">true</enabled>
     </console>
+    <debug>
+      <enabled type="bool">false</enabled>
+    </debug>
     <input_helpers>
       <enabled type="bool">true</enabled>
     </input_helpers>