Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TC-1 Merge the Data Capture and Demo Application Repositories #7

Merged
merged 54 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
ac98e61
Initial commit
davewalker5 Jan 21, 2020
e83b847
Initial commit
davewalker5 Jan 22, 2020
e4fb747
First version created
davewalker5 Jan 22, 2020
8909c58
Created the README from the TelloCommander README
davewalker5 Jan 22, 2020
3edd98a
Added CI build
davewalker5 Jan 22, 2020
54bd752
Fixup incorrect solution file name
davewalker5 Jan 22, 2020
2855e4d
Fixup .NET code version
davewalker5 Jan 22, 2020
0f09eff
Added build instructions
davewalker5 Jan 22, 2020
525c7bb
Replace API with "application" in the connection details
davewalker5 Jan 22, 2020
34ad9a6
First version
davewalker5 Jan 22, 2020
623ec3c
NuGet packaging for first release
davewalker5 Jan 22, 2020
7e040c3
NuGet packaging for first release
davewalker5 Jan 22, 2020
9916f29
Added README
davewalker5 Jan 22, 2020
dc3ddbd
Fix build issue
davewalker5 Jan 22, 2020
76c64f8
Fix build issue
davewalker5 Jan 22, 2020
260654d
Implement the command line library
davewalker5 Jan 22, 2020
540b4c5
Reorganised project structure
davewalker5 Jan 22, 2020
ad72157
Tidying up prior to publication
davewalker5 Jan 22, 2020
91769b7
NuGet packaging for 1.0.0.5 release
davewalker5 Jan 23, 2020
ffb62bd
NuGet packaging for 1.0.0.5 release
davewalker5 Jan 23, 2020
a254722
Merge pull request #1 from davewalker5/command-line-library
davewalker5 Jan 23, 2020
a886814
Create dotnetcore.yml
davewalker5 Jan 23, 2020
eacf9c4
Remove redundant file
davewalker5 Jan 23, 2020
4a1b012
Added details on DB capture commands
davewalker5 Jan 23, 2020
a0cff93
Added DB capture command details
davewalker5 Jan 23, 2020
906c1a1
Update README.md
davewalker5 Jan 23, 2020
5ae6d6d
Update README.md
davewalker5 Jan 23, 2020
d4162f5
Test coverage improvements
davewalker5 Jan 24, 2020
91b00c5
Update README.md
davewalker5 Jan 24, 2020
340b2ef
Update README.md
davewalker5 Jan 24, 2020
e8352f7
Update README.md
davewalker5 Feb 10, 2020
558a5f8
Update README.md
davewalker5 Feb 10, 2020
c65875c
Updgraded to .NET Core 3.1
Mar 20, 2020
e508cdf
Merge pull request #1 from davewalker5/dotnet-core-3.1
davewalker5 Mar 20, 2020
113d17a
Updated dependencies
davewalker5 Oct 2, 2021
c1755c7
Merge pull request #2 from davewalker5/update-dependencies
davewalker5 Oct 2, 2021
d379401
Updated dependencies
davewalker5 Oct 2, 2021
c94ce74
Merge pull request #2 from davewalker5/update-dependencies
davewalker5 Oct 2, 2021
e5a1e8f
Remove Trello link from README
davewalker5 Apr 10, 2023
d306174
Remove Trello link from README
davewalker5 Apr 10, 2023
8b3086e
Target .NET 6.0 ; Update NuGet references
davewalker5 Apr 11, 2023
6c2edc5
Update dotnetcore.yml
davewalker5 Apr 11, 2023
40f26ac
Merge pull request #3 from davewalker5/target-update
davewalker5 Apr 11, 2023
fc4d727
Target .NET 6.0 ; Update NuGet references
davewalker5 Apr 11, 2023
9040cd8
Update dotnetcore.yml
davewalker5 Apr 11, 2023
cb817a9
Merge pull request #3 from davewalker5/target-update
davewalker5 Apr 11, 2023
942e4a6
Merge data/database repository
davewalker5 Dec 21, 2023
b5fa3b0
Update dotnetcore.yml
davewalker5 Dec 21, 2023
7a60775
Added info on the data capture capabilities to the README
davewalker5 Dec 21, 2023
f1c0e19
Added info on the data capture capabilities to the README
davewalker5 Dec 21, 2023
d0c480d
Added info on the data capture capabilities to the README
davewalker5 Dec 21, 2023
65d25ad
Merge TelloCommanderConsole demo application repository
davewalker5 Dec 21, 2023
25ff5f3
Added repo merge note to the README
davewalker5 Dec 21, 2023
87221f0
Added repo merge note to the README
davewalker5 Dec 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions .github/workflows/dotnetcore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ on: [push]

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 6.0.310
- name: Build
run: dotnet build --configuration Release src/TelloCommander.sln
- name: Run unit tests and generate code coverage
run: dotnet test src/TelloCommander.sln /p:CollectCoverage=true /p:CoverletOutput=coverage/ /p:CoverletOutputFormat=lcov
- name: Generage Coveralls code coverage
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: src/TelloCommander.Tests/coverage/coverage.info
- uses: actions/checkout@v1
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: "7.0.302"
include-prerelease: true
- name: Build
run: dotnet build --configuration Release src/TelloCommander.sln
- name: Run unit tests and generate code coverage
run: dotnet test src/TelloCommander.sln /p:CollectCoverage=true /p:CoverletOutput=coverage/ /p:CoverletOutputFormat=lcov
- name: Generage Coveralls code coverage
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: src/TelloCommander.Tests/coverage/coverage.info
34 changes: 17 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# TelloCommander

[![Build Status](https://github.com/davewalker5/TelloCommander/workflows/.NET%20Core%20CI%20Build/badge.svg)](https://github.com/davewalker5/TelloCommander/actions)
[![GitHub issues](https://img.shields.io/github/issues/davewalker5/TelloCommander)](https://github.com/davewalker5/TelloCommander/issues)
[![Coverage Status](https://coveralls.io/repos/github/davewalker5/TelloCommander/badge.svg?branch=master)](https://coveralls.io/github/davewalker5/TelloCommander?branch=master)
Expand All @@ -9,6 +9,8 @@
[![Language](https://img.shields.io/badge/language-c%23-blue.svg)](https://github.com/davewalker5/TelloCommander/)
[![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/davewalker5/TelloCommander)](https://github.com/davewalker5/TelloCommander/)

> **_NOTE:_** The separate Tello Commander Database and demo application repositories have been merged with the TelloCommander repository. The intention is to update the README and the Wiki to provide further guidance on the merged repository structure

## About

Tello Commander is a C# API for controlling a Tello drone, offering the following features:
Expand All @@ -22,24 +24,22 @@ Tello Commander is a C# API for controlling a Tello drone, offering the followin
- Capture of drone telemetry information to CSV
- Capture of drone telemetry to a SQL database

## Version 1.0.0.5
The following database types are supported:

Release 1.0.0.5 of TelloCommander introduces the ability to stream drone telemetry to a SQL database for subsequent analysis and splits the project into the following repos/libraries/NuGet packages:
| Type | Purpose |
| --------- | -------------------------------------------------------------------------------- |
| In Memory | In-memory database for transient storage and primarily targetted at unit testing |
| SQLite | Permanent storage in a SQLite database |

| Repo | NuGet Package | Purpose |
| --- | --- | --- |
| [TelloCommander](https://github.com/davewalker5/TelloCommander/) | [TelloCommander](https://www.nuget.org/packages/TelloCommander/) | Core Tello control API |
| [TelloCommanderDb](https://github.com/davewalker5/TelloCommanderDb/) | [TelloCommander.Data](https://www.nuget.org/packages/TelloCommander.Data/) | Core SQL telemetry capture API |
| [TelloCommanderDb](https://github.com/davewalker5/TelloCommanderDb/) | [TelloCommander.Data.InMemory](https://www.nuget.org/packages/TelloCommander.Data.InMemory/) | EF Core database context for capturing telemetry to an in-memory database |
| [TelloCommanderDb](https://github.com/davewalker5/TelloCommanderDb/) | [TelloCommander.Data.Sqlite](https://www.nuget.org/packages/TelloCommander.Data.Sqlite/) | EF Core database context for capturing telemetry to a SQLite database |
| [TelloCommanderConsole](https://github.com/davewalker5/TelloCommanderConsole) | [TelloCommander.CommandLine](https://www.nuget.org/packages/TelloCommander.CommandLine/) | Basis for a command-line controller for the Tello with example application |
A demonstration console application is provided to demonstrate use of the API to connect to and communicate with a drone. It provides the following connection types:

Release 1.0.0.5 also changed the location of the following classes and, with it, the repo/library/NuGet package that they reside in:
| Type | Purpose |
| --------- | ------------------------------------------------------------------------------------- |
| Mock | Uses a mock that simulates responses from the drone without establishing a connection |
| Simulator | The application is connected to the simulator, running on the same machine |
| Drone | The application is connected to a real drone |

| Class | Original Namespace | New Namespace |
| --- | --- | --- |
| ConsoleCommander | TelloCommander.Commander | TelloCommander.CommandLine |
| ConsoleCommanderWrapper | TelloCommander.Commander | TelloCommander.CommandLine |
It is based on the ConsoleCommander class provided by the API.

## Getting Started

Expand Down Expand Up @@ -89,7 +89,7 @@ while (!isEmpty);
commander.Disconnect();
```

The argument passed to the "ReadStandardDictionary" is the Tello API version number and defines the set of available commands (see the [wiki](https://github.com/davewalker5/TelloCommander/wiki/Home)) for more details.
The argument passed to the "ReadStandardDictionary" is the Tello API version number and defines the set of available commands (see the [wiki](https://github.com/davewalker5/TelloCommander/wiki/Home)) for more details.

The following is example output for a simple takeoff, height query and landing:

Expand All @@ -111,7 +111,7 @@ More complete information on the capabilities and use of the API are provided in

## Authors

- **Dave Walker** - *Initial work* - [LinkedIn](https://www.linkedin.com/in/davewalker5/)
- **Dave Walker** - _Initial work_ - [LinkedIn](https://www.linkedin.com/in/davewalker5/)

## Feedback

Expand Down
144 changes: 144 additions & 0 deletions src/TelloCommander.CommandLine/ConsoleCommander.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
using System;
using System.Diagnostics.CodeAnalysis;
using TelloCommander.CommandDictionaries;
using TelloCommander.Commander;
using TelloCommander.Data.Collector;
using TelloCommander.Data.Sqlite;
using TelloCommander.Interfaces;
using TelloCommander.Status;

namespace TelloCommander.CommandLine
{
[ExcludeFromCodeCoverage]
public class ConsoleCommander : DroneCommander
{
private readonly DroneStatusMonitor _monitor = new();

public ConsoleCommander(ITelloConnection connection, CommandDictionary dictionary) : base(connection, dictionary)
{
}

/// <summary>
/// Connect to the drone then repeatedly prompt for and send commands
/// </summary>
/// <param name="enableStatusMonitor"></param>
public void Run(bool enableStatusMonitor = true)
{
char[] separators = { ' ' };
TelemetryCollector collector = null;
TelloCommanderDbContext context = null;

try
{
Connect();

if (enableStatusMonitor)
{
_monitor.Listen(DroneStatusMonitor.DefaultTelloStatusPort);
}

Console.WriteLine();
Console.WriteLine("You are connected to the Tello in API mode");

bool haveCommand;
do
{
Console.WriteLine();
Console.Write("Enter command or hit ENTER to quit : ");
string command = Console.ReadLine();

haveCommand = !string.IsNullOrEmpty(command);
if (haveCommand)
{
Console.WriteLine($"Command : {command}");

try
{
string[] words = command.Trim().Split(separators, StringSplitOptions.RemoveEmptyEntries);
switch (words[0])
{
case "?":
ReportDroneStatus();
LastResponse = "ok";
break;
case "startcapture":
_ = int.TryParse(words[2], out int intervalMilliseconds);
_monitor.StartCapture(words[1], intervalMilliseconds);
LastResponse = "ok";
break;
case "stopcapture":
_monitor.StopCapture();
LastResponse = "ok";
break;
case "startdbcapture":
_ = int.TryParse(words[3], out int collectionInterval);
string[] filters = (words.Length > 4) ? words[4].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) : null;
context = new TelloCommanderDbContextFactory().CreateDbContext(null);
collector = new TelemetryCollector(context, _monitor);
collector.Start(words[1], words[2], collectionInterval, filters);
LastResponse = "ok";
break;
case "stopdbcapture":
if (collector != null)
{
collector.Stop();
context.Dispose();
collector = null;
}
LastResponse = "ok";
break;
default:
RunCommand(command);
break;
}

Console.WriteLine($"Response: {LastResponse}");
}
catch (Exception ex)
{
Console.WriteLine($"Error : {ex.Message}");
}
}
}
while (haveCommand);

_monitor.Stop();
Disconnect();
}
catch (Exception ex)
{
Console.WriteLine($"Error Connecting: {ex.Message}");
}
}

/// <summary>
/// Report the current status of the drone
/// </summary>
private void ReportDroneStatus()
{
Console.WriteLine($"{DateTime.Now:hh:mm:ss.fff} Status : {_monitor.Status}");
if (!string.IsNullOrEmpty(_monitor.Error))
{
Console.WriteLine($"{DateTime.Now:hh:mm:ss.fff} Error : {_monitor.Error}");
}
else if (!string.IsNullOrEmpty(_monitor.Status))
{
// If there's no error and the status has a value, it's been successfully read and
// the public properties on the monitor will be populated. The sequence number is
// incremented every time the status is read from the drone. If it stops increasing
// for any length of time, then either the monitor has stopped or the drone has
// stopped broadcasting its status
Console.WriteLine($"{DateTime.Now:hh:mm:ss.fff} Sequence : {_monitor.Sequence}");
Console.WriteLine($"{DateTime.Now:hh:mm:ss.fff} Attitude : {_monitor.Attitude}");
Console.WriteLine($"{DateTime.Now:hh:mm:ss.fff} Speed : {_monitor.Speed}");
Console.WriteLine($"{DateTime.Now:hh:mm:ss.fff} Temperature : {_monitor.Temperature}");
Console.WriteLine($"{DateTime.Now:hh:mm:ss.fff} TOF : {_monitor.TOF}");
Console.WriteLine($"{DateTime.Now:hh:mm:ss.fff} Height : {_monitor.Height}");
Console.WriteLine($"{DateTime.Now:hh:mm:ss.fff} Battery : {_monitor.Battery}");
Console.WriteLine($"{DateTime.Now:hh:mm:ss.fff} Barometer : {_monitor.Barometer}");
Console.WriteLine($"{DateTime.Now:hh:mm:ss.fff} Time : {_monitor.Time}");
Console.WriteLine($"{DateTime.Now:hh:mm:ss.fff} Acceleration : {_monitor.Acceleration}");
}
}
}
}
121 changes: 121 additions & 0 deletions src/TelloCommander.CommandLine/ConsoleCommanderWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using TelloCommander.CommandDictionaries;
using TelloCommander.Commander;
using TelloCommander.Connections;
using TelloCommander.Interfaces;

namespace TelloCommander.CommandLine
{
[ExcludeFromCodeCoverage]
public class ConsoleCommanderWrapper
{
/// <summary>
/// Prompt for the data necessary to create the console commander,
/// create it and run it
/// </summary>
public void Run()
{
Console.WriteLine($"Tello Commander {DroneCommander.Version}");

string version = PromptForDictionaryVersion();
if (!string.IsNullOrEmpty(version))
{
ConnectionType connectionType = PromptForConnectionType();
if (connectionType != ConnectionType.None)
{
CommandDictionary dictionary = CommandDictionary.ReadStandardDictionary(version);
switch (connectionType)
{
case ConnectionType.Mock:
ITelloConnection mockConnection = new MockTelloConnection(dictionary);
new ConsoleCommander(mockConnection, dictionary).Run(false);
break;
case ConnectionType.Simulator:
ITelloConnection connection = new TelloConnection(IPAddress.Loopback.ToString(), TelloConnection.DefaultTelloPort, connectionType);
new ConsoleCommander(connection, dictionary).Run(true);
break;
case ConnectionType.Drone:
new ConsoleCommander(new TelloConnection(), dictionary).Run(true);
break;
default:
break;
}

}
}
}

/// <summary>
/// Prompt the user for an option from a numbered list
/// </summary>
/// <returns></returns>
private static int PromptForOption(string title, string[] options)
{
Console.WriteLine();
Console.WriteLine(title);
Console.WriteLine();

for (int i = 0; i < options.Length; i++)
{
Console.WriteLine($"[{i + 1}] {options[i]}");
}

Console.WriteLine();

int option;
do
{
Console.Write($"Please enter your option between 1 and {options.Length} or enter 0 to quit: ");
string input = Console.ReadLine();
_ = int.TryParse(input, out option);
}
while ((option < 0) || (option > options.Length));

return option;
}

/// <summary>
/// Prompt for and return the API (dictionary) version to use
/// </summary>
/// <returns></returns>
private static string PromptForDictionaryVersion()
{
string[] versions = CommandDictionary.GetAvailableDictionaryVersions();
string version = null;

if (versions.Length == 1)
{
version = versions[0];
Console.WriteLine($"Using dictionary version {version}");
}
else
{
int selection = PromptForOption("Dictionary Version:", versions);
if (selection > 0)
{
version = versions[selection - 1];
}
}

return version;
}

/// <summary>
/// Prompt for the type of connection to use
/// </summary>
/// <returns></returns>
private static ConnectionType PromptForConnectionType()
{
int connectionType = PromptForOption("Connection:", new string[]
{
"Mock connection",
"Simulator connection",
"Real connection"
});

return (ConnectionType)connectionType;
}
}
}
Loading
Loading