CNX Software recensisce i primi passi con il kit GL-S200 Thread Border Router
La scorsa settimana abbiamo esaminato l'hardware del kit GL.iNet GL-S200 Thread Border Router con tre Thread Dev Board nRF52840, e ora ho avuto il tempo di lavorare con il kit: racconterò quindi la mia esperienza iniziale nella seconda parte della recensione.
Configurazione iniziale GL-S200
Ho collegato la porta WAN allo switch Ethernet, a sua volta collegato al modem router, e la porta LAN al portatile, per accedere all'interfaccia web tramite l'indirizzo IP predefinito (192.168.8.1). GL-S200 utilizza lo stesso pannello di amministrazione degli altri router GL.iNet, come il router Beryl AX che abbiamo recensito all'inizio dell'anno.
La procedura guidata permette di scegliere lingua e password del pannello. Poi accedi al familiare pannello GL.iNet 4.x.x.
Dopo la procedura guidata, il sistema dovrebbe collegarsi automaticamente a Internet e il LED RGB centrale diventare verde.
Rete Thread
Il primo passaggio consiste nell'andare su THREAD MESH nel pannello sinistro per abilitare la rete Thread.
Facendo clic su Enable, otterrai tre indirizzi IPv6:
-
Link-Local Address – tutte le interfacce raggiungibili con una singola trasmissione radio
-
Local Address –
Tutte le interfacce raggiungibili dall'esterno di una rete Thread (sembra chiamarsi Global Address nella documentazione OpenThread)Aggiornamento GL-iNet: OT/OTBR non supporta ancora l'accesso Internet IPv6 globale.
Puoi leggere la risposta ufficiale Openthread: https://github.com/openthread/openthread/discussions/8794
L'indirizzo locale è un indirizzo OMR (off-mesh-routable), con cui puoi accedere ai dispositivi Thread dal lato WiFi/Ethernet.
-
Mesh-Local EID – tutte le interfacce raggiungibili nella stessa rete Thread
Se hai dispositivi Thread tuoi, puoi passare al menu Thread Commissioning e inserire l'EUI64 dei dispositivi e la chiave precondivisa. GL.iNet ha però creato una sezione più semplice nell'interfaccia web per gestire le proprie Thread Dev Board, abbreviate TBD.
Nella GL DEV BOARD->Devices possiamo fare clic su Add Devices pulsante, poi Applica. Premendo SW2 su una scheda, viene aggiunta automaticamente a GL-S200 Thread Border Router.
Selezioniamo il tipo A0+A1 e diamo un nome alla scheda. Possiamo ripetere l'operazione per le altre due schede e vedremo nel pannello di amministrazione i valori di temperatura, pressione, umidità e illuminamento di tutte e tre.
aggiornamento firmware GL-S200
Mi sono ricordato di qualcosa: GL.iNet aveva fornito nuovo firmware GL-S200 da installare manualmente. Facciamolo da "SYSTEM->Upgrade".
Il pannello mostra 4.1.3 release 5 come aggiornato perché il nuovo firmware non è sul server OTA. Ma ho ricevuto un link di download con firmware più recente compilato il 6 marzo 2023.
Ho scaricato il file, aperto la sezione Local Upgrade e caricato il file sul GL-S200 Thread Border Router.
La verifica è riuscita, quindi ho fatto clic su Installa, infine ho ottenuto il firmware 4.1.3 Release 7 installato sul mio dispositivo.
Aggiornamento firmware delle Thread Dev Board
Durante l'aggiornamento firmware ho notato che anche le Thread Dev Board potevano passare da 1.1.5 a 1.1.9. Ho proceduto e tutto ha funzionato perfettamente.
Topologia Thread
Thread usa reti mesh: i nodi vicini si collegano al router direttamente, quelli fuori portata o con segnale debole possono agire a loro volta da router. Con tutti i dispositivi sulla scrivania…
… la rete aveva una topologia a stella, come previsto.
Ho provato a distanziare le schede e disporle in linea, mettendone persino una all'esterno.
Possiamo individuare facilmente quella all'aperto grazie a temperatura e illuminamento maggiori.
Facendo clic su “Self” nel diagramma della topologia possiamo anche vedere l'intensità del segnale del nodo collegato al Thread Border Router. Tuttavia, non sono mai riuscito a utilizzare la Thread Dev Board come router. Siamo persino usciti a camminare per provare ad allontanarci dalla copertura o almeno ottenere un segnale più debole, ma la rete mesh non funzionava come mi aspettavo. Ho quindi chiesto agli ingegneri GL.iNet, che mi hanno risposto che era necessario un firmware per router Thread:
Attualmente il nostro firmware TBD predefinito è del tipo dispositivo finale Thread e i dispositivi non possono collegarsi direttamente tra loro. Forniremo il firmware router Thread e la relativa guida di installazione TBD più tardi oggi.
Mi hanno inviato il firmware router e anche l'utility mcumgr per Linux e Windows.
Ho collegato una delle Thread Dev Board a un PC Linux (Ubuntu 22.04):
print(“Hello World”) verrà visualizzato come print(“Hello World”)`.
$ bt -l
port | age (sec) | device | driver | description
------+------------+------------+------------------+----------------------
* 0 | 1137 | ttyUSB0 | ch341-uart | USB Serial
La porta seriale è rilevata, quindi posso verificare lo stato firmware con il comando:
$ sudo ./mcumgr --conntype serial --connstring=/dev/ttyUSB0,baud=460800 image list
Error: NMP timeout
jaufranc@cnx-laptop-4:~/edev/GL-S200/TBD upgrade$ sudo ./mcumgr --conntype serial --connstring=/dev/ttyUSB0,baud=460800 image list
Images:
image=0 slot=0
version: 1.1.9
bootable: true
flags: active confirmed
hash: 88b4725af7975e0b60915c320a82082bb2dda923b736f0e31d2c7d4d67cac3d3
image=0 slot=1
version: 1.1.5
bootable: true
flags:
hash: 4d8548e6910e7214d8325a7d1a49a8390fb25cce983bdb0b15bfecc657f7860b
Split status: N/A (0)
Il primo tentativo è fallito con l'errore “NMP timeout”, ma il secondo è riuscito. Possiamo vedere il firmware 1.1.9 aggiornato nel pannello di amministrazione nello slot 0 e il precedente firmware 1.1.5 nello slot 1. Ora posso provare a installare il firmware router:
$ sudo ./mcumgr --conntype serial --connstring=/dev/ttyUSB0,baud=460800 image upload GL-Thread-Dev-Board-FTD-OTA-v1.1.9.bin
426.58 KiB / 426.58 KiB [========================] 100.00% 8.93 KiB/s 47s
Done
Controlliamo di nuovo:
$ sudo ./mcumgr --conntype serial --connstring=/dev/ttyUSB0,baud=460800 image list
Images:
image=0 slot=0
version: 1.1.9
bootable: true
flags: active confirmed
hash: 88b4725af7975e0b60915c320a82082bb2dda923b736f0e31d2c7d4d67cac3d3
image=0 slot=1
version: 1.1.9
bootable: true
flags:
hash: 7dbb8a9867a000bb968099593bc1f6c2c7bb28ab458719f499364c4a77feca9f
Split status: N/A (0)
Done
Il firmware nello slot 0 è quello attivo; nello slot 1 si trova la versione Router appena installata. Possiamo passare al nuovo firmware così:
sudo ./mcumgr --conntype serial --connstring=/dev/ttyUSB0,baud=460800 image test 7dbb8a9867a000bb968
Possiamo quindi riavviare la scheda e verificare che il nuovo firmware con hash che inizia con 7dbb sia nello slot 0:
$ sudo ./mcumgr --conntype serial --connstring=/dev/ttyUSB0,baud=460800 image list
Images:
image=0 slot=0
version: 1.1.9
bootable: true
flags: active confirmed
hash: 7dbb8a9867a000bb968099593bc1f6c2c7bb28ab458719f499364c4a77feca9f
image=0 slot=1
version: 1.1.9
bootable: true
flags:
hash: 88b4725af7975e0b60915c320a82082bb2dda923b736f0e31d2c7d4d67cac3d3
Split status: N/A (0)
Dopo aver aggiunto nuovamente la scheda al pannello di amministrazione, possiamo vedere il Thread Leader (GL-S200), due dispositivi finali e un router (la scheda su cui abbiamo appena installato il firmware router).
Nessun End Device è collegato a Board 1 perché sono tutti sulla scrivania e collegati a GL-S200. Ho spostato Board 1 e un End Device in un'altra stanza, a 12 metri da GL-S200 Thread Border Router, ma la topologia non è cambiata. La connessione sembra persistente: un nodo Thread passa a un altro Router solo fuori portata, non in base al solo segnale.
Ma quando ho spento e riavviato GL-S200, i due dispositivi finali si erano ricollegati al router Board 1, che ora era il “Thread Leader” della rete.
Funziona davvero. Non me l'aspettavo così: Board 2 è a 10 centimetri da GL-S200 Thread Border Router (self), Board 1 a 12 metri, ma Board 2 non si ricollega a GL-S200 nemmeno dopo un po'. Finché la connessione resta attiva, un nodo Thread non passa a un altro router anche se più vicino e con segnale migliore; immagino sia sensato per l'autonomia.
Ho portato Board 2 (End Device) e Board 1 (Router) fuori dalla portata di GL-S200, acceso prima Board 1 e poi Board 2 per associarle e sono tornato a casa. Ha funzionato: nello schema sopra Board 2 si collega a GL-S200 "Thread Leader" tramite Board 1 che agisce da router.
Informazioni sulla GL Thread Dev Board
Con i tre puntini in Action di un dispositivo trovi Device Detail, View Records, Edit Device, Get Code e Reset Device.
Informazioni dispositivo
Otterremo EUI-64, nome, indirizzo IPv6, indirizzo MAC esteso (64 bit anziché i consueti 48 bit), versione del firmware e dati dei sensori.
Visualizza registrazioni
Dopo oltre 24 ore ho aperto View Records per vedere i grafici dei sensori di una scheda.
Sembra quasi tutto corretto, ma in basso a sinistra ci sono valori alle 9 pm e il grafico inizia solo alle 11 pm, per qualche motivo. Succede su tutte le schede.
Nel grafico orario appare ancora peggio. Sembra un errore di visualizzazione anziché la mancanza di punti dati, perché sul lato sinistro possiamo sempre ottenere un punto dati.
Esempi di codice
La sezione “Get Code” potrebbe essere la più importante se vuoi monitorare e controllare i tuoi dispositivi Thread, grazie ai cinque esempi di codice forniti.
Colleghiamoci a GL-S200 Thread Border Router via SSH per gli esempi. Iniziamo leggendo i dati dei sensori.
root@GL-S200:~# /usr/bin/demo_get_sensor_data
1 dev_id=9483c44004df0679 connected=1 temperature=31.300811 humidity=43.409729 brightness=0 pressure=97.817392
2 dev_id=9483c47d79c19475 connected=1 temperature=32.742767 humidity=53.620910 brightness=0 pressure=97.814472
3 dev_id=9483c4ec736c4f68 connected=1 temperature=31.292800 humidity=42.652893 brightness=0 press
Possiamo scegliere un dispositivo specifico tramite EUI-64:
root@GL-S200:~# /usr/bin/demo_get_sensor_data 9483c44004df0679
dev_id=9483c44004df0679 connected=1 temperature=31.300811 humidity=43.409729 brightness=0 pre
Ecco il codice sorgente come riferimento:
#!/bin/sh
# Note, this file is stored in /usr/bin/demo_get_sensor_data
# Usage: demo_get_sensor_data <dev_id>
# It will print all sensor data if <dev_id> is null, and the <dev_id> is the EUI64 of the device, which saved in /etc/config/thread_devices
. /usr/share/libubox/jshn.sh
dev_id=$1
if [ -z "$dev_id" ]; then
res=$(curl -s localhost/rpc -d '{"jsonrpc":"2.0","id":"0","method":"call","params":["","gw","get_device_list",{}]}')
json_init
json_load "$res"
json_select result
json_select device_list
idx=1
while json_is_a ${idx} object; do
json_select ${idx}
json_get_var dev_id dev_id
json_get_var connected connected
json_select dev_data
json_get_var val_temp temperature
json_get_var val_humi humidity
json_get_var val_brightness brightness
json_get_var val_pressure pressure
echo "$idx dev_id=$dev_id connected=$connected temperature=$val_temp humidity=$val_humi brightness=$val_brightness pressure=$val_pressure"
json_select ..
json_select ..
idx=$((idx + 1))
done
else
res=$(curl -s localhost/rpc -d "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"call\",\"params\":[\"\",\"gw\",\"get_device_status\",{\"dev_id\":\"$dev_id\"}]}")
json_init
json_load "$res"
json_select result
json_get_var dev_id dev_id
json_get_var connected connected
json_select dev_data
json_get_var val_temp temperature
json_get_var val_humi humidity
json_get_var val_brightness brightness
json_get_var val_pressure pressure
echo "dev_id=$dev_id connected=$connected temperature=$val_temp humidity=$val_humi brightness=$val_brightness pressure=$val_pressure"
fi
Proviamo gli altri esempi.
ls /usr/bin/demo*
/usr/bin/demo_control_gpio /usr/bin/demo_sensor_trigger
/usr/bin/demo_control_led /usr/bin/demo_user_action_trigger
/usr/bin/demo_get_sensor_data
Il secondo esempio controlla i due LED RGB della scheda selezionata tramite il suo ID dispositivo EUI-64:
root@GL-S200:~# /usr/bin/demo_control_led 9483c44004df0679
LED OFF
LED ON
LED OFF
LED TOGGLE
Changle LED Color to Red light
Changle LED Color to Orange light
Changle LED Color to Yellow light
Changle LED Color to Green light
Changle LED Color to Blue light
Changle LED Color to Indigo light
Changle LED Color to Purple light
Changle LED Color to White light
Ecco una breve dimostrazione video.
L'esempio GPIO imposta I/O in modalità uscita, poi basso e alto, sempre per una scheda specifica:
root@GL-S200:~# /usr/bin/demo_control_gpio 9483c44004df0679
Get GPIO Status
GPIO 0.15: 0
GPIO 0.16: 0
GPIO 0.17: 0
GPIO 0.20: 0
Set GPIO 0.15/0.16/0.17/0.20 to output low level
Get GPIO Status
GPIO 0.15: 0
GPIO 0.16: 0
GPIO 0.17: 0
GPIO 0.20: 0
Set GPIO 0.15/0.16/0.17/0.20 to output high level
Get GPIO Status
GPIO 0.15: 1
GPIO 0.16: 1
GPIO 0.17: 1
GPIO 0.20: 1
Gli ultimi due esempi per LED e GPIO usano coap_cli, una "piccola implementazione CoAP"; per spegnere i LED:
coap_cli -B 2 -N -e "$ctl_cmd_led_off" -m put coap://[$addr]/cmd 1>/dev/null 2>/
utilizzo di coap_cli:
root@GL-S200:~# coap_cli
coap_cli v4.2.1 -- a small CoAP implementation
Copyright (C) 2010-2019 Olaf Bergmann <bergmann@tzi.org> and others
TLS Library: None
Usage: coap_cli [-a addr] [-b [num,]size] [-e text] [-f file] [-l loss]
[-m method] [-o file] [-p port] [-r] [-s duration] [-t type]
[-v num] [-A type] [-B seconds] [-K interval] [-N] [-O num,text]
[-P addr[:port]] [-T token] [-U]
[[-k key] [-u user]]
[[-c certfile] [-C cafile] [-R root_cafile]] URI
URI can be an absolute URI or a URI prefixed with scheme and host
General Options
-a addr The local interface address to use
-b [num,]size Block size to be used in GET/PUT/POST requests
(value must be a multiple of 16 not larger than 1024)
If num is present, the request chain will start at
block num
-e text Include text as payload (use percent-encoding for
non-ASCII characters)
-f file File to send with PUT/POST (use '-' for STDIN)
-l list Fail to send some datagrams specified by a comma
separated list of numbers or number ranges
(for debugging only)
-l loss% Randomly fail to send datagrams with the specified
probability - 100% all datagrams, 0% no datagrams
-m method Request method (get|put|post|delete|fetch|patch|ipatch),
default is 'get'
-o file Output received data to this file (use '-' for STDOUT)
-p port Listen on specified port
-r Use reliable protocol (TCP or TLS)
-s duration Subscribe to / Observe resource for given duration
in seconds
-t type Content format for given resource for PUT/POST
-v num Verbosity level (default 3, maximum is 9). Above 7,
there is increased verbosity in GnuTLS logging
-A type Accepted media type
-B seconds Break operation after waiting given seconds
(default is 90)
-K interval send a ping after interval seconds of inactivity
-N Send NON-confirmable message
-O num,text Add option num with contents text to request. If the
text begins with 0x, then the hex text is converted to
binary data
-P addr[:port] Use proxy (automatically adds Proxy-Uri option to
request)
-T token Include specified token
-U Never include Uri-Host or Uri-Port options
PSK Options (if supported by underlying (D)TLS library)
-k key Pre-shared key for the specified user
-u user User identity for pre-shared key mode
PKI Options (if supported by underlying (D)TLS library)
-c certfile PEM file containing both CERTIFICATE and PRIVATE KEY
This argument requires (D)TLS with PKI to be available
-C cafile PEM file containing the CA Certificate that was used to
sign the certfile. This will trigger the validation of
the server certificate. If certfile is self-signed (as
defined by '-c certfile'), then you need to have on the
command line the same filename for both the certfile and
cafile (as in '-c certfile -C certfile') to trigger
validation
-R root_cafile PEM file containing the set of trusted root CAs that
are to be used to validate the server certificate.
The '-C cafile' does not have to be in this list and is
'trusted' for the verification.
Alternatively, this can point to a directory containing
a set of CA PEM files
Examples:
coap-client -m get coap://[::1]/
coap-client -m get coap://[::1]/.well-known/core
coap-client -m get coap+tcp://[::1]/.well-known/core
coap-client -m get coaps://[::1]/.well-known/core
coap-client -m get coaps+tcp://[::1]/.well-known/core
coap-client -m get -T cafe coap://[::1]/time
echo -n 1000 | coap-client -m put -T cafe coap://[::1]/time -f -
La demo di attivazione dell'azione riporta lo stato della manopola:
root@GL-S200:~# /usr/bin/demo_user_action_trigger 9483c44004df0679
2023/03/19 17:38:14 info (/usr/bin/demo_user_action_trigger:34) 9483c44004df0679: Press the knob.
2023/03/19 17:38:16 info (/usr/bin/demo_user_action_trigger:34) 9483c44004df0679: Press the knob.
2023/03/19 17:38:18 info (/usr/bin/demo_user_action_trigger:32) 9483c44004df0679: Turn the knob forward
2023/03/19 17:38:19 info (/usr/bin/demo_user_action_trigger:32) 9483c44004df0679: Turn the knob forward
2023/03/19 17:38:20 info (/usr/bin/demo_user_action_trigger:32) 9483c44004df0679: Turn the knob forward
2023/03/19 17:38:20 info (/usr/bin/demo_user_action_trigger:32) 9483c44004df0679: Turn the knob reverse
2023/03/19 17:38:21 info (/usr/bin/demo_user_action_trigger:32) 9483c44004df0679: Turn the knob reverse
2023/03/19 17:38:21 info (/usr/bin/demo_user_action_trigger:32) 9483c44004df0679: Turn the knob reverse
2023/03/19 17:38:23 info (/usr/bin/demo_user_action_trigger:34) 9483c44004df0679: Press the knob.
2023/03/19 17:38:25 info (/usr/bin/demo_user_action_trigger:32) 9483c44004df0679: Turn the
Il codice si basa sul binario /usr/bin/eco [Aggiornamento: sembra essere il progetto di interprete eco-lua Lua , vedi i commenti]:
#!/usr/bin/env eco
-- Note, this file is stored in /usr/bin/demo_user_action_trigger, It listens for events reported when the user operates the knob.
-- Usage: demo_sensor_trigger
local ubus = require 'eco.ubus'
local sys = require 'eco.sys'
local cjson = require 'cjson'
local log = require "glog"
local OPT_TURNING_THE_KNOB = 1
local OPT_PRESS_THE_KNOB = 2
log.level(log.LOG_INFO)
sys.signal(sys.SIGINT, function()
print('
Got SIGINT, now quit')
eco.unloop()
end)
local con, err = ubus.connect()
if not con then
error(err)
end
con:listen('user_active_trigger', function(ev, msg)
local event_data = cjson.encode(msg)
log.debug('Recievd user active trigger ' .. ev .. ' ' .. event_data)
local trigger, operation, direction = msg.trigger, msg.operation, msg.direction
if operation == OPT_TURNING_THE_KNOB then
log.info(trigger .. ': Turn the knob ' .. direction)
elseif operation == OPT_PRESS_THE_KNOB then
log.info(trigger .. ': Press the knob.')
else
log.err('Unknown operation!')
end
end)
Lo stesso vale per l'esempio di attivazione tramite sensore, che monitora il sensore PIR di tutte le Thread Dev Board collegate al GL-S200 Thread Border Router:
root@GL-S200:~# /usr/bin/demo_sensor_trigger
2023/03/19 17:47:46 info (/usr/bin/demo_sensor_trigger:31) 9483c44004df0679: Human body detected.
2023/03/19 17:47:46 info (/usr/bin/demo_sensor_trigger:31) 9483c4ec736c4f68: Human body detected.
2023/03/19 17:47:49 info (/usr/bin/demo_sensor_trigger:31) 9483c4ec736c4f68: Human body detected.
2023/03/19 17:47:52 info (/usr/bin/demo_sensor_trigger:31) 9483c44004df0679: Human body detected.
2023/03/19 17:48:15 info (/usr/bin/demo_sensor_trigger:31) 9483c47d79c19475: Human body detected.
Tutti questi esempi possono aiutarti a iniziare a creare i tuoi script.
“Automations” di GL-S200
La sezione GL DEV BOARDS include anche una sezione “Automations”.
Proverò a controllare i LED RGB di due Thread Dev Board usando la manopola sulla terza scheda rimanente.
Dopo il nome dell'automazione scegliamo l'azione utente e la scheda manopola: "Board 2".
Ho selezionato “Turning the knob”, poi “Device(s) Action”.
Poiché voglio controllare le altre due schede, ho selezionato “Board 1” e “Board 2”.
L'unica opzione è “Change Color”: selezioniamola e facciamo clic su Apply.
Ma non funziona: i LED RGB restano spenti qualunque sia la direzione in cui giro la manopola. Ho scoperto che dovevano essere accesi prima di cambiare i colori, quindi ho creato un'altra automazione per accenderli o spegnerli premendo la manopola.
Ora funziona.
La sezione Automation supporta anche webhook, quindi ho deciso di creare un'automazione che mi avvisi su Discord quando viene rilevato movimento. Ho creato un server Discord e ottenuto un URL Webhook (https://discord.com/api/webhooks/xxxx) seguendo le istruzioni su Discord.
Poi ho creato un'altra automazione selezionando Sensor Trigger…
… “Human Body Detected”, cioè rilevata una persona: significa che il sensore di movimento PIR è stato attivato
… e “Webhook”.
Ho aggiunto l'URL Webhook, selezionato Json e inserito contenuti come:
{"content":"OMG! Somebody has just entered the bedroom!"}
Infine ho fatto clic su Applica e ho ripetuto la stessa procedura per rilevare il movimento in cucina e in ufficio.
Ora posso aprire Discord e camminare per casa per attivare i sensori PIR delle tre schede.
Successo! La sezione automazione è interessante, ma sembra funzionare solo con le Thread Dev Board GL.iNet. Ho chiesto se sarebbe stato condiviso il codice per adattare la soluzione ai propri dispositivi Thread, ma non ho ricevuto risposta a quella domanda.
Varie
Come gli altri dispositivi di rete GL.iNet, GL-S200 supporta GoodCloud per l'accesso remoto, ma l'utilità è limitata perché le parti Thread e Bluetooth non sono supportate.
Inizialmente pensavo che il pulsante Mode Switch servisse a passare da BLE a Thread, ma come nei router precedenti può essere impostato per attivare o disattivare WireGuard o OpenVPN.
Per mancanza di tempo non ho testato Bluetooth, ma mi aspetto interfaccia ed esperienza simili al bridge GL-S10 da BLE a MQTT che ho recensito l'anno scorso.
Un'esperienza interessante: ringrazio GL.iNet per il kit Thread Border Router GL-S200 inviato per valutazione e beta test. Il kit ricevuto si può preordinare per $154.00 più spedizione, ma se hai già i tuoi nodi Thread, allora il solo GL-S200 è venduto a $79 durante i preordini, dopodiché il prezzo sarà $99.
|
Jean-Luc Aufranc (CNXSoft)Jean-Luc ha avviato CNX Software nel 2010 come attività a tempo parziale, prima di lasciare il lavoro di responsabile dell'ingegneria software e iniziare a scrivere notizie e recensioni quotidiane a tempo pieno nel 2011. |
Informazioni su GL.iNet
Fondata nel 2010, GL.iNet è un fornitore leader di router innovativi e soluzioni di rete. Dai router da viaggio compatti ai KVM remoti all'avanguardia, GL.iNet offre tecnologie di rete pluripremiate progettate per garantire prestazioni e sicurezza.
GL.iNet permette a persone e organizzazioni di connettersi con fiducia. Mettendo il controllo nelle mani degli utenti, GL.iNet sostiene la produttività e la collaborazione che contribuiscono a una buona qualità di vita.