private static async Task TestCase1_TachoMotorPositionByDegreesAsync(TestScriptExecutionContext context, TTechnicMotor motor) { context.Log.LogInformation("TachoMotor: Testing positioning by degress"); await motor.StartSpeedForDegreesAsync(45, 10, 100); await Task.Delay(2000); context.Assert(motor.AbsolutePosition, 42, 48); context.Assert(motor.Position, 42, 48); await motor.StartSpeedForDegreesAsync(45, 10, 100); await Task.Delay(2000); context.Assert(motor.AbsolutePosition, 87, 93); context.Assert(motor.Position, 87, 93); await motor.StartSpeedForDegreesAsync(45, 10, 100); await Task.Delay(2000); context.Assert(motor.AbsolutePosition, 132, 138); context.Assert(motor.Position, 132, 138); await motor.StartSpeedForDegreesAsync(45, 10, 100); await Task.Delay(2000); context.Assert(Math.Abs(motor.AbsolutePosition), 177, 180); context.Assert(motor.Position, 177, 183); await context.ConfirmAsync("TachoMotor.StartSpeedForDegreesAsync: Has moved 40 times CW each by 45°?"); }
public async Task ExecuteScriptAsync(Hub hub, TestScriptExecutionContext context) { var motor = hub.Port(0).GetDevice <TTechnicMotor>(); await motor.GotoRealZeroAsync(); await Task.Delay(2000); await motor.SetZeroAsync(); // TestCase: AbsoluteMotorReportsAbsolutePosition await motor.TryLockDeviceForCombinedModeNotificationSetupAsync(motor.ModeIndexAbsolutePosition, motor.ModeIndexPosition); await motor.SetupNotificationAsync(motor.ModeIndexPosition, true, 2); await motor.SetupNotificationAsync(motor.ModeIndexAbsolutePosition, true, 2); await motor.UnlockFromCombinedModeNotificationSetupAsync(true); await context.ConfirmAsync("AbsoluteMotor.GotoRealZeroAsync: Is in zero position? Adjust Beam to 0°?"); await TestCase1_TachoMotorPositionByDegreesAsync(context, motor); await TestCase2_TachoMotorExplicitPositionAsync(context, motor); await TestCase3_TachoMotorHighSpeedAndFloatingAsync(context, motor); await TestCase4_TachoMotorPositiveNegativeSpeedForTimeAsync(context, motor); await TestCase5_TachoMotorAccelerationAsync(context, motor); await TestCase6_BasicMotorAsync(context, motor); await TestCase7_InputAsync(context, motor); }
private static async Task ResetToZeroAsync(TestScriptExecutionContext context, TTechnicMotor motor, int expectedTime) { await motor.GotoPositionAsync(0, 10, 100); await Task.Delay(expectedTime); context.Assert(motor.AbsolutePosition, -3, 3); context.Assert(motor.Position, -3, 3); await context.ConfirmAsync("TachoMotor.GotoPositionAsync: has moved to zero position?"); }
private static async Task TestCase3_TachoMotorHighSpeedAndFloatingAsync(TestScriptExecutionContext context, TTechnicMotor motor) { context.Log.LogInformation("TachoMotor: High different Speed and Floating"); await motor.StartSpeedForDegreesAsync(810, -100, 100, SpecialSpeed.Float); await Task.Delay(2000); await context.ConfirmAsync("TachoMotor.StartSpeedForDegreesAsync: High speed CCW turn with floating end state?"); await ResetToZeroAsync(context, motor, 2000); }
private async Task TestCase4_TechnicDistanceSensorDistanceAsync(TestScriptExecutionContext context, TechnicDistanceSensor distanceSensor) { context.Log.LogInformation("Test distances between 4 and 250cm for 10s"); using var d1 = distanceSensor.DistanceObservable.Subscribe(x => context.Log.LogInformation($"Distance: {x}")); await distanceSensor.SetupNotificationAsync(distanceSensor.ModeIndexDistance, true); await Task.Delay(10_000); await distanceSensor.SetupNotificationAsync(distanceSensor.ModeIndexDistance, false); await context.ConfirmAsync("Are the distances measured accurately?"); }
private static void PrintModel(TestScriptExecutionContext context, DeploymentModel model) { context.Log.LogInformation($"> Deployment Model of Test Script"); foreach (var hub in model.Hubs) { context.Log.LogInformation($" > Hub: {hub.HubType}"); foreach (var device in hub.Devices) { context.Log.LogInformation($" > Device: {device.DeviceType} @ {device.PortId}"); } } }
private async Task TestCase2_TechnicDistanceSensorLightsBrightnessAsync(TestScriptExecutionContext context, TechnicDistanceSensor distanceSensor) { // play with the eye lights (0-100) for (byte idx = 0; idx < 100; idx += 5) { await distanceSensor.SetEyeLightAsync(0b0000_0000, idx, 0b0110_0100, idx); await Task.Delay(500); } await distanceSensor.SetEyeLightAsync(0, 0, 0, 0); await context.ConfirmAsync("TechnicDistanceSensor.SetEyeLightAsync: Did the right side brighten up?"); }
private static async Task TestCase5_TachoMotorAccelerationAsync(TestScriptExecutionContext context, TTechnicMotor motor) { context.Log.LogInformation("TachoMotor: Acceleration Profiles"); await motor.SetAccelerationTimeAsync(500); await motor.SetDecelerationTimeAsync(500); await motor.StartSpeedForTimeAsync(2000, 50, 100, SpecialSpeed.Brake, SpeedProfiles.AccelerationProfile | SpeedProfiles.DecelerationProfile); await Task.Delay(4000); await context.ConfirmAsync("TachoMotor.SetAccelerationTimeAsync: CW 0.5s each slow start and end?"); await ResetToZeroAsync(context, motor, 20_000); }
private async Task TestCase6_TechnicColorSectorLightsAsync(TestScriptExecutionContext context, TechnicColorSensor colorSensor) { await colorSensor.SetSectorLightAsync(100, 0, 0); await context.ConfirmAsync("TechnicColorSensor.SetSectorLightAsync: Light on Sector 1?"); await colorSensor.SetSectorLightAsync(0, 100, 0); await context.ConfirmAsync("TechnicColorSensor.SetSectorLightAsync: Light on Sector 2?"); await colorSensor.SetSectorLightAsync(0, 0, 100); await context.ConfirmAsync("TechnicColorSensor.SetSectorLightAsync: Light on Sector 3?"); await colorSensor.SetSectorLightAsync(0, 0, 0); }
private async Task TestCase7_InputAsync(TestScriptExecutionContext context, TTechnicMotor motor) { context.Log.LogInformation("AbsoluteMotor: Input on Absolute and relative Position"); context.Log.LogInformation("Turn 90° clockwise"); await motor.AbsolutePositionObservable.Where(x => x.SI > 85 && x.SI < 95).FirstAsync().GetAwaiter(); context.Log.LogInformation("Turn 180° counter-clockwise"); await motor.AbsolutePositionObservable.Where(x => x.SI <-85 && x.SI> -95).FirstAsync().GetAwaiter(); context.Log.LogInformation("Turn 90° counter-clockwise"); await motor.PositionObservable.Where(x => x.SI <-175 && x.SI> -185).FirstAsync().GetAwaiter(); }
private static async Task TestCase4_TachoMotorPositiveNegativeSpeedForTimeAsync(TestScriptExecutionContext context, TTechnicMotor motor) { context.Log.LogInformation("TachoMotor: Positive and Negative Speeds and for Time"); await motor.StartSpeedForTimeAsync(1000, 10, 100); await Task.Delay(2000); await context.ConfirmAsync("TachoMotor.StartSpeedForTimeAsync: CW for 1s?"); await motor.StartSpeedForTimeAsync(1000, -10, 100); await Task.Delay(2000); await context.ConfirmAsync("TachoMotor.StartSpeedForTimeAsync: CCW for 1s?"); await ResetToZeroAsync(context, motor, 3000); }
private async Task TestCase1_TechnicDistanceSensorLightsAsync(TestScriptExecutionContext context, TechnicDistanceSensor distanceSensor) { await distanceSensor.SetEyeLightAsync(leftTop : 100); await context.ConfirmAsync("TechnicDistanceSensor.SetEyeLightAsync: Light Left Top?"); await distanceSensor.SetEyeLightAsync(rightTop : 100); await context.ConfirmAsync("TechnicDistanceSensor.SetEyeLightAsync: Light Right Top?"); await distanceSensor.SetEyeLightAsync(leftBottom : 100); await context.ConfirmAsync("TechnicDistanceSensor.SetEyeLightAsync: Light Left Bottom?"); await distanceSensor.SetEyeLightAsync(rightBottom : 100); await context.ConfirmAsync("TechnicDistanceSensor.SetEyeLightAsync: Light Right Bottom?"); }
private static async Task TestCase6_BasicMotorAsync(TestScriptExecutionContext context, TTechnicMotor motor) { context.Log.LogInformation("TachoMotor: Start Speed & Power"); await motor.StartPowerAsync(100); await Task.Delay(1000); await motor.StopByBrakeAsync(); await motor.StartPowerAsync(-100); await Task.Delay(1000); await motor.StopByFloatAsync(); await context.ConfirmAsync("TachoMotor.StartPowerAsync: CW for 1s, brake, CCW for 1s, floating?"); await ResetToZeroAsync(context, motor, 3000); }
private static async Task TestCase2_TachoMotorExplicitPositionAsync(TestScriptExecutionContext context, TTechnicMotor motor) { context.Log.LogInformation("TachoMotor: Testing explicit position from TachoMotor.SetZero"); await motor.GotoPositionAsync(360, 10, 100); await Task.Delay(2000); context.Assert(motor.AbsolutePosition, -3, 3); context.Assert(motor.Position, 357, 363); await context.ConfirmAsync("TachoMotor.GotoPositionAsync: has moved CW to zero position?"); await motor.GotoPositionAsync(810, 10, 100); await Task.Delay(4000); context.Assert(motor.AbsolutePosition, 87, 93); context.Assert(motor.Position, 807, 813); await context.ConfirmAsync("TachoMotor.GotoPositionAsync: Motor has moved CW by 360° + 90° and is exaclty 90° off zero?"); }
private async Task TestCase5_TechnicColorIndexColorSensorAsync(TestScriptExecutionContext context, TechnicColorSensor colorSensor) { context.Log.LogInformation("Testing known Colors"); await colorSensor.SetupNotificationAsync(colorSensor.ModeIndexColor, true, 1); await colorSensor.ColorObservable.Where(c => c == TechnicColor.Black).FirstAsync().GetAwaiter(); context.Log.LogInformation($"[OK] {nameof(TechnicColor.Black)}"); await colorSensor.ColorObservable.Where(c => c == TechnicColor.Blue).FirstAsync().GetAwaiter(); context.Log.LogInformation($"[OK] {nameof(TechnicColor.Blue)}"); await colorSensor.ColorObservable.Where(c => c == TechnicColor.Teal).FirstAsync().GetAwaiter(); context.Log.LogInformation($"[OK] {nameof(TechnicColor.Teal)}"); await colorSensor.ColorObservable.Where(c => c == TechnicColor.Green).FirstAsync().GetAwaiter(); context.Log.LogInformation($"[OK] {nameof(TechnicColor.Green)}"); await colorSensor.ColorObservable.Where(c => c == TechnicColor.Yellow).FirstAsync().GetAwaiter(); context.Log.LogInformation($"[OK] {nameof(TechnicColor.Yellow)}"); await colorSensor.ColorObservable.Where(c => c == TechnicColor.Red).FirstAsync().GetAwaiter(); context.Log.LogInformation($"[OK] {nameof(TechnicColor.Red)}"); await colorSensor.ColorObservable.Where(c => c == TechnicColor.White).FirstAsync().GetAwaiter(); context.Log.LogInformation($"[OK] {nameof(TechnicColor.White)}"); await colorSensor.SetupNotificationAsync(colorSensor.ModeIndexColor, false); context.Log.LogInformation("All known colors recognized."); }
public async Task ExecuteScriptAsync(Hub hub, TestScriptExecutionContext context) { var distanceSensor = hub.Port(0).GetDevice <TechnicDistanceSensor>(); var colorSensor = hub.Port(1).GetDevice <TechnicColorSensor>(); context.Log.LogInformation("Start Testing DistanceSensor"); await TestCase1_TechnicDistanceSensorLightsAsync(context, distanceSensor); await TestCase2_TechnicDistanceSensorLightsBrightnessAsync(context, distanceSensor); await TestCase3_TechnicDistanceSensorShortDistanceAsync(context, distanceSensor); await TestCase4_TechnicDistanceSensorDistanceAsync(context, distanceSensor); context.Log.LogInformation("Start Testing ColorSensor"); await TestCase5_TechnicColorIndexColorSensorAsync(context, colorSensor); await TestCase6_TechnicColorSectorLightsAsync(context, colorSensor); await TestCase7_TechnicColorHsvSensorAsync(context, colorSensor); }
private async Task TestCase7_TechnicColorHsvSensorAsync(TestScriptExecutionContext context, TechnicColorSensor colorSensor) { context.Log.LogInformation("Testing HSV"); await colorSensor.SetupNotificationAsync(colorSensor.ModeIndexHSV, true, 1); await colorSensor.HsvObservable.Where(c => (c.hue is > 340 and < 360 || c.hue is > 0 and < 20) && c.saturation > 90 && c.value > 90).FirstAsync().GetAwaiter(); context.Log.LogInformation($"[OK] Reached Significant Red"); await colorSensor.HsvObservable.Where(c => (c.hue is > 100 and < 140) && c.saturation > 90 && c.value > 90).FirstAsync().GetAwaiter(); context.Log.LogInformation($"[OK] Reached Significant Green"); await colorSensor.HsvObservable.Where(c => (c.hue is > 220 and < 260) && c.saturation > 90 && c.value > 90).FirstAsync().GetAwaiter(); context.Log.LogInformation($"[OK] Reached Significant Blue"); await colorSensor.SetupNotificationAsync(colorSensor.ModeIndexHSV, false); context.Log.LogInformation("All known colors recognized."); }
static async Task Main(string[] args) { var configuration = new ConfigurationBuilder() .SetBasePath(Environment.CurrentDirectory) .AddJsonFile("poweredup.json", true) .AddCommandLine(args) .Build(); var serviceCollection = new ServiceCollection() .AddLogging(builder => { builder.AddConsole(); }) .AddPoweredUp(); var bluetoothAdapter = configuration["BluetoothAdapter"] ?? "WinRT"; #if WINDOWS if (bluetoothAdapter == "WinRT") { serviceCollection.AddWinRTBluetooth(); } #endif #if NET5_0_OR_GREATER if (bluetoothAdapter == "BlueGigaBLE") { // config for "COMPortName" and "TraceDebug" (either via command line or poweredup.json) serviceCollection.AddBlueGigaBLEBluetooth(configuration); } #endif var serviceProvider = serviceCollection.BuildServiceProvider(); var host = serviceProvider.GetService <PoweredUpHost>(); IEnumerable <ITestScript> scripts = new ITestScript[] { new TechnicMotorTestScript <TechnicLargeLinearMotor>(), new MindstormsSensorsTestScript(), }; var context = new TestScriptExecutionContext(serviceProvider.GetService <ILogger <TestScriptExecutionContext> >()); foreach (var script in scripts) { // Test Script context.Log.LogInformation($"Execute Script {script.GetType().Name}"); // build deployment model var model = BbuildDeploymentModel(script); PrintModel(context, model); // Accept to execute Test Script var executeTest = await context.ConfirmAsync("> Confirm to execute Test Script"); if (executeTest) { context.Log.LogInformation("> Discovering & Connecting Hub"); var hubType = HubFactory.GetTypeFromSystemType(model.Hubs[0].HubType ?? throw new InvalidOperationException("Specify the hub type in the test script.")); using var hub = await host.DiscoverAsync(hubType); await hub.ConnectAsync(); context.Log.LogInformation("> Verifying Deployment Model (fix it if necessary)"); await hub.VerifyDeploymentModelAsync(model); context.Log.LogInformation("> Start Test Script"); await script.ExecuteScriptAsync(hub, context); context.Log.LogInformation("> Switch Off Hub"); await hub.SwitchOffAsync(); } else { context.Log.LogWarning($"> User decided not to execute Test Script"); } } }