Applicato all'IIOT
Laravel Day Verona 2018
Applicato all'IIOT
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
Applicato all'IIOT
Il Mondo Industriale
APPLICAZIONI
Il Contesto
Applicato all'IIOT
Il Mondo Industriale
Copyright SENECA SRL
Telemetria e Telecontrollo
Applicato all'IIOT
Il Mondo Industriale
SCHEMA GENERICO
Logica
Locale
(PLC/RTU)
Supervisione
(SCADA)
I/O
e
Sensori
Bus
di
Campo
Datalogger
N:1
Applicato all'IIOT
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
Copyright SENECA SRL
Applicato all'IIOT
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)
Applicato all'IIOT
Il Mondo Industriale
LO SCADA
Supervisione
Applicato all'IIOT
Il Mondo Industriale
LO SCADA: Rappresentazione della Realtà
- SCADA "Nativi" / "Web"
- Origine del "Sinottico" (Mosaico)
- Target di Utenza specifico
- Codifica comunicazione ben definita
Applicato all'IIOT
IL PROGETTO
RealizzazionE
Scelte Tecnologiche
Applicato all'IIOT
Il Progetto: IDEA DI PRODOTTO
Time constrain
Investimento di pochi mesi, il prodotto è di traino delle vendite.
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
Il Progetto
Windows?
Applicato all'IIOT
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
Il Progetto
SCHEMA A BLOCCHI
Metadati
(Configurazioni)
Datastore
(Serie di tempi)
Sistema Operativo/Servizi
UI JS
Laravel
Applicato all'IIOT
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
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
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()
{
/* .. */
}
}
Non sempre è stringente per l'rtu "sapere" che il dato è valido, né che è salvato correttamente nell'immediato.
Applicato all'IIOT
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
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
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
Il Progetto
Comunicazione col sistema
FAI giraRE
HTTPD come
root...
Applicato all'IIOT
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
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
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
Datastore
BIG DATA
Applicato all'IIOT
Scelta del Datastore
Applicato all'IIOT
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
Datastore
"Big data" con MySQL?
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)
Applicato all'IIOT
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
Applicato all'IIOT
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() { /* ... */ }
}
- 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
Datastore: InfluxDB
PROBLEMATICA DELL'Aliasing
-
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
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
Datastore: InfluxDB
Largest Triangle Three Buckets
5000 samples
100 samples
250 samples
50 samples
DOWNSAMPLE
Sveinn Steinarsson (https://skemman.is/handle/1946/15343)
Applicato all'IIOT
DERIVAZIONI
RISULTATI
Progetti Derivati
Applicato all'IIOT
DERIVAZIONI
Copyright SENECA SRL
Dashboard
Applicato all'IIOT
DERIVAZIONI
Copyright SENECA SRL
SINOTTICO
Applicato all'IIOT
Derivazioni
Copyright SENECA SRL
MyBoat
- Realtime (MQTT)
- Riuso struttura di base
- Integrazione Node
- UI Solo tramite app
- Portale Laravel
Applicato all'IIOT
Derivazioni
VPN
Copyright SENECA SRL
Applicato all'IIOT
Derivazioni
https://joind.in/talk/c72fa
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,207