Giter Site home page Giter Site logo

tigra-astronomy / ta.reactivecommunications Goto Github PK

View Code? Open in Web Editor NEW
2.0 2.0 7.0 4.91 MB

A thread-safe transactional communications methodology for ASCOM drivers

Home Page: http://tigra-astronomy.com/reactive-communications-for-ascom

License: Other

PowerShell 0.35% C# 99.65%
ascom ascom-driver communication communications communication-library reactive-programming reactive-extensions

ta.reactivecommunications's People

Contributors

kyleworley avatar nameofthedragon avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

ta.reactivecommunications's Issues

Transactions that time out should be marked as Failed

Currently, transactions that time out are not marked as Failed. This should be the case, and the ErrorMessage property should contain text like "Timed out".

Originally created at 27/01/2017 21:22:38 by Tim Long as a bug with severity minor.

Bluetooth?

Hi Tim,

I am currently working on a small project to allow a mobile phone to be used to control some aspects of an ASCOM telescope driver. I have basic Rfcomm working between a Xamarin Forms Android app and a WPF Windows 10 desktop application in a test project using the 32Feet library for InTheHand. My next step is to make the communications asynchronous and two way. When a bluetooth connection is made it contains two streams (send and receive). What I am thinking of doing is attempting to extend the ReactiveCommunications library to wrap the bluetooth channel. Before I start, I thought I would ask if you believe this would be possible or would I be wasting my time.

Thanks,

Phil

Asynchronous transactions

Enhance the DeviceTransaction class with a new method WaitForCompletionAsync.

This will allow asynchronous execution of code after the transaction has completed.

Originally created at 28/01/2017 00:06:14 by Tim Long as a enhancement with severity major.

Break dependency on NLog

Its not great to have dependencies on too many third party libraries. We can't help but depend on System.Reactive, as that's the whole point, but we probably shouldn't depend on NLog.

Suggested strategy

  1. Introduce an ILoggingService interface.
  2. Inject the logging service as a constructor parameter were needed.
  3. Make a degenerate implementation that does nothing, and make that the default.
  4. Remove dependency on NLog.
  5. Create a separate project/assembly/nuget package and Implement the interface as NLogLoggingService.

This may be a breaking change unless we can overload all the required constructors.

Use of Serial Communications

Based on Tim's video's there are a couple of ways to use Reactive coms to establish serial communications. This isn't an issue but rather an interpretation of how to manage a serial communication link.

Reactive Comms is an evolutionally library where there is more than one way to establish communications with serial devices. I wrote this stuff out as I worked through the video examples to understand what the action steps were.

The latest approach I see in the sample videos is using the Factory Channel Method. The following is what I have used to develop a test program to link up the reactive comms in a test program before developing my program.

//in order to create a connection you need
//step 1 is a communications string connectionString = the parameters to configure the factory //instance for serial port this would be com port configuration example
string connectionString= "Com7:9600,None,8,one,NoDTR,NoRTS"

//step 2 need to create a new factory instance using var factory = new ChannelFactory();
// the factory becomes the methodology to hold or create the data link.
var factory = new ChannelFactory();

//step 3. create a channel for the data comm connection will be established where
channel = factory.FromConnectionString(conectionString);
//the FromConnectionString parameter is passed the connectionString for the configuration.

//The older or other method was to use an endpoint for step 3 as the following
var endpoint = DeviceEndpoint.FromConnectionString("Com1");
// or the entry was the connectionString variable.
//Then the channel for step 3 would be created using an Icommunications Interface using
IcommunicationsChannel channel= new SerialCommunicationsChannel(endpoint)

//Step 4 At this point the Serial port is all wired to be opened
//Either approach works At this stage the channel is available to be opened.
//However this step can be completed later in the activity code and not the prep code.
channel.open();

//Step 5 create the observer
// After the channel is created you need a transaction observer
// if you have a sequence of data , which are called observables(t)
// so if you had a string it would Iobservable(string)
// then you have observer which subscribe to those observable strings
// the transaction observer is the observer mechanism

        var observer = new TransactionObserver(channel);  // need to identify what to watch so pass in channel

//Step 6 create the processor and link the processor to the observer
// Observer is going to view data from this specific channel
// this could be all that is needed to just observe data
// but now you might need to manage a sequence of transaction such as Trans 1, 2,3....n
// you then need a processor to manage the sequence of transactions called a processor.
var processor = new ReactiveTransactionProcessor(); // this defines the processor
processor.SubscribeTransactionObserver(observer); // this links the process to the observer

// Step 7 now to use a transaction to interact with the observer
// If using a terminates string we use
// TerminatedStringTransaction("string command") there are different overrides
// TerminatedStringTransaction("string command", initiator: 'startChar', terminator: 'endChar' )
var transaction = new TerminatedStringTransaction("", initiator: '$', terminator: 'z') { Timeout = TimeSpan.FromSeconds(20) };

//In this instance command to issue out the serial port is "" of blank because this example is using
//a free running time based status packet. So there is no command to issue.
//The timeout just allow the use of the timeout property of the transaction processor
// At this stage the transaction is created

//It is at this stage that a person could create a custom transaction method to handle a different way of managing the data so the var transaction stated would change to

           var transaction = new MySerialTransaction("mycommand"){ Timeout = TimeSpan.FromSeconds(10) }

//where there is a method MySerialTransaction( string command) in your class

// step 8 commit the transaction to the processor
// now we need to process the data that was received by the transaction
// so the transaction would send the command string and wait for the responding date
// so we need to use processor to commit the transaction by passing the trasaction into the processor

            processor.CommitTransaction(transaction);
            transaction.WaitForCompletionOrTimeout(); 
           // this specified to have the transaction wait for period of time or fail

step 9 wait for the response and process the response. use the transaction.Successful and .Response parameters to validate the responses.

           if (transaction.Successful && transaction.Response.Any())
            {
                var response = transaction.Response.Single();
                log.Info($"the responses is", response);  //using an Nlog info capability and ready for any required parsing capabilities
             }

Todd Benko

Support .NET Frameworks prior to 4.7.1

It is not possible to install the NUGET packages with a version greater than 1.0.0 on projects targeting anything less than .NET Framework 4.7.1.

I think the underlying problem may be related to the dependence on System.Reactive. This also seems to have an issue installing on earlier .NET Framework versions.

Originally created at 09/01/2019 13:42:31 by Phil Crompton as a enhancement with severity major.

Additional Channel inputs

I am working on a project which receives a serial input of weather station status packets. This is of course using the reactive comms as the serial interface reading a timed output status packet every 5 seconds.

The project to receive the data is basically straight forward from the reactive comm perspective. What I would like to do though is to take my input data and relay it out to be used by the same driver as in input from say a dropbox file or a network connection. So the if the driver is connected to actual sensor by serial I then want to relay the data out so the same driver can share the status packet to other instances where those drivers would use either a network file like dropbox file as the channel input or a network connection as a channel input and basically receive the data the similar to the data from the sensor.

For the file, I envision at first using a network shared drive but later came to realize a dropbox file would make it easier to share for those outside of the immediate network.. Say a cluster of observatories could use the one weather sensor.

For the network connection, I had origianally been thinking of using the broadcast address where I would broadcast the data from the sensor in the same manner as soon as it was received from the serial port. So I would then just create a network channel and all the processor/transaction activity would remain unchanged in the secondary instances of the driver. However I then thought maybe this would be additional uncessary traffic on all network IP's using the broadcast address. Maybe what should happen is the host instance with the serial device would setup a UDP transponder which would wait for a request on a given port and only respond to secondary instances. So then secondary instances would have their input set as a UDP channel which would then send a command to the host instance and wait for the response. Hence only the channel connection again would change and the command string of the transaction would change.

Any idea as to configuring the channel for a host file channel input and a UDP network file as the input source to the Reactive Comms link.

Any if it should be UDP or a more robust TCP/IP channel?

Todd

Convert to .NET Standard 2.0

Convert the library to target .NET Standard 2.0 as a first step on the journey to .NET Core.

NetStandard2.0 is compatible with .NET Framework applications up to NetFX 4.8, so all currently existing .NET Framework applications and drivers will continue to work.

NetStandard 2.1 may not be backwared compatible with .NET Framework apps, so that is not an option at the moment. However, Microsoft is developing UI technology for .Net Core, there will be no more versions of the .NET Framework (.NET 5.0 will be .NET Core only) and the ASCOM team is working on .NET Core compatibility, so in due course we see all ASCOM drivers migrating to .NET Core and Alpaca. It is therefore essential that we are able to support .NET Core. The backward compatibility requirements for ASCOM pretty much mean that all ASCOM drivers will have to be out-of-process COM LocalServers or Alpaca network servers.

DeviceTransaction.WaitForCompletionOrTimeout() can time out too soon when called from a client application

The timeout for a transaction should run from the moment it's command is sent, not from when the client app calls WaitForCompletionOrTimeout().

The transaction observer calls this method internally and will produce the correct result. The client app can also call the method but then may receive a timeout before the transaction even reaches the front of the queue. This can result in the application receiving timeouts for transactions that then go on to succeed. The effect can be particularly problematic with protocols that have transactions with long response times.

Originally created at 27/01/2017 21:19:19 by Tim Long as a bug with severity major.

Serial Device Endpoint parameter summary

Tim you should add this to the summary text of these parameters for the next time you update the library

public SerialDeviceEndpoint(string portName: [int baudRate = 9600], [System.IO.Ports.Parity parity = 0], [int dataBits = 8], [System.IO.Ports.StopBits stopBits = 1], [bool dtrEnable = True], [bool rtsEnable = True], [System.IO.Ports.Handshake handshake = 0])

Parameters:

portName: Name of the port, COMx where x is an integer.
baudRate: The baud rate. Optional; default is 9600.
parity: The parity bit type. Optional; default is System.IO.Ports.Parity.None.
dataBits: The number of data bits. Optional; default is 8.
stopBits: The number stop bits. Optional; default is 1.
dtrEnable: Indicates whether the DTR signal should be asserted or negated. Optional; default is true.
rtsEnable: Indicates whether the RTS signal should be asserted or negated. Optional; default is true
handshake: The serial handshake method (default: None)

Note what is not stated is what will dtrEnable and rtsEnable take as valid strings. Tim you should add this to the summary text of these parameters for the next time you update the library

dtrEnable accepts DTR or NoDTR
rtsEnable accepts RTS or NoRTS
These are the only ones which I was able to discern it does not take !DTR or !RTS or NDTR or NRTS which are common negated indicators

I'm not sure what is acceptable Handshake strings for the different types of handshake methods

You also identified there was a bug related to this
Normally you could figure out what a connection string looks like by creating and endpoint manually, passing in all the parameter values in the contructor, then printint the created object. The ToString method should then print out the exact connection string you'd need to store in your settings to recreate that configuration in the future. However, the DTR and RTS parameters have been omitted from SerialDeviceEndpoint, so that's a formatting bug.

Use ASCII expansions in diagnostic output

It's a small thing, but non-printing and whitespace characters tend to mess up diagnostic output. For example:

100 21:17:33.5438 DEBUG ObservableDiagnosticExtensions Serial Receive[1]: OnNext()
101 21:17:33.5438 DEBUG ObservableDiagnosticExtensions Serial Receive[1]: OnNext(
102 )   
103 21:17:33.5598 DEBUG ObservableDiagnosticExtensions SemVer[1]: OnNext(3.4.0-auto-close.6
104 )   
105 21:17:33.5598 DEBUG ObservableDiagnosticExtensions SemVer[1]: Dispose()
106 21:17:33.5598 INFO TransactionObserver Transaction 1 completed

In other places, ASCII expansion is already being used, for example this line is a mix of outcomes:

108 21:17:33.5598 INFO TransactionObserver Completed transaction TID=1 [@FRR<CR><LF>] [3.4.0-auto-close.6
109 ] 00:00:10 Completed

So the requirement is to be more consistent wherever diagnostic output is produced and always use ASCII expansion for non-printing and whitespace characters.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.