|
From: Richard H. <rj...@za...> - 2017-06-14 15:24:02
|
I've nearly finished my improvements to Emesary to make it easy and seamless to transmit properties over MP instead of the of the usual way. This is a two part set of changes, the first part (complete) is to transmit from the master model, the second part is still WIP and relates to the transmission back for dual control. On 13/06/2017 22:03, jsb wrote: > What is Emesary? At the highest level Emesary is a way of communicating information between objects that are otherwise unrelated and possibly separated by a physical (machine, network, process) boundary. http://chateau-logic.com/content/emesary-nasal-implementation-flightgear Two (or more) systems can be connected together by using a bridge; the bridge that I've implemented uses the generic string properties to transmit the messages transparently (to both the sender and recipient). http://chateau-logic.com/content/emesary-multiplayer-bridge-flightgear (documentation is possibly slightly out of date for the most recent developments that are in my fgdata) I've got the transmission of properties working ; using a new notification type. Usage example - this can all go into one Nasal module somewhere. ----------- var PropertySyncNotification = { new: func(_ident="none", _name="", _kind=0, _secondary_kind=0) { var new_class = PropertySyncNotificationBase.new(_ident, _name, _kind, _secondary_kind); new_class.addIntProperty("consumables/fuel/total-fuel-lbs", 1); new_class.addIntProperty("controls/fuel/dump-valve", 1); new_class.addIntProperty("engines/engine[0]/augmentation-burner", 1); new_class.addIntProperty("engines/engine[0]/n1", 1); new_class.addIntProperty("engines/engine[0]/n2", 1); new_class.addNormProperty("surface-positions/wing-pos-norm", 2); #... etc ... return new_class; } }; # # this section sets up the notifications that will be routed and the transmitters that are used # I've separated out the transmitter that will be used to send the properties to enable better control. var routedNotifications = [notifications.PropertySyncNotification.new(nil), notifications.GeoEventNotification.new(nil)]; var bridgedTransmitter = emesary.Transmitter.new("outgoingBridge"); var outgoingBridge = emesary_mp_bridge.OutgoingMPBridge.new("F-14mp",routedNotifications, 19, "", bridgedTransmitter); var incomingBridge = emesary_mp_bridge.IncomingMPBridge.startMPBridge(routedNotifications); var f14_aircraft_notification = notifications.PropertySyncNotification.new("F-14"~getprop("/sim/multiplay/callsign")); ----------- That's all that is required to ship properties between multiplayer modules via emesary. There is a limit of 128 bytes on a string which limits the amount of outgoing messages. Outgoing notifications are queued and transmitted as space permits. The way the bridge works is to publish the notification, encoded into an MP string, for a period of time to allow for lagging clients and network issues. If a notification IsDistinct then the bridge will transfer just the last message received; otherwise the bridge will transfer all received notifications over MP, to allow for In this sense IsDistinct indicates that the contents of the notification are accurate and definitive (e.g. surface position), so the last value is the most accurate. Other notification (e.g. button 12 pushed will always need to be transferred). Obviously using this technique a variable number of properties can be transmitted, and importantly it's up to the modeller to decide what to transmit. There is a flag that I've temporarily added (sim/multiplay/transmit-only-generics) that doesn't transmit the standard properties, just chat and the generics (to make more space in the packet). There can be different types of notifications sent at a different schedule (so you could have a 10 second update of very slow moving items). --------------- What I'm working on now is how to make (possibly multiple) slaves communicate back to a master craft, initially the F-14 backseat. The design goal is that the same code should work for both the master and the slave, and that there should not need to be any extra logic. At the highest level this would be (master craft): 1. Inside the model bindings a notification is raised, or a property changed that will cause a notification to be raised. 2. The model receives the notification and the appropriate property is changed. 3. The property changed will be sent over Emesary to all slaves. Slaves will not transmit this data back to the master as there is no outgoing bridge configured to do this. For the slave aircraft 1. Inside the model bindings a notification is raised, or a property changed that will cause a notification to be raised. 2. The notification is bridged over MP and received by the master craft. What I'm hoping to have is something that will require a reasonably straightforwards way to do this; something like the following. <action> <binding> <command>property-adjust</command> <property>instrumentation/altimeter/setting-inhg-demand</property> <factor>0.01</factor> <min>27.90</min> <max>31.40</max> <wrap>false</wrap> </binding> <binding> <command>nasal</command> <script>f14.notify(f14.altimeter_setting_inhg, "instrumentation/altimeter/setting-inhg-demand")</script> </binding> </action> in a Nasal module somewhere: var aircraftControlEventNotification = AircraftControlNotification.new("s2m"); notify = func(id, prop){ # print("Notify ",id," ",prop," ",getprop(prop)); aircraftControlEventNotification.eventType = id; aircraftControlEventNotification.eventValue = getprop(prop); emesary.GlobalTransmitter.NotifyAll(slaveToMasterEventNotification); } var aircraftControlRecipient = emesary.Recipient.new("aircraftControl"); emesary.GlobalTransmitter.Register(aircraftControlRecipient); aircraftControlRecipient.Receive = func(notification) { if (notification.NotificationType == "AircraftControlNotification") { if (notification.eventType == altimeter_setting_inhg) setprop("instrumentation/altimeter/setting-inhg", notification.eventValue); return emesary.Transmitter.ReceiptStatus_Ok; } return emesary.Transmitter.ReceiptStatus_NotProcessed; # we're not processing it, just looking } So the code above will work in both the master and the slave, the difference is that the slave has an outgoing bridge attached to the global transmitter that will transmit the AircraftControlNotification to the master craft. The code for this is in my fgdata branch; and the modified F-14 that uses Emesary instead of the usual approach is available on the https://github.com/Zaretto/fg-aircraft/tree/EmesaryMP-dev-F14 The TLDR version is that this technique reduces the F-14 from nearly 1100 byte packets to around 360, out of which around 60 bytes are the most of the properties required (and that were previously transmitted) Careful consideration will need to be given to other clients, as they will need to be able to decode notifications to be able to work in this way. |