Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Laravel Day Verona 2018
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Chi Sono
class eppak extends MedioMan implements Veneto
{
public function identity()
{
return [
"Name" => "Alessandro",
"LastName" => "Cappellozza",
"Moniker" => "eppak",
"Email" => "alessandro.cappellozza@gmail.com"
];
}
public function job() {
return $this->r & $this->d;
}
public function company() {
return "SENECA";
}
public function alcohol()
{
return false;
}
public function alpine()
{
return false;
}
}
Alessandro Cappellozza
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5504797/logo.png)
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Mondo Industriale
APPLICAZIONI
Il Contesto
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Mondo Industriale
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5500337/energy.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5500341/water.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5500340/machines.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5500339/infrastructures.png)
Copyright SENECA SRL
Telemetria e Telecontrollo
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Mondo Industriale
SCHEMA GENERICO
Logica
Locale
(PLC/RTU)
Supervisione
(SCADA)
I/O
e
Sensori
Bus
di
Campo
Datalogger
N:1
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Mondo Industriale
Caratteristiche:
- Sono RTU / PLC
- Ram 128/256k
- Qualche Mbit di Flash
- Architettura ARM
- Con e senza I/O
- Modem (spesso 2g)
- Ethernet
- Bus di campo seriale
- Datalogger
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5500228/Z-UMTS_HD-_noombra.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5500226/Z-PASS2_IO_.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5500239/My2.png)
Copyright SENECA SRL
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5504797/logo.png)
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Mondo Industriale
Protocolli
- Modbus RTU/TCP
- MBus
- EtherCAT
- Profibus
- OPC UA/DA (COM)
- Su chiamata, CSD (Circuit Switch Data)
- TCP/UDP
- Rest HTTP
- XML/JSON per il trasporto
- MQTT
- AMPQ
- CoAP
- Binario (compressione)
INTEGRAZIONE/EVOLUZIONE
(Cambio di mentalità es. CSD)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5512719/right3.png)
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Mondo Industriale
LO SCADA
Supervisione
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5502280/file564b25ea087dc.201511171304.jpg)
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Mondo Industriale
LO SCADA: Rappresentazione della Realtà
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5518064/SIP_OLD.jpg)
- SCADA "Nativi" / "Web"
- Origine del "Sinottico" (Mosaico)
- Target di Utenza specifico
- Codifica comunicazione ben definita
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
IL PROGETTO
RealizzazionE
Scelte Tecnologiche
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Progetto: IDEA DI PRODOTTO
Time constrain
Investimento di pochi mesi, il prodotto è di traino delle vendite.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5500222/vpn_box.png)
ON PREMISE
- Volontà di avere i dati in casa
- Non voler gestire servizi esterni (costi)
- Tangibilità del prodotto
- Prodotto meglio comprensibile (confinato)
- Costo/prestazioni più certe possibili
- Resilienza all'abbonamento
- Supervisione contenuta
GENERALITA'
- Semplicità (target clienti poco skillati)
- Ricoprire uno o più ruoli dello SCADA
- Integrabilità
Vanno individuate delle tecnologie...
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Progetto
Windows?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5500377/giphy-downsized-large.gif)
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Progetto
Linux & Laravel
- Supporto ai comandi
- Disaccoppiamento dal web
- Supporto alle code
- Disaccoppiamento middleware
- "Versionamento" db con migrations
- Molti packages e supporto
- Ottimo per headless
- Compatibilità
- Riproducibilità
- Leggero (pochi fronzoli)
- Vasto supporto software
- Sicuro
L'approccio web solleva problematiche di tempi di esecuzione delle richieste quindi sono necessarie elaborazioni "batch"
Debian 8
LARAVEL 5
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Progetto
SCHEMA A BLOCCHI
Metadati
(Configurazioni)
Datastore
(Serie di tempi)
Sistema Operativo/Servizi
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5500221/vpnbox_frontale.jpg)
UI JS
Laravel
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Progetto
PROTOCOLLO
/* RICEVO */
class ProtocolController extends Controller
{
use CommandBus;
public function receive(Request $request, DataBus $bus)
{
$data = $request->getContent();
$bus->dispatch(new DeivceData($data));
return response()->json([ 'err' => 0 ]);
}
}
/* RICEVO E SERVO */
class ProtocolController extends Controller
{
use CommandBus;
public function receive(Request $request)
{
$data = $request->getContent();
$deviceData = new DeivceData($data);
$this->dispatch($deviceData);
return response()->json([
'err' => 0,
'act' => CommandQueue::actions($data) /* LOGICA DI ESTRAZIONE */
]);
}
}
-
Basato su HTTP
-
Payload JSon
- Sincrono
- Consente bidirezionalità solo nel caricamento del dato
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Progetto
DISTINZIONE DEL TIPO DI CHIAMATA
class DeivceData {
private $data = null;
public function __construct($data)
{
$this->data = $data;
}
public function data() { return $this->data; }
}
class DeivceDataHandler {
private $data = null;
private $ds = null;
public function __construct(DatastoreManager $ds, DeivceData $data)
{
$this->data = $data;
$this->ds = $ds;
}
public function handle() {
$parsed = new PacketParser($this->data);
$ds->store($parsed);
}
}
class PacketParser {
private $data = null;
public function __construct($data)
{
$this->data = new JSON($data);
}
public function isLog() { return $this->data->has('log'); }
public function isCfg() { return $this->data->has('cfg'); }
public function isEvent() { return $this->data->has('ev'); }
public function isAck() { return $this->data->has('ack'); }
public function uuid() {
return $this->data->has('uuid') ?: $this->data->getUuid;
}
}
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Progetto
PROCESSING CODA
class ProcessData implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $ds = null;
private $data = null;
public function __construct(DatastoreManager $ds, DevcieData $data)
{
/* .. */
}
public function handle()
{
/* .. */
}
}
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5500221/vpnbox_frontale.jpg)
Non sempre è stringente per l'rtu "sapere" che il dato è valido, né che è salvato correttamente nell'immediato.
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Progetto
/* ..*/
$this->app->bind(
'App\Datastore\Contracts\Collector', 'App\Datastore\DataCollector'
);
namespace App\Datastore;
class DataCollector implements Contracts\Collector {
public function __construct(Alarms $alarms, Datastore $ds) { /* .. */ }
public function store($data) {
if($this->data->isLog()) {
$processed = $logProcessor->parse($data);
$ds->write($processed);
$alarms->dispatch($processed);
}
}
}
namespace App\Datastore\Contracts;
interface Collector {
public function store($data);
}
namespace App\Datastore;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
class LogProcessor {
public function parse($data) { /* LOGICA DEL DATO */ }
}
DATASTORE
PROCESSORE
Scatenare eventi
Calcolare campi virtuali, cambi scala, sommatorie (...)
namespace App\Dispatcher;
class Alarms {
public function dispatch($data) { /* DISPATCH MESSAGGI */ }
}
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Progetto
DIFFERENZE CON WEB APP STANDARD
Procedure sensibili
- Backup e Restore
- Upgrade
- Comunicare col sistema operativo (in maniera sicura)
Il prodotto deve essere ripristinabile in qualsiasi stato e non deve avere necessità della ui per la manutenzione base
Le procedure devono girare senza ausili esterni (rete)
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Progetto
Bootloader
Viene mutuato dal monto embed il concetto di bootloader che renda indipendente la app da possibili guasti e/o difetti di aggiornamento
# crontab
@reboot sh /var/www/bin/bootloader.sh
#!/bin/bash
sleep 15
/usr/bin/php /var/www/bootloader/upgrade.php
/usr/bin/php /var/www/bootloader/restore.php
// UPGRADE
<?php
$this->loadEnv();
if (file_exists('...') {
$this->stopServices();
$this->upgrade();
$this->migrate();
$this->startServices();
}
// RESTORE
<?php
$this->loadEnv();
if (file_exists('...') {
$this->stopServices();
$this->upgrade();
$this->migrate();
$this->startServices();
}
- Output rediretto in console
- Output salvato su log
- Procedura unattended
- Gira con privilegi elevati
- Pochissime dipendenze
- Procedura valida per restore/upgrade (simili)
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Progetto
Comunicazione col sistema
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5515308/post-272-photo.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5515310/41AUw0wNduL._SX425_.jpg)
FAI giraRE
HTTPD come
root...
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Progetto
Comunicazione col sistema
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <syslog.h>
int
main (int argc, char *argv[])
{
int res = 1;
char buff[1024];
setuid (0);
if (/* SECURITY CHECK */)
{
syslog(LOG_INFO, "RUN SOMETHING");
sprintf(buff, "/SOME/PATH/BIN");
system(buff);
syslog(LOG_INFO, buff);
res = 0;
}
return res;
}
COME BIN
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Progetto
Comunicazione col sistema
class System
{
private $exec = false;
private $jobid = 0;
public function _construct()
{
declare(ticks=1);
pcntl_async_signals(true);
pcntl_signal(SIGUSR1, [$this, 'receivedSignal']);
}
public function apply()
{
$pid = posix_getpid();
$this->exec = false;
$this->jobid = Queue::push(new \App\Jobs\UpdateSystemSettings($pid));
$ts = time();
while(time() - $ts < SYSTEM_SETTINGS_TIMEOUT) {
usleep(250);
if($this->exec) { return true; }
}
return false;
}
private function receivedSignal($signo) {
// CHECK $this->jobid
$this->exec = true;
}
}
COME JOB
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Il Progetto
Backup
class Backup implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $clt = null;
private $meta = null;
private $settings = null;
public function __construct(Settings $settings, System $system, Collector $clt, MetaData $meta)
{
$this->settings = $settings;
$this->system = $system;
$this->clt = $clt;
$this->meta = $meta;
}
public function handle()
{
$path= $this->settings->backupDestination();
$this->meta->backup($path);
$this->clt->backup($path);
$zipped = $this->system->zip($path);
$this->system->move($zipped);
}
}
Necessita <<solo>> di privilegi elevati
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Datastore
BIG DATA
Applicato all'IIOT
Scelta del Datastore
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Datastore
"Big data is like teenage sex: everyone talks about it, nobody really knows how to do it, everyone thinks everyone else is doing it, so everyone claims they are doing it..."
Dan Ariely
http://fb.me/1r54f62oU
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Datastore
"Big data" con MySQL?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5512804/node_db_mysql__767789.png)
NUMERO DI CAMPIONI:
50 (device) x
100 (tag) x
1440 (minuti/g) x
720(giorni) x
=~ 5.2 x 10^9
Dai test
- Le query cominciavano a rallentare vistosamente dopo i 500k record
- Difficoltà di trovare uno schema che coniugasse prestazioni e generalità
- Modalità di estrazione del dato (ampi frame temporali)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5512719/right3.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5512719/right3.png)
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Datastore
Di che Tipo di dato ho bisogno (e come)?
- Per lo più float 64: anche i booleani spesso sono compattati in bitmask
- Confine temporale: alcuni tipi di dati non hanno quasi mai necessità di span larghi
- Downsampling (1): rappresentare ampi intervalli con pochi dati
- Downsampling (2): risparmio di banda tra client/server (e nella rappresentazione)
- Rielaborazione del dato: necessità di estrazione di un unico dato rappresentativo da un bucket
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5521926/Senza_nome.png)
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Datastore: InfluxDB
namespace App\Datastore\Contracts;
interface Datastore {
public function read($vars, $tags, $from, $to);
public function last($vars, $tags);
public function history($vars, $tags, $from, $to, $span = null, $agg = null);
public function write($values, $tags);
public function setRetention($days);
public function getSize();
public function getVersion();
}
namespace App\Datastore;
class InfluxDatastore implements Contracts\Datastore {
public function read($vars, $tags, $from, $to) { /* ... */ }
public function last($vars, $tags) { /* ... */ }
public function history($vars, $tags, $from, $to, $span = null, $agg = null) { /* ... */ }
public function write($values, $tags) { /* ... */ }
public function setRetention($days){ /* ... */ }
public function getSize() { /* ... */ }
public function getVersion() { /* ... */ }
}
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497602/Influxdb_logo_1.png)
- Semplicità e completezza
- Scritto in go
- Integrazione con PHP
- Manutenzione
- Installazione semplice
- Prestante
- Query Continue
- SSD obbligatorio
- Alias sul downsample
- Cluster non open
Test con i3 (2GB)/SSD: 5.2 Mld campioni, estrazione 8 tracce (media) su periodo random fino a due anni
=~ 14sec di media
+
-
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Datastore: InfluxDB
PROBLEMATICA DELL'Aliasing
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5521858/DDWO3.png)
-
Insito nella procedura di downsampling
- Non tutti i dati lo subiscono: es. monotone crescenti.
- I booleani hanno bisogno di una rappresentazione a parte (es duty cycle).
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Datastore: InfluxDB
Largest Triangle Three Buckets
public class InfluxDatastoreLTTB extends InfluxDatastore {
public function history($vars, $tags, $from, $to, $span = null, $agg = null); {
if ($agg == "LTTB") {
$data = $this->read($vars, $tags, $from, $to);
return DataProcess::LTTB($data, MAX_SAMPLES);
} else {
return parent::history($vars, $tags, $from, $to, $span, $agg);
}
}
}
/* ... */
public function LTTB($data, $thr = MAX_SAMPLES)
{
$downampled = [];
$prev = $data[0];
for($b=1; $b<count($blocks)-1; $b++) {
$rank = 0;
$block = $blocks[$b];
$avg = $this->avg($blocks[$b + 1]);
for($i=0; $i<count($block); $i++) {
$rank = $this->getRank($block[$i], $avg, $prev);
if($downampled[$b] < $rank) {
$downampled[$b] = $rank;
$prev = $rank;
}
}
}
return $downampled;
}
private function makeBlocks($data) { /* DIVISION + LAST BLOCK */ }
private function avg($block) { /* .. */ }
private function getRank($sample, $avg, $prev) { /* .. */ };
- Consuma RAM: i campioni vengono caricati blocco.
- Consuma CPU: l'elaborazione è esaustiva.
- Consuma IOPS: l'estrazione è onerosa.
Il tutto è proporzionato al timespan in questione.
(Mockup)
Però il risultato è visivamente notevole...
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Datastore: InfluxDB
Largest Triangle Three Buckets
5000 samples
100 samples
250 samples
50 samples
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5504877/samples.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5504900/left-arrow-icon-93019.png)
DOWNSAMPLE
Sveinn Steinarsson (https://skemman.is/handle/1946/15343)
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
DERIVAZIONI
RISULTATI
Progetti Derivati
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
DERIVAZIONI
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5521950/dashboard.png)
Copyright SENECA SRL
Dashboard
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
DERIVAZIONI
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5521951/synoptic.png)
Copyright SENECA SRL
SINOTTICO
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Derivazioni
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5540523/barca_My.jpg)
Copyright SENECA SRL
MyBoat
- Realtime (MQTT)
- Riuso struttura di base
- Integrazione Node
- UI Solo tramite app
- Portale Laravel
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5500239/My2.png)
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Derivazioni
VPN
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5540550/vpn.jpg)
Copyright SENECA SRL
Applicato all'IIOT
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5497535/Laravel_logo_wordmark_logotype.png)
Derivazioni
https://joind.in/talk/c72fa
![](https://s3.amazonaws.com/media-p.slid.es/uploads/963528/images/5521944/chart.png)
Laravel applicato all'IIOT
alessandro.cappellozza@gmail.com
Laravel Day 2018 Verona - Alessandro Cappellozza
By Alessandro Cappellozza
Laravel Day 2018 Verona - Alessandro Cappellozza
Laravel Applicato all'IIOT - Laravel Day 2018 Verona - Alessandro Cappellozza
- 1,164