Automatizovaný zavlažovací systém využívající UniPi 1.1

Domů Reference Automatizovaný zavlažovací systém využívající UniPi 1.1 Zpět
Reference

Automatizovaný hydroponický systém, který kombinuje jednotku UniPi 1.1 s cloudovou službou Cloud4RPi.

Ačkoliv již jednotka UniPi 1.1 není vyvíjena, stále je dostupná zákazníkům a mnoho z nich stále preferují verzi 1.1 díky její nízké ceně a jednoduchosti. Jeden z takových zákazníků pak své UniPi použil ke stavbě vlastního hydroponického systému, který kombinuje UniPi 1.1 s cloudovou službou Cloud4RPi. Tým Cloud4RPikterý původně celý projekt zveřejnil, pak svolil k tomu, abychom projekt uvedli i na našich stránkách. Již dříve jsme zde psali o podobném technickém řešení, tento článek proto může sloužit jako ukázka jeho praktické realizace. 

Hardware

Jak již bylo zmíněno, jádrem systému je standardní jednotka UniPi 1.1která nabízí následující

  • 8x relé výstup
  • 1x analogový výstup
  • 2x analogový vstup
  • 14x digitální vstup
  • 1x UART port pro napojení sériových konzolí či široké škály zařízení
  • 1x port pro sběrnici 1-Wire
  • 1x sběrnice L2C

Jednotka jue upevněna v podomácku vyrobené dřevěné konstrukci, která je vybavena jednou DIN lištou a devíti elektrickými zásuvkami. UniPi je připevněna na DIN lištu na obrázku lze vidět samotnou jednotku společně s pojistkou a svorkovnicí. Jedna ze zásuvek slouží jako permanentní zdroj energie pro UniPi, zbylých osm je napojeno na relé výstupy. To jednotce umožňuje zapínat či vypínat připojená zařízení, 

 

V době pořízení fotografie se systém sestával pouze ze spínačů osvětlení a zavlažovačů, do budoucna ale uživatel plánuje zabudovat automatický ventilační systém a systém udržování vlhkosti. 

Software

Díky integraci služby Cloud4RPi může uživatel monitorovat či sbírat údaje o systému z jakéhokoliv místa na světě pomocí internetového připojení. Celé řešení je založeno na platformě Node-RED instalované přímo na UniPi - jde o nástroj vyrobený společnosti IBM, který je navržen přímo pro propojování hardwaru a vytváření algoritmů pro ovládání různých IoT zařízení. Jde o uživatelsky přívětivý program, který umožňuje programovat chování zařízení skrze přehledné grafické schéma. Manuál k Node-RED je dostupný zde.

Druhou částí je samotná služba Cloud4RPi. Tato služba poskytuje uživateli cloudový kontrolní panel, skrze který lze ovládat zařízení a sbírat údaje o nich skrze internet. Pro užití této služby je nutné vytvořit si účet zde.

Cloud dokáže se zařízením komunikovat dvěma způsoby - buď skrze frontu MQTT, případně za pomoci HTTP webové API, určené k tvoření HTTP služeb. Teoreticky by bylo možné pro tento projekt použít oba způsoby, tvůrce systému se ale rozhodl pro možnost MQTT vzhledem k pohodlnějšímu nastavování. 

Propojení Node-RED a Cloud4RPi

V Node-RED jsou zde užívány dva druhy komunikace

  • komunikace zařízení -> cloud pro prvotní konfiguraci, stavová hlášení a sběr dat ze senzorů
  • komunikace cloud -> zařízení pro zadávání příkazů skrze ovládací panel

Prvním krokem bylo odesílání proměnných do správného MQTT topicu - v našem případě do devices/{token}/config. Zpráva je odesílána ve formátu JSON a vypadá následovně. 

v{
  "ts": /* Datum a čas ve formátu ISO 8601 */,
  "payload": [
    {"name": "Proměnná boolean", "type": "bool" },
    {"name": "Proměnná číselná", "type": "numeric" },
    {"name": "Proměnná string", "type": "string" }
  ]
}
Do vlákna devices/{token}/data jsou následně odeslána tato data:
{ 
  "ts": /* Datum a čas ve formátu ISO 8601 */,
  payload: {
    "Název proměnné": "Hodnota proměnné",
    "Další proměnná": 42,
    /* atd. */
    "Další proměnná": false
  }
}

Uživatel má také možnost odeslat diagnostická data - ta nejsou ukládána do logů a ukládají se do kanálu  devices/{token}/diagnostics

{
  "ts": /* Datum a čas ve formátu ISO 8601 */,
  payload: {
      "Diagnostická proměnná": "Hodnota proměnné",
      "Další diagnostická proměnná": 12
  }
}

MQTT spojení je v Node-RED prováděno skrze uzel flow, který se napojuje na dané topicy a posílá do nich zprávy. Co se nastavení Cloud4RPi týče, daný projekt užívá server mq.cloud4rpi.io a port 1883 bez podpory MQTT 3.1. 

Samotný uzel je nastaven tak, aby byly specifikovány kanály, se kterými má uzel komunikovat. 

devices/{token}/config		- konfigurace proměnných
devices/{token}/data		- hodnoty proměnných
devices/{token}/diagnostics	- diagnostické údaje 
devices/{token}/commands	- příjem příkazů z UI (uživatel je připojen zde)

V grafickém rozhraní Node-RED bylo prvním krokem vytvoření uzlu inject se zatrhnutou možností "Inject once at start"

Uzel inject zde slouží pro spuštění systému. Vedle toho je použit uzel timestamp

Tento uzel spouští odesílání konfigurace proměnných do kanálu devices/{token}/config  za podmínky, že data prošla správným prvotním zpracováním - pro to slouží uzel function:

Zde lze využít jakýkoliv kód v JavaScript, konfigurace tak zde mohla být navrácena v odpovídajícím formátu

var message = {
    ts: new Date().toISOString(),
    payload: [ 
        {"name": "Bool Variable", "type": "bool"},
        {"name": "Number Variable", "type": "number"},
        {"name": "String Variable", "type": "string"}
    ]
};
return {payload: message};

 

Za zmínku stojí fakt, že datové pakety pro uzel mqtt jsou obsaženy v prvku payload odpovídajícího uspořádání, zasíláného aktivačním kódem. 

Zmíněné uzly (timestamp, function and mqtt) byly následně propojeny do následujícího řetězce

Odeslání konfigurační zprávy pak ústí v následující oznámení, zobrazené na stránce zařízení v Cloud4RPi. 

Hardwarové proměnné jsou konfigurovány v EVOKu,  základním kontrolním softrwaru pro jednotky UniPi. Konkrétně byly užity dvě vlastnosti - HTTP (pro odesílání žádostí o sdělení stavu zařízení) a Websocket (pro příjem stavového hlášení).

Hodnoty proměnných jsou zde zasílány ve dvou případech

  • po spuštění systému, kdy dojde k aktualizaci kontrolního panelu
  • pokud dojde ke změně hodnoty některé proměnné - v takovém případě je zaslána pouze pozměněná hodnota 

Po spuštění systému obdrží Cloud4RPi systémovou konfiguraci (a proměnné) ze stejného uzlu. Data jsou nicméně úmyslně odesílána se zpožděním skrze zpožďovací uzel delay

Příkaz k zaslání všech hodnot proměnných na UniPi se provádí skrze HTTP žádost zaslanou na http://{UniPi IP address}/rest/all. Pro tento účel je užit uzel http request:

Aby byla data odesílána ve formátu JSON, uzel je nastaven takto: 

Uzel function následně sestaví přijaté hodnoty do JSON zprávy, odeslané na Cloud4RPi...

var getMsgValue = function(device, circuit){
  return msg.payload.filter(function(val){
      if(!val.dev){
          return false;
      }
      return val.dev === device && val.circuit === circuit;
  })[0].value;
};
var message = {
    ts: new Date().toISOString(),
    payload: {
        "Relé 1": getMsgValue("relay", "1") === 1,
        "Relé 2": getMsgValue("relay", "2") === 1,
        "Relé 3": getMsgValue("relay", "3") === 1,
        "Relé 4": getMsgValue("relay", "4") === 1,
        "Relé 5": getMsgValue("relay", "5") === 1,
        "Relé 6": getMsgValue("relay", "6") === 1,
        "Relé 7": getMsgValue("relay", "7") === 1,
        "Relé 8": getMsgValue("relay", "8") === 1
    }
};
return {payload: {message}};

...při užití následující konfigurace:

var message = {
    ts: new Date().toISOString(),
    payload: [ 
      {"name": "Relé 1", "type": "bool"},
      {"name": "Relé 2", "type": "bool"},
      {"name": "Relé 3", "type": "bool"},
      {"name": "Relé 4", "type": "bool"},
      {"name": "Relé 5", "type": "bool"},
      {"name": "Relé 6", "type": "bool"},
      {"name": "Relé 7", "type": "bool"},
      {"name": "Relé 8", "type": "bool"}
    ]
};
return {payload: message};

Výsledná podoba údajů v uživatelském rozhraní je následující: 

Pro zaslání zpráv o změnách stavu jednotky UniPi je užit uzel websocket s nastavenou adresou e  ws://{UniPi IP address}/ws  , který užívá vlastnost EVOKu Websocket: 

Zprávy jsou na Cloud4RPi zasílány ve formě datových paketů vytvářených uzlem function

var circuit_number = parseInt(msg.circuit);
var valid_relay = circuit_number >= 1 && circuit_number <= 8;
if (msg.dev === "relay" && valid_relay){
    var relay_name = 'Relay ' + circuit_number;
    return {
        payload: {  
            ts: new Date().toISOString(),
            payload: {relay_name: msg.value === 1}
        }
    }
}

Výsledkem je níže zobrazený kontrolní panel, kde lze spínat jednotlivá relé a uživatel může v reálném čase sledovat změny jejich stavu. 

Pro vyšší uživatelskou přívětivost byl zahrnut widget Spínač. Ten zobrazuje boolean proměnnou a zasílá příkazy ke změně jejího stavu. 

Kontrolní implementace Node-RED je pak zapsána do MQTT kanálu devices/{token}/commands . Uzel MQTT, zapsaný v kanálu  /commands je napojen na uzel json nod, který mění MQTT zprávy na objekty JSON. 

Tento uzel je pak propojen s funkcí převádějící MQTT zprávy do WebSocket příkazů: 

for (var var_name in msg.payload){
    if (var_name.indexOf('Relay ') >= 0){
        return {
            cmd: "set",
            dev: "relay",
            circuit: var_name.split(' ')[1],
            value: msg.payload[var_name] ? "1" : "0"
        }
    }
}

Další uzel function je pak spojen s uzlem WebSocket. 

Diagnostika

Cloud4RPi obsahuje MQTT kanál devices/{token}/diagnostics, užívaný pro diagnostiku. V našem případě je využit pro zasílání proměnných vyjadřujících stav systému, které jsou zobrazovány v kontrolním panelu. V níže uvedeném příkladu chtěl uživatel zobrazovat teplotu CPU a provozní dobu. Využil pro to uzel exec, užitý v Node-RED:

Tento uzel spustí arbitrární bash příkaz a navrátí jeho hodnotu. V níže uvedeném příkladu je uzel nastaven tak, aby odesílal příkazy každých 30 vteřin. Pro sběr hodnot jsou pak užity dva řetězce - hodnoty jsou následně odesílány do speciálního úložiště v Node-RED, označeného jako flow. To umožňuje pozdější odeslání dat do topicu devices/{token}/diagnosticsMQTT.

Interval odesílání je úmyslně nastaven jako delší než interval žádostí, aby měl uzel odesílající žádost dostatek času pro sběr dat. Samotné hodnoty -tj. teplota CPU a doba provozu- jsou pak detekovány příkazy sensorsuptime.

Pro ukládání hodnot jsou užity uzly function, umístěné za uzly exec. Tyto uzly obsahují následující kód

  • flow.set(‘cpuTemp’, msg.payload) pro odečet teploty CPU
  • flow.set(‘uptimeInfo’, msg.payload); pro odečet doby provozu

Zprávy jsou pak upraveny následujícím kódem: 

return { 
    payload: {
        "ts": new Date().toISOString(),
        payload: {
            "Teplota CPU": flow.get('cpuTemp'),
            "Doba provozu": flow.get('uptimeInfo') || ""
        }
    }
}

V našem případě je diagnostika zobrazována na kontrolním panelu zhruba jednu minutu po spuštění systému

Původní článek, kde je k nalezení i kompletní užitý kód, je přístupný zde.