src/Entity/Device.php line 29

Open in your IDE?
  1. <?php
  2. /**
  3.  * @license SILK SOFTWARE HOUSE SP Z O O
  4.  */
  5. namespace App\Entity;
  6. use App\Entity\Traits\IdTrait;
  7. use App\Entity\Traits\TimePreUpdateTrait;
  8. use App\Entity\Traits\TimeTrait;
  9. use App\Model\Filter\MeasurementFilter;
  10. use DateTimeInterface;
  11. use Doctrine\Common\Collections\ArrayCollection;
  12. use Doctrine\Common\Collections\Collection;
  13. use Doctrine\ORM\Mapping as ORM;
  14. use DateTime;
  15. use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
  16. use Symfony\Component\Validator\Constraints as Assert;
  17. /**
  18.  * Class Device.
  19.  *
  20.  * @ORM\Table("devices")
  21.  * @ORM\Entity(repositoryClass="App\Repository\DeviceRepository")
  22.  * @ORM\HasLifecycleCallbacks()
  23.  *
  24.  * @UniqueEntity(fields={"serialNumber"})
  25.  */
  26. class Device
  27. {
  28.     use IdTrait;
  29.     use TimeTrait;
  30.     use TimePreUpdateTrait;
  31.     /**
  32.      * Serial number.
  33.      *
  34.      * @var string
  35.      *
  36.      * @ORM\Column(name="serial_number", type="string", nullable=false, options={"comment": "Serial number."})
  37.      */
  38.     private $serialNumber;
  39.     /**
  40.      * Customer.
  41.      *
  42.      * @var Customer|null
  43.      *
  44.      * @ORM\ManyToOne(targetEntity="App\Entity\Customer", inversedBy="devices")
  45.      * @ORM\JoinColumn(name="customer_id", nullable=true)
  46.      */
  47.     private $customer;
  48.     /**
  49.      * Measurements.
  50.      *
  51.      * @var Measurement[]|ArrayCollection
  52.      *
  53.      * @ORM\OneToMany(targetEntity="App\Entity\Measurement", mappedBy="device")
  54.      *
  55.      * @ORM\OrderBy({"finishedAt" = "DESC"})
  56.      */
  57.     private $measurements;
  58.     /**
  59.      * @var array|null
  60.      */
  61.     private $measurementIds;
  62.     /**
  63.      * Assignment ends at.
  64.      *
  65.      * @var DateTime|null
  66.      *
  67.      * @ORM\Column(name="active_to", type="datetime", nullable=true, options={"comment": "Assignment ends at."})
  68.      */
  69.     private $assignmentEndsAt;
  70.     /**
  71.      * Is used.
  72.      *
  73.      * @var bool
  74.      *
  75.      * @ORM\Column(name="is_used", type="boolean", nullable=false, options={"comment": "Did used marked this devices as used.", "default": true})
  76.      */
  77.     private $isUsed true;
  78.     /**
  79.      * @ORM\Column(type="datetime", nullable=true)
  80.      */
  81.     private $calibratedAt;
  82.     /**
  83.      * Channels limit.
  84.      *
  85.      * @var int|null
  86.      *
  87.      * @ORM\Column(name="channels_limit", type="integer", options={"comment": "Channels limit.", "default": 12}, nullable=true)
  88.      */
  89.     private $channelsLimit 12;
  90.     /**
  91.      * Name assigned to this device.
  92.      *
  93.      * @var string|null
  94.      *
  95.      * @ORM\Column(name="name", type="text", nullable=true, options={"comment": "Name assigned to this device."})
  96.      */
  97.     private $name;
  98.     /**
  99.      * Device user settings.
  100.      *
  101.      * @var UserSetting[]|ArrayCollection
  102.      *
  103.      * @ORM\ManyToMany(targetEntity="App\Entity\UserSetting", mappedBy="usedDevices")
  104.      */
  105.     private $userSetting;
  106.     /**
  107.      * @ORM\OneToMany(targetEntity="App\Entity\DataSample", mappedBy="device")
  108.      * @ORM\OrderBy({"id" = "asc"})
  109.      */
  110.     private $dataSample;
  111.     /**
  112.      * @ORM\OneToMany(targetEntity="App\Entity\RecipeToSync", mappedBy="device", cascade={"remove"})
  113.      */
  114.     private $recipeToSyncs;
  115.     /**
  116.      * @ORM\OneToMany(targetEntity="App\Entity\DeviceCommand", mappedBy="device")
  117.      */
  118.     private $deviceCommands;
  119.     /**
  120.      * @ORM\OneToOne(targetEntity="App\Entity\DeviceLastCommunication", mappedBy="device", cascade={"persist", "remove"})
  121.      * @ORM\OrderBy({"id" = "DESC"})
  122.      */
  123.     private $deviceLastCommunication;
  124.     /**
  125.      * @ORM\Column(type="string", nullable=true, length=255)
  126.      *
  127.      * @Assert\Email(
  128.      *     message = "The email '{{ value }}' is not a valid email."
  129.      * )
  130.      */
  131.     private $email;
  132.     /**
  133.      * @ORM\Column(type="datetime", name="latest_battery_level_notification_at", nullable=true)
  134.      */
  135.     private $latestBatteryLevelNotificationAt;
  136.     /**
  137.      * Device constructor.
  138.      */
  139.     public function __construct()
  140.     {
  141.         $this->measurements = new ArrayCollection();
  142.         $this->userSetting = new ArrayCollection();
  143.         $this->dataSample = new ArrayCollection();
  144.         $this->recipeToSyncs = new ArrayCollection();
  145.         $this->deviceCommands = new ArrayCollection();
  146.     }
  147.     /**
  148.      * Get serial number.
  149.      *
  150.      * @return string
  151.      */
  152.     public function getSerialNumber(): string
  153.     {
  154.         return $this->serialNumber;
  155.     }
  156.     /**
  157.      * Set serial number.
  158.      *
  159.      * @param string $serialNumber
  160.      *
  161.      * @return Device
  162.      */
  163.     public function setSerialNumber(string $serialNumber): Device
  164.     {
  165.         $this->serialNumber $serialNumber;
  166.         return $this;
  167.     }
  168.     /**
  169.      * Get customer.
  170.      *
  171.      * @return Customer|null
  172.      */
  173.     public function getCustomer(): ?Customer
  174.     {
  175.         return $this->customer;
  176.     }
  177.     /**
  178.      * Set customer.
  179.      *
  180.      * @param Customer|null $customer
  181.      *
  182.      * @return Device
  183.      */
  184.     public function setCustomer(?Customer $customer): Device
  185.     {
  186.         if ((!$this->customer && $customer) || ($this->customer && !$customer)
  187.             || ($this->customer && $customer && $customer->getId() !== $this->customer->getId())) {
  188.             $this->isUsed true;
  189.         }
  190.         $this->customer $customer;
  191.         return $this;
  192.     }
  193.     /**
  194.      * Get active measurements.
  195.      *
  196.      * @return Measurement[]|ArrayCollection
  197.      */
  198.     public function getActiveMeasurements(): ArrayCollection
  199.     {
  200.         $result = new ArrayCollection();
  201.         foreach ($this->measurements as $measurement) {
  202.             if (!$measurement->getIsFinished()) {
  203.                 $result->add($measurement);
  204.             }
  205.         }
  206.         return $result;
  207.     }
  208.     /**
  209.      * Get measurements.
  210.      *
  211.      * @return Measurement[]|ArrayCollection
  212.      */
  213.     public function getMeasurements()
  214.     {
  215.         return $this->measurements;
  216.     }
  217.     /**
  218.      * Get array of measurements id.
  219.      *
  220.      * The value is cached.
  221.      *
  222.      * @return array|null
  223.      */
  224.     public function getSortedMeasurmentsIdsArray()
  225.     {
  226.         if (!isset($this->measurementIds)) {
  227.             $measurements $this->getMeasurements();
  228.             if ($measurements->isEmpty()) {
  229.                 return [];
  230.             }
  231.             $measurementIds array_map(function ($measurement) {
  232.                 return $measurement->getId();
  233.             }, $measurements->toArray());
  234.             sort($measurementIds);
  235.             $this->measurementIds $measurementIds;
  236.         }
  237.         return $this->measurementIds;
  238.     }
  239.     /**
  240.      * Prime the relative-name lookup when measurements were loaded by an
  241.      * optimized overview query instead of through this entity collection.
  242.      *
  243.      * @param Measurement[] $measurements
  244.      */
  245.     public function cacheSortedMeasurementIds(iterable $measurements): void
  246.     {
  247.         $this->measurementIds = [];
  248.         foreach ($measurements as $measurement) {
  249.             $this->measurementIds[] = $measurement->getId();
  250.         }
  251.         sort($this->measurementIds);
  252.     }
  253.     /**
  254.      * Prime the relative-name lookup from an inexpensive scalar ID query.
  255.      *
  256.      * @param int[] $measurementIds
  257.      */
  258.     public function cacheSortedMeasurementIdsArray(iterable $measurementIds): void
  259.     {
  260.         $this->measurementIds array_values(array_unique(array_map('intval'is_array($measurementIds)
  261.             ? $measurementIds
  262.             iterator_to_array($measurementIds))));
  263.         sort($this->measurementIds);
  264.     }
  265.     /**
  266.      * Get active measurements.
  267.      *
  268.      * @param MeasurementFilter $filters
  269.      *
  270.      * @return Measurement[]|ArrayCollection
  271.      */
  272.     public function getInactiveMeasurements(MeasurementFilter $filters): ArrayCollection
  273.     {
  274.         $result = new ArrayCollection();
  275.         foreach ($this->measurements as $measurement) {
  276.             if (!$measurement->getIsFinished()
  277.                 || ($filters->getMeasurementId() && (int) $filters->getMeasurementId() !== $measurement->getId())
  278.                 || $filters->getIsDateToLowerThan($measurement->getStartedAt())
  279.                 || $filters->getIsDateFromGreaterThan($measurement->getFinishedAt())) {
  280.                 continue;
  281.             }
  282.             $result->add($measurement);
  283.         }
  284.         return $this->sortMeasurementsByArchiveTime($result);
  285.     }
  286.     /**
  287.      * Keep archive ordering deterministic even when older measurements are inserted later.
  288.      *
  289.      * @param ArrayCollection|Measurement[] $measurements
  290.      *
  291.      * @return ArrayCollection
  292.      */
  293.     private function sortMeasurementsByArchiveTime(ArrayCollection $measurements): ArrayCollection
  294.     {
  295.         $iterator $measurements->getIterator();
  296.         $iterator->uasort(function (Measurement $leftMeasurement $right): int {
  297.             $comparison $right->getFinishedAt() <=> $left->getFinishedAt();
  298.             if (!== $comparison) {
  299.                 return $comparison;
  300.             }
  301.             return $right->getStartedAt() <=> $left->getStartedAt();
  302.         });
  303.         return new ArrayCollection(iterator_to_array($iterator));
  304.     }
  305.     /**
  306.      * Get is active.
  307.      *
  308.      * @return bool
  309.      */
  310.     public function getIsActive(): bool
  311.     {
  312.         return $this->getActiveMeasurements()->count() > 0;
  313.     }
  314.     /**
  315.      * Get active assignment.
  316.      *
  317.      * @return Customer|null
  318.      *
  319.      * @throws \Exception
  320.      */
  321.     public function getActiveAssignment(): ?Customer
  322.     {
  323.         if (null === $this->assignmentEndsAt || $this->assignmentEndsAt > new DateTime()) {
  324.             return $this->customer;
  325.         }
  326.         return null;
  327.     }
  328.     /**
  329.      * Get last measurement.
  330.      *
  331.      * @return Measurement|null
  332.      */
  333.     public function getLastMeasurement(): ?Measurement
  334.     {
  335.         foreach (krsort($this->measurements) as $measurement) {
  336.             if (true === $measurement->getSetting()->isDeleted()) {
  337.                 continue;
  338.             }
  339.             return $measurement;
  340.         }
  341.         return null;
  342.     }
  343.     /**
  344.      * Get first measurement.
  345.      *
  346.      * @return Measurement|null
  347.      */
  348.     public function getFirstMeasurement(): ?Measurement
  349.     {
  350.         foreach ($this->measurements as $measurement) {
  351.             // im sorry but | null must be checked
  352.             if (null !== $measurement->getSetting()) {
  353.                 if (true === $measurement->getSetting()->isDeleted()) {
  354.                     continue;
  355.                 }
  356.             }
  357.             return $measurement;
  358.         }
  359.         return null;
  360.     }
  361.     /**
  362.      * Returns duration in days.
  363.      *
  364.      * @return int|null
  365.      *
  366.      * @throws \Exception
  367.      */
  368.     public function getDuration(): ?int
  369.     {
  370.         /** @var Measurement $lastMeasurement */
  371.         $lastMeasurement $this->measurements->last();
  372.         if (!$lastMeasurement) {
  373.             return null;
  374.         }
  375.         $endsAt $lastMeasurement->getFinishedAt() ?? new DateTime();
  376.         $startedAt $lastMeasurement->getStartedAt() ?? $lastMeasurement->getCreatedAt();
  377.         return (int) $endsAt->diff($startedAt)->format('%a') + 1;
  378.     }
  379.     /**
  380.      * To string.
  381.      *
  382.      * @return string
  383.      */
  384.     public function __toString()
  385.     {
  386.         return $this->serialNumber ?? '{{ not-serialized-device }}';
  387.     }
  388.     /**
  389.      * Get assignment ends at.
  390.      *
  391.      * @return DateTime|null
  392.      */
  393.     public function getAssignmentEndsAt(): ?DateTime
  394.     {
  395.         return $this->assignmentEndsAt;
  396.     }
  397.     /**
  398.      * Set assignment ends at.
  399.      *
  400.      * @param DateTime|null $assignmentEndsAt
  401.      *
  402.      * @return Device
  403.      */
  404.     public function setAssignmentEndsAt(?DateTime $assignmentEndsAt): Device
  405.     {
  406.         $this->assignmentEndsAt $assignmentEndsAt;
  407.         return $this;
  408.     }
  409.     /**
  410.      * Get is used.
  411.      *
  412.      * @return bool
  413.      */
  414.     public function isUsed(): bool
  415.     {
  416.         return $this->isUsed;
  417.     }
  418.     /**
  419.      * Set is used.
  420.      *
  421.      * @param bool $isUsed
  422.      *
  423.      * @return Device
  424.      */
  425.     public function setIsUsed(bool $isUsed): Device
  426.     {
  427.         $this->isUsed $isUsed;
  428.         return $this;
  429.     }
  430.     /**
  431.      * @return DateTimeInterface|null
  432.      */
  433.     public function getCalibratedAt(): ?DateTimeInterface
  434.     {
  435.         return $this->calibratedAt;
  436.     }
  437.     /**
  438.      * @param DateTimeInterface|null $calibratedAt
  439.      *
  440.      * @return Device
  441.      */
  442.     public function setCalibratedAt(?DateTimeInterface $calibratedAt): self
  443.     {
  444.         $this->calibratedAt $calibratedAt;
  445.         return $this;
  446.     }
  447.     /**
  448.      * Get channels limit.
  449.      *
  450.      * @return int|null
  451.      */
  452.     public function getChannelsLimit(): ?int
  453.     {
  454.         return $this->channelsLimit;
  455.     }
  456.     /**
  457.      * Set channels limit.
  458.      *
  459.      * @param int|null $channelsLimit
  460.      *
  461.      * @return Device
  462.      */
  463.     public function setChannelsLimit(?int $channelsLimit): Device
  464.     {
  465.         $this->channelsLimit $channelsLimit;
  466.         return $this;
  467.     }
  468.     /**
  469.      * Get name.
  470.      *
  471.      * @param bool $defaultOnNull
  472.      *
  473.      * @return string|null
  474.      */
  475.     public function getName(?bool $defaultOnNull false): ?string
  476.     {
  477.         if ($defaultOnNull && empty($this->name)) {
  478.             return '{{instrument}} '.$this->getId();
  479.         }
  480.         return $this->name;
  481.     }
  482.     /**
  483.      * @return string
  484.      */
  485.     public function getNameWithSerial(): string
  486.     {
  487.         return $this->getSerialNumber().': '.$this->getName(true);
  488.     }
  489.     /**
  490.      * Set name.
  491.      *
  492.      * @param string|null $name
  493.      *
  494.      * @return Device
  495.      */
  496.     public function setName(?string $name): Device
  497.     {
  498.         $this->name $name;
  499.         return $this;
  500.     }
  501.     /**
  502.      * @return Collection|DataSample[]
  503.      */
  504.     public function getDataSample(): Collection
  505.     {
  506.         return $this->dataSample;
  507.     }
  508.     /**
  509.      * @param DataSample $dataSample
  510.      *
  511.      * @return Device
  512.      */
  513.     public function addDataSample(DataSample $dataSample): self
  514.     {
  515.         if (!$this->dataSample->contains($dataSample)) {
  516.             $this->dataSample[] = $dataSample;
  517.             $dataSample->setDevice($this);
  518.         }
  519.         return $this;
  520.     }
  521.     /**
  522.      * @param DataSample $dataSample
  523.      *
  524.      * @return Device
  525.      */
  526.     public function removeDataSample(DataSample $dataSample): self
  527.     {
  528.         if ($this->dataSample->contains($dataSample)) {
  529.             $this->dataSample->removeElement($dataSample);
  530.             // set the owning side to null (unless already changed)
  531.             if ($dataSample->getDevice() === $this) {
  532.                 $dataSample->setDevice(null);
  533.             }
  534.         }
  535.         return $this;
  536.     }
  537.     /**
  538.      * @return Collection|RecipeToSync[]
  539.      */
  540.     public function getRecipeToSyncs(): Collection
  541.     {
  542.         return $this->recipeToSyncs;
  543.     }
  544.     /**
  545.      * @param RecipeToSync $recipeToSync
  546.      *
  547.      * @return Device
  548.      */
  549.     public function addRecipeToSync(RecipeToSync $recipeToSync): self
  550.     {
  551.         if (!$this->recipeToSyncs->contains($recipeToSync)) {
  552.             $this->recipeToSyncs[] = $recipeToSync;
  553.             $recipeToSync->setDevice($this);
  554.         }
  555.         return $this;
  556.     }
  557.     /**
  558.      * @param RecipeToSync $recipeToSync
  559.      *
  560.      * @return Device
  561.      */
  562.     public function removeRecipeToSync(RecipeToSync $recipeToSync): self
  563.     {
  564.         if ($this->recipeToSyncs->contains($recipeToSync)) {
  565.             $this->recipeToSyncs->removeElement($recipeToSync);
  566.             // set the owning side to null (unless already changed)
  567.             if ($recipeToSync->getDevice() === $this) {
  568.                 $recipeToSync->setDevice(null);
  569.             }
  570.         }
  571.         return $this;
  572.     }
  573.     /**
  574.      * @return Collection|DeviceCommand[]
  575.      */
  576.     public function getDeviceCommands(): Collection
  577.     {
  578.         return $this->deviceCommands;
  579.     }
  580.     /**
  581.      * @param DeviceCommand $deviceCommand
  582.      *
  583.      * @return Device
  584.      */
  585.     public function addDeviceCommand(DeviceCommand $deviceCommand): self
  586.     {
  587.         if (!$this->deviceCommands->contains($deviceCommand)) {
  588.             $this->deviceCommands[] = $deviceCommand;
  589.             $deviceCommand->setDevice($this);
  590.         }
  591.         return $this;
  592.     }
  593.     /**
  594.      * @param DeviceCommand $deviceCommand
  595.      *
  596.      * @return Device
  597.      */
  598.     public function removeDeviceCommand(DeviceCommand $deviceCommand): self
  599.     {
  600.         if ($this->deviceCommands->contains($deviceCommand)) {
  601.             $this->deviceCommands->removeElement($deviceCommand);
  602.             // set the owning side to null (unless already changed)
  603.             if ($deviceCommand->getDevice() === $this) {
  604.                 $deviceCommand->setDevice(null);
  605.             }
  606.         }
  607.         return $this;
  608.     }
  609.     /**
  610.      * @return DeviceLastCommunication|null
  611.      */
  612.     public function getDeviceLastCommunication(): ?DeviceLastCommunication
  613.     {
  614.         return $this->deviceLastCommunication;
  615.     }
  616.     /**
  617.      * @param DeviceLastCommunication $deviceLastCommunication
  618.      *
  619.      * @return Device
  620.      */
  621.     public function setDeviceLastCommunication(DeviceLastCommunication $deviceLastCommunication): self
  622.     {
  623.         $this->deviceLastCommunication $deviceLastCommunication;
  624.         // set the owning side of the relation if necessary
  625.         if ($deviceLastCommunication->getDevice() !== $this) {
  626.             $deviceLastCommunication->setDevice($this);
  627.         }
  628.         return $this;
  629.     }
  630.     /**
  631.      * @return string|null
  632.      */
  633.     public function getEmail(): ?string
  634.     {
  635.         return $this->email;
  636.     }
  637.     /**
  638.      * @param string|null $email
  639.      *
  640.      * @return Device
  641.      */
  642.     public function setEmail(?string $email): self
  643.     {
  644.         $this->email $email;
  645.         return $this;
  646.     }
  647.   /**
  648.      * @return DateTime|null
  649.      */
  650.     public function getLatestBatteryLevelNotificationAt(): ?DateTime
  651.     {
  652.         return $this->latestBatteryLevelNotificationAt;
  653.     }
  654.     /**
  655.      * @param DateTime|null $latestBatteryLevelNotificationAt
  656.      *
  657.      * @return Device
  658.      */
  659.     public function setLatestBatteryLevelNotificationAt(?DateTime $latestBatteryLevelNotificationAt null): self
  660.     {
  661.         $this->latestBatteryLevelNotificationAt $latestBatteryLevelNotificationAt;
  662.         return $this;
  663.     }
  664. }