Skip to content
This repository has been archived by the owner on Apr 24, 2024. It is now read-only.

Commit

Permalink
feature: add FluidXScanner-class
Browse files Browse the repository at this point in the history
  • Loading branch information
simbig committed Mar 23, 2023
1 parent 6336516 commit ddbe1d6
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 27 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Expand Up @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

## v5.1.0

### Added

- Add `FluidXScanner`-class

## v5.0.0

### Added
Expand Down
54 changes: 27 additions & 27 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions rector.php
Expand Up @@ -2,6 +2,7 @@

use Rector\Config\RectorConfig;
use Rector\Core\ValueObject\PhpVersion;
use Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector;
use Rector\Set\ValueObject\SetList;
use Rector\TypeDeclaration\Rector\Closure\AddClosureReturnTypeRector;

Expand All @@ -18,4 +19,10 @@
]);
$config->paths([__DIR__ . '/src', __DIR__ . '/tests']);
$config->phpVersion(PhpVersion::PHP_74);

$config->skip([
FinalizeClassesWithoutChildrenRector::class => [
__DIR__ . '/src/FluidXPlate/FluidXScanner.php', // enabled for mocking
],
]);
};
103 changes: 103 additions & 0 deletions src/FluidXPlate/FluidXScanner.php
@@ -0,0 +1,103 @@
<?php declare(strict_types=1);

namespace Mll\LiquidHandlingRobotics\FluidXPlate;

use Illuminate\Support\Str;
use Mll\Microplate\Coordinate;
use Mll\Microplate\CoordinateSystem96Well;
use MLL\Utils\StringUtil;

/**
* Communicates with a FluidX scanner device and fetches results from it.
*/
class FluidXScanner
{
private const READING = 'Reading...';
private const XTR_96_CONNECTED = 'xtr-96 Connected';
private const NO_READ = 'NO READ';
private const NO_TUBE = 'NO TUBE';
public const LOCALHOST = '127.0.0.1';

public function scanPlate(string $ip): FluidXPlate
{
if (self::LOCALHOST === $ip) {
return self::returnTestPlate();
}

if ('' === $ip) {
throw new ScanFluidXPlateException('Cannot start scan request without an IP address.');
}

try {
$socket = \Safe\fsockopen($ip, 8001, $errno, $errstr, 30);
} catch (\Throwable $e) {
throw new ScanFluidXPlateException("Cannot reach FluidX Scanner {$ip}: {$e->getMessage()}. Verify that the FluidX Scanner is turned on and the FluidX software is started.", 0, $e);
}

\Safe\fwrite($socket, "get\r\n");

$answer = '';
do {
$content = fgets($socket);
$answer .= $content;
} while (is_string($content) && ! Str::contains($content, 'H12'));

\Safe\fclose($socket);

return self::parseRawContent($answer);
}

public static function parseRawContent(string $rawContent): FluidXPlate
{
if ('' === $rawContent) {
throw new ScanFluidXPlateException('Der Scanner lieferte ein leeres Ergebnis zurück.');
}

$lines = StringUtil::splitLines($rawContent);
$barcodes = [];
$id = null;
foreach ($lines as $line) {
if ('' === $line || self::READING === $line || self::XTR_96_CONNECTED === $line) {
continue;
}
$content = explode(', ', $line);
if (count($content) <= 3) {
continue;
}

// All valid lines contain the same plate barcode
$id = $content[3];
if (FluidXScanner::NO_READ === $id && isset($content[4])) {
$id = $content[4];
}

$barcodeScanResult = $content[1];
$coordinateString = $content[0];
if (self::NO_READ !== $barcodeScanResult && self::NO_TUBE !== $barcodeScanResult) {
$barcodes[$coordinateString] = $barcodeScanResult;
}
}

if (is_null($id)) {
throw new ScanFluidXPlateException('Der Scanner lieferte keinen Plattenbarcode zurück.');
}

if (FluidXScanner::NO_READ === $id) {
throw new ScanFluidXPlateException([] === $barcodes
? 'Weder Platten-Barcode noch Tube-Barcodes konnten gescannt werden. Bitte überprüfen Sie, dass die Platte korrekt in den FluidX-Scanner eingelegt wurde.'
: 'Platten-Barcode konnte nicht gescannt werden. Bitte überprüfen Sie, dass die Platte mit der korrekten Orientierung in den FluidX-Scanner eingelegt wurde.');
}

$plate = new FluidXPlate($id);
foreach ($barcodes as $coordinate => $barcode) {
$plate->addWell(Coordinate::fromString($coordinate, new CoordinateSystem96Well()), $barcode);
}

return $plate;
}

private static function returnTestPlate(): FluidXPlate
{
return self::parseRawContent(\Safe\file_get_contents(__DIR__ . '/TestPlate.txt'));
}
}
7 changes: 7 additions & 0 deletions src/FluidXPlate/ScanFluidXPlateException.php
@@ -0,0 +1,7 @@
<?php declare(strict_types=1);

namespace Mll\LiquidHandlingRobotics\FluidXPlate;

final class ScanFluidXPlateException extends FluidXPlateException
{
}

0 comments on commit ddbe1d6

Please sign in to comment.