Browse Source

UPD: bump to service version 1.7.0
UPD: bump to omlink version 1.12.0

Giancarlo Voci 7 years ago
parent
commit
4a71e82a3e

+ 0 - 1
cfg/config.bin

@@ -1 +0,0 @@
-eJyFkV1v2jAUhu8t+T9EXG2amg8SaDdkaSEYSBdilA/EVlUoBANRE5s5DluL+O9zwqpdzpIl29Jz3uccPx1Kvs3K+hmCFY5in4TI0oe6CYGbJiQg7gT1apEbPQg815tjDWlJlGIIUh81hbEXnEnKdgYEEzxOZ6gPAQ49MvHDGeqlyfTuQZFzfzYP1E7QXkVRCB7dSKe/T4Wg6HKRRUU/fPxkWwN7aJrm9apqxSHqVa/1z/LLkdcSlTzPyvY0OnEhkW2bw9Fuy7KKIl6VBXtRIbttU1OBBOeyvZyyukb8RFlVsB0EC3e9iXASfd9MSbSZummQIMtsrVdIikY5QTDSlpk8QjB2Y5xGATJutSGI/QSH7gIjsrgLupeAzMjGS+OELHCkevj6l7leDZVLZW0UVXagtVHyA9dP7ACB75Fw03Jp8j+gkTekVYppSXOp/ToW+VHLm1ryigotLxWlUZZtS6X+LtI5vktD8OSRCOv77XPXmuC7JpcFZxB0M7U+93Vr+KBbpm45ahLdZAem49i3WHFWOQmOEwhe6CvyzH/Lspx7x+zb5uBece2gf4jD28v5UZBvLIw9tmSzN7u5uEM6j8P16lx3OlM/nIzJOsbRyvewslqSSP1C33Yg+AOTHMFx

+ 4 - 1
cfg/config.ini

@@ -1,5 +1,5 @@
 [globals]
-VERSION=1.6.0
+VERSION=1.7.0
 AUTOLOAD="src/"
 CACHE = TRUE
 UI=ui/frontend/
@@ -12,6 +12,8 @@ dbuser=root
 dbpass=openmind
 MAX_RETRY_FOR_FAULT=10
 DEV=true
+AGGREGATE_TIMEOUT=500
+BLINKOFF_COLOR=0
 
 ; Path
 BASEURL=/omlink
@@ -32,3 +34,4 @@ pass=ZrgzkvJrOKnNSCnPnGz3u{A6eHSNXVvs
 
 [FINDBOXSERVICE]
 PORT=1234
+MAX_JOBS=1

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
 	"name": "omlink",
-	"version": "1.10.2",
+	"version": "1.12.0",
 	"codename": "Barricade",
 	"private": true,
 	"description": "OM-Link Engine",

+ 2 - 2
src/OpenMind/FindBox/FindBoxCoreSystem.php

@@ -91,7 +91,7 @@ class FindBoxCoreSystem
 
 		$streamfbOS = @stream_socket_client("tcp://{$this->Host}:{$this->Port}", $errno, $errstr, 1);
 		if (!$streamfbOS) {
-			$frameworkUtils->getLogger()->write("CallAPI::stream_socket_client error eode: [{$errno}]-'{$errstr}'", 'd/m/Y H:i:s');
+			$frameworkUtils->getLogger()->write("CallAPI::stream_socket_client error code: [{$errno}]-'{$errstr}'", 'd/m/Y H:i:s');
 			return $this->returnCode($errno, $errstr);
 		} else {
 			//$requestText = "{$method} {$URI}{$Parameters} HTTP/1.0\r\nHost: {$this->Host}\r\n{$auth}Accept: */*\r\nConnection: close\r\n\r\n";
@@ -143,7 +143,7 @@ class FindBoxCoreSystem
 
 		$streamfbOS = @stream_socket_client("tcp://{$this->Host}:{$this->Port}", $errno, $errstr, 1);
 		if (!$streamfbOS) {
-			$frameworkUtils->getLogger()->write("AsyncCallAPI::stream_socket_client error eode: [{$errno}]-'{$errstr}'", 'd/m/Y H:i:s');
+			$frameworkUtils->getLogger()->write("AsyncCallAPI::stream_socket_client error code: [{$errno}]-'{$errstr}'", 'd/m/Y H:i:s');
 			return $this->returnCode($errno, $errstr);
 		} else {
 			stream_set_blocking($streamfbOS, false);

+ 214 - 66
src/OpenMind/FindBox/FindBoxService.php

@@ -20,8 +20,12 @@ class JobManager
 	/** @var AsyncJobClass[] $jobs */
 	private $jobs;
 
-	public function __construct()
+	/** @var Log $ServiceLogger */
+	private $ServiceLogger;
+
+	public function __construct($ServiceLogger)
 	{
+		$this->ServiceLogger = $ServiceLogger;
 		$this->Reset();
 	}
 
@@ -33,11 +37,57 @@ class JobManager
 		$this->jobs = [];
 	}
 
-	public function RemoveLabelsFromJobs(array $labelsToRemove)
+	private function array_diff_symmetric(array $ar1, array $ar2): array
+	{
+		return array_merge(array_diff($ar1, $ar2), array_diff($ar2, $ar1));
+	}
+
+	public function AggregateBlinkByParams()
 	{
-		foreach($this->jobs as $job) {
-			$job->RemoveLabels($labelsToRemove);
+		global $f3;
+
+		if (count($this->jobs) == 0)
+			return;
+
+		$uniq = [];
+		$freeJobs = array_slice($this->jobs, $f3->get('FINDBOXSERVICE.MAX_JOBS'), null, true);
+
+		if (count($freeJobs) == 0)
+			return;
+		// Get unique jobs with same params
+		foreach($freeJobs as $k => $jobToFind) {
+
+			$parmExists = array_filter($uniq, function ($job) use ($jobToFind) {
+				return (count($this->array_diff_symmetric($job->getLedParams(), $jobToFind->getLedParams())) === 0);
+			});
+			if (count($parmExists) == 0)
+				$uniq[$k] = $jobToFind;
 		}
+
+		foreach($uniq as $jobUniq) {
+			array_filter($freeJobs, function ($job) use (&$jobUniq) {
+
+				// aggregate ids with same params
+				if (count($this->array_diff_symmetric($jobUniq->getLedParams(), $job->getLedParams())) === 0) {
+
+					if (count($this->array_diff_symmetric($job->getLabels(), $jobUniq->getLabels())) === 0)
+						return;
+
+					$labels = array_unique(array_merge($job->getLabels(), $jobUniq->getLabels()));
+					$jobUniq->setLabels($labels);
+				}
+			});
+		}
+
+		$this->jobs = array_merge(
+			array_slice($this->jobs, 0, 1, true),
+			$uniq
+		);
+	}
+
+	public function count()
+	{
+		return count($this->jobs);
 	}
 
 	/**
@@ -47,11 +97,20 @@ class JobManager
 	 */
 	public function Run(callable $callBack)
 	{
-		foreach($this->jobs as $k => $job) {
-			if ($callBack($job) === TRUE)
+		global $f3;
+
+		if (count($this->jobs) == 0)
+			return;
+
+		$jobList = array_slice($this->jobs, 0, $f3->get('FINDBOXSERVICE.MAX_JOBS'), TRUE);
+
+		foreach($jobList as $k => $job) {
+
+			if ($callBack($job) === TRUE) {
 				unset($this->jobs[$k]);
-			else
+			} else
 				$job->Run();
+
 		}
 	}
 
@@ -59,30 +118,19 @@ class JobManager
 	{
 		$this->jobs[] = $job;
 	}
-
-	public function count()
-	{
-		return count($this->jobs);
-	}
 }
 
 class AsyncJobClass
 {
+	public $Opened;
 	/** @var integer $retryForFault */
 	public $retryForFault;
-
 	/** @var Generator $blinkGenerator */
 	private $blinkGenerator = null;
-
 	/** @var array|null ledParams */
 	private $ledParams;
-
-	/** @var bool $blinkoff */
-	private $blinkoff = false;
-
 	/** @var array labels */
 	private $labels;
-
 	/** @var FindBoxCoreSystem $fb */
 	private $fb;
 
@@ -101,6 +149,7 @@ class AsyncJobClass
 		$this->labels = $labels;
 		$this->ledParams = $ledParams;
 		$this->retryForFault = $f3->get('MAX_RETRY_FOR_FAULT');
+		$this->Opened = false;
 	}
 
 	public function __destruct()
@@ -113,13 +162,15 @@ class AsyncJobClass
 
 	public function Stop($reason)
 	{
+		$this->Opened = false;
 		return $this->blinkGenerator->send($reason);
 	}
 
-	public function RemoveLabels(array $labelsToFind)
+	public function RemoveLabels(array $labelsToFind): int
 	{
-		$a = array_diff($this->labels, $labelsToFind);
-		$this->labels = $a;
+		$diff = array_diff($this->labels, $labelsToFind);
+		$this->labels = $diff;
+		return count($diff);
 	}
 
 	/**
@@ -155,7 +206,6 @@ class AsyncJobClass
 	public function BlinkOFF()
 	{
 		$esl = new SmartESL($this->fb, $this->labels);
-		$this->blinkoff = true;
 		$this->blinkGenerator = $esl->AsyncBlinkOff();
 	}
 
@@ -164,12 +214,14 @@ class AsyncJobClass
 	 */
 	public function isBlinkoff(): bool
 	{
-		return $this->blinkoff;
+		return $this->ledParams == null;
 	}
 
 	public function GetCurrentValue()
 	{
-		return $this->blinkGenerator->current();
+		$value = $this->blinkGenerator->current();
+		$this->Opened = !is_array($value);
+		return $value;
 	}
 
 	public function Run()
@@ -181,6 +233,14 @@ class AsyncJobClass
 	{
 		return !$this->blinkGenerator->valid();
 	}
+
+	/**
+	 * @return array
+	 */
+	public function getLedParams(): array
+	{
+		return ($this->ledParams == null) ? [] : $this->ledParams;
+	}
 }
 
 class FindBoxService
@@ -203,6 +263,8 @@ class FindBoxService
 	/** @var JobManager $jobManager */
 	private $jobManager;
 
+	private $ts_ms;
+
 	public function __construct()
 	{
 		global $f3;
@@ -219,6 +281,8 @@ class FindBoxService
 			}
 		$this->labelToBlink = [];
 
+		$this->ts_ms = NULL;
+
 		$this->qs_Server = new QueueSystem();
 
 		$this->qs_Server->CreateService();
@@ -234,55 +298,80 @@ class FindBoxService
 		$this->ServiceLogger->write("Starting FindBoxService main loop", 'd/m/Y H:i:s');
 		$this->ServiceLogger->write("Opening socket listen {$f3->get('FINDBOXSERVICE.PORT')}", 'd/m/Y H:i:s');
 
-		$this->jobManager = new JobManager();
+		$this->jobManager = new JobManager($this->ServiceLogger);
+
 		while (true) {
 			$this->getCurrentQueue();
 
-			foreach($this->labelToBlink as $commandID => &$label) {
-				switch ($label->operation) {
+			$isTimeToAggregateCommands = ($this->now_ms() - $this->ts_ms) > $f3->AGGREGATE_TIMEOUT;
 
-					case QueueCommand::$Q_BLINK_OFF:
-						$labelJ = join(', ', $label->id);
-						$this->ServiceLogger->write("BlinkOff for label(s) {$labelJ} requested", 'd/m/Y H:i:s');
+			if ($isTimeToAggregateCommands && (count($this->labelToBlink) > 0)) {
 
-						$this->jobManager->RemoveLabelsFromJobs($label->id);
+				foreach($this->labelToBlink as $commandID => &$label) {
+					switch ($label->operation) {
 
-						// Rimuove il JOB se esiste
-						$asyncBlinkOFF = new AsyncJobClass($this->findBoxCore, $label->id);
-						$asyncBlinkOFF->BlinkOFF();
-						$this->jobManager->add($asyncBlinkOFF);
+						case QueueCommand::$Q_BLINK_OFF:
+							$labelJ = join(', ', $label->id);
+							$this->ServiceLogger->write("BlinkOff for label(s) {$labelJ} requested", 'd/m/Y H:i:s');
 
-						unset($this->labelToBlink[$commandID]);
+							// Rimuove il JOB se esiste
+							$asyncBlinkOFF = new AsyncJobClass($this->findBoxCore, $label->id);
+//							$asyncBlinkOFF->BlinkOFF();
+							$this->jobManager->add($asyncBlinkOFF);
 
-						break;
+							unset($this->labelToBlink[$commandID]);
 
-					case QueueCommand::$Q_BLINK_ON:
-						$labelJ = join(', ', $label->id);
-						$this->ServiceLogger->write("BlinkOn for label(s) {$labelJ} requested", 'd/m/Y H:i:s');
+							break;
 
-						$this->jobManager->RemoveLabelsFromJobs($label->id);
+						case QueueCommand::$Q_BLINK_ON:
+							$labelJ = join(', ', $label->id);
+							$this->ServiceLogger->write("BlinkOn for label(s) {$labelJ} requested", 'd/m/Y H:i:s');
 
-						$asyncBlink = new AsyncJobClass($this->findBoxCore, $label->id, $label->params);
-						$asyncBlink->BlinkON();
-						$this->jobManager->add($asyncBlink);
+							$asyncBlink = new AsyncJobClass($this->findBoxCore, $label->id, $label->params);
+//							$asyncBlink->BlinkON();
+							$this->jobManager->add($asyncBlink);
 
-						unset($this->labelToBlink[$commandID]);
+							unset($this->labelToBlink[$commandID]);
 
-						break;
+							break;
+					}
 				}
+				$this->ts_ms = NULL;
 			}
 
+//			if ($this->jobManager->count() < 1)
+//				continue;
+
+			$this->jobManager->AggregateBlinkByParams();
+
 			// Async check on JOBS
 			$this->jobManager->Run(function (AsyncJobClass $asyncBlink) {
 
+				// Start the JOB
+				if (!$asyncBlink->Opened) {
+					if ($asyncBlink->isBlinkoff())
+						$asyncBlink->BlinkOFF();
+					else
+						$asyncBlink->BlinkON();
+				}
+
 				$err = $asyncBlink->GetCurrentValue();  // Fa scattare il generator e ricava il valore
 
 				// Response RESTful ricevuta da Findbox Core?
 				if (is_array($err)) {
-					if ($this->ManageBlinkFaults($asyncBlink, $asyncBlink->getLabels(), $err)) {
+					// TODO da controllare perchè sembra che si accumulino array quadrupli
+					$this->ServiceLogger->write('JobManager->Run: '
+						. json_encode($asyncBlink->getLabels())
+						. json_encode($asyncBlink->getLedParams())
+						. ' err ' . json_encode($err['value']['value']), 'd/m/Y H:i:s');
+
+					if ($this->ManageBlinkFaults($asyncBlink, $err)) {
 						// Remove the JOB
 						return TRUE;
 					} else {
+						$labelJ = join(', ', $asyncBlink->getLabels());
+						$this->ServiceLogger->write("Restart BlinkOn/Off for label(s) {$labelJ} requested", 'd/m/Y H:i:s');
+
 						// Restart JOB if any errors
 						if ($asyncBlink->isBlinkoff())
 							$asyncBlink->BlinkOFF();
@@ -292,9 +381,7 @@ class FindBoxService
 				}
 				return FALSE;
 			});
-
 		}
-
 		return;
 	}
 
@@ -303,6 +390,24 @@ class FindBoxService
 		/** @var QueueCommand $qCommand */
 		$this->qs_Server->ServerCheckClientCommands(
 			function ($clientCommands) {
+
+				if ($clientCommands->operation == QueueCommand::$Q_BLINK_ON || $clientCommands->operation == QueueCommand::$Q_BLINK_OFF) {
+
+					if ($clientCommands->id == null) {
+						$this->ServiceLogger->write("No labels passed to BLINK_OFF", 'd/m/Y H:i:s');
+						return NULL;
+					}
+					// Remove NULL label_id if present
+					$clientCommands->id = array_filter($clientCommands->id);
+
+					// Start aggregation timer only when first blink on/off is received
+					if ($this->ts_ms == NULL)
+						$this->ts_ms = $this->now_ms();
+
+					$this->RemoveDuplicateLabels($clientCommands->id);
+
+				}
+
 				switch ($clientCommands->operation) {
 
 					case QueueCommand::$Q_GETJOBS:
@@ -319,19 +424,26 @@ class FindBoxService
 						$this->saveProduct($clientCommands);
 						break;
 
-					case QueueCommand::$Q_BLINK_ON:
 					case QueueCommand::$Q_BLINK_OFF:
 						// Split blink list by 9 items each array
-						if ($clientCommands->id == null) {
-							$this->ServiceLogger->write("No labels passed to BLINK_ON/OFF command code '{$clientCommands->operation}'", 'd/m/Y H:i:s');
-							return NULL;
-						}
-						$idsWithoutNULLs = array_filter($clientCommands->id);
-						$labelsSplitted = array_chunk($idsWithoutNULLs, 9);
-						foreach($labelsSplitted as $labels) {
-							$cmd = clone $clientCommands;
-							$cmd->id = $labels;
-							$this->labelToBlink[rand(0, 60000)] = $cmd;
+						$this->SplitArrayIn9Parts($clientCommands);
+
+						break;
+
+					case QueueCommand::$Q_BLINK_ON:
+						// filter for blinkon and regroup for jobs that has same blink parameters
+						$flt = array_filter($this->labelToBlink, function (&$item) use ($clientCommands) {
+							if ($item->operation != QueueCommand::$Q_BLINK_ON)
+								return false;
+							return count(array_diff($item->params, $clientCommands->params)) === 0;
+						});
+
+						if (count($flt) > 0) {
+							$key = array_keys($flt)[0]; // get first array key name
+							$flt[$key]->id = array_merge($flt[$key]->id, $clientCommands->id);  //merge all label id of all jobs removing duplicates too
+						} else {
+							// Split blink list by 9 items each array
+							$this->SplitArrayIn9Parts($clientCommands);
 						}
 						break;
 
@@ -346,6 +458,31 @@ class FindBoxService
 		);
 	}
 
+	/**
+	 * Return time in milliseconds
+	 *
+	 * @return float
+	 */
+	private function now_ms()
+	{
+		return round(microtime(true) * 1000);
+	}
+
+	/**
+	 * Remove the label already present in blink_on lists
+	 *
+	 * @param array $labelsToRemove
+	 */
+	private function RemoveDuplicateLabels(array $labelsToRemove)
+	{
+		$this->labelToBlink = array_filter($this->labelToBlink, function (&$item) use ($labelsToRemove) {
+			if (count(array_intersect($item->id, $labelsToRemove)) > 0) {
+				$item->id = array_diff($item->id, $labelsToRemove);
+			}
+			return count($item->id) > 0; // need to clean empty jobs due to empty label_id
+		});
+	}
+
 	/**
 	 * Send SaveProduct to Label
 	 *
@@ -355,25 +492,36 @@ class FindBoxService
 	public function saveProduct($label)
 	{
 		if ($label->operation == QueueCommand::$Q_SAVEPRODUCT) {
-			$this->findBoxCore->SaveProducts($label->id[0], $label->description, $label->params['dataFields']);
+			$retSave = $this->findBoxCore->SaveProducts($label->id[0], $label->description, $label->params['dataFields']);
 			$labelsJ = join(', ', $label->id);
-			$this->ServiceLogger->write("Save product {$labelsJ}", 'd/m/Y H:i:s');
+			$this->ServiceLogger->write("Save product {$labelsJ} RET_CODE= {$retSave['value']['code']} RET_VALUE= {$retSave['value']['value']}", 'd/m/Y H:i:s');
 			return true;
 		}
 		return false;
 	}
 
+	private function SplitArrayIn9Parts(QueueCommand $command)
+	{
+		// Split blink list by 9 items each array
+		$labelsSplitted = array_chunk($command->id, 9);
+		foreach($labelsSplitted as $labels) {
+			$cmd = clone $command;
+			$cmd->id = $labels;
+			$this->labelToBlink[rand(0, 60000)] = $cmd;
+		}
+	}
+
 	/**
 	 * @param AsyncJobClass $job
 	 * @param array $labels
 	 * @param $fbError
 	 * @return bool true if no error, false if error
 	 */
-	private function ManageBlinkFaults(AsyncJobClass &$job, array $labels, $fbError): bool
+	private function ManageBlinkFaults(AsyncJobClass &$job, $fbError): bool
 	{
 		$labelResponses = $this->findBoxCore->getLabelsFromResponse($fbError);
 		if ($labelResponses === NULL) {
-			$labelJ = join(', ', $labels);
+			$labelJ = join(', ', $job->getLabels());
 			$this->ServiceLogger->write("Label(s) {$labelJ} error removed from queue: {$fbError['value']['value']}", 'd/m/Y H:i:s');
 			return true;
 		}
@@ -391,7 +539,7 @@ class FindBoxService
 
 		// Ho finito il numero di tentativi massimi?
 		if ($job->retryForFault < 0) {  // Rimuovo dalla coda l'etichetta
-			$labelJ = join(', ', $labels);
+			$labelJ = join(', ', $job->getLabels());
 			$this->ServiceLogger->write("Label(s) {$labelJ} fatal error. Removing from queue", 'd/m/Y H:i:s');
 			return true;
 		} else {                        // Riprovo al prossimo ciclo

+ 4 - 3
src/OpenMind/FindBox/SmartESL.php

@@ -60,7 +60,8 @@ class SmartESL
 
 	public function AsyncBlinkOff(): Generator
 	{
-		return $this->AsyncBlinkSpecial(0, 0, 0, 0, 0);
+		global $f3;
+		return $this->AsyncBlinkSpecial(2, 1, 1000, 1, $f3->BLINKOFF_COLOR);
 	}
 
 
@@ -94,8 +95,8 @@ class SmartESL
 	 */
 	public function BlinkOff()
 	{
-		return $this->BlinkSpecial(0, 0, 0, 0, 0);
-
+		global $f3;
+		return $this->BlinkSpecial(2, 1, 1000, 1, $f3->BLINKOFF_COLOR);
 	}
 
 	/**