1
0
Fork 0

emesary.nas add comments, type checks; fix typos; add debug/emesary.deb.nas add fgcommand to use the global transmitter

This commit is contained in:
Henning Stahlke 2020-06-29 10:49:18 +02:00 committed by James Turner
parent 8d785cacbc
commit a13f9b3bb0
5 changed files with 373 additions and 101 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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;
},
};

View file

@ -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

View file

@ -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>