Skip to main content

API

Rôzne komponenty spolu komunikujú rôznym spôsobom, preto je dôležité mať jedno miesto, kde sa dá prehľadne pozrieť, ako fungujú naše API.

Module <--> Backend

Modul komunikuje smerom na backend cez WebSocket a posiela periodicky nasledujúce správy:

Posielanie údajov z modulu na backend

Posielanie údajov z modulu na backend
{
"moduleId": "<názov modulu>",
"status": "<ok | progress | error>",
<podporované údaje>
}

Posielanie inštrukcií z backendu na modul

Posielanie inštrukcií z backendu na modul
{
"type": "instruction",
"moduleId": "<názov modulu>",
"category": "<ketegória>", // "MOTOR", "PUMP", ...
"device": "<názov zariadenia>", // "MOTOR_1", "PUMP_2", ...
"instruction": "<inštrukcia>", // "SET_TEMPERATURE", "SET_MOTOR_SPEED", ...
"params": "<parameter>"
}

Backend <--> Frontend

Pri každom dopyte a jeho odpovedi, sa budú nachádzať aj created_at a updated_at, avšak pre prehľadnosť, tu niesú napísané.

Podporované funkcie

FE môže získať informácie o podporovaých funkciách v rámci systému.

GET /api/function
[
{
"id": 1,
"codeName": "SET_TEMPERATURE",
"name": "Set temperature",
"category": "TEMPERATURE",
"units": "°C",
"inputType": "float",
"description": "Sets temerature for selected chamber",
"options": [
{
"id": 1,
"name": "Chamber 1",
"codeName": "TEMP_1"
},
{
"id": 2,
"name": "Chamber 2",
"codeName": "TEMP_2"
}
]
},
{
"id": 2,
"codeName": "SET_MOTOR_SPEED",
"name": "Set motor speed",
"category": "MOTOR",
"units": "RMP",
"inputType": "float",
"description": "Sets rpms for selected motor",
"options": [
{
"id": 3,
"name": "Motor 1",
"codeName": "MOTOR_1"
},
{
"id": 4,
"name": "Motor 2",
"codeName": "MOTOR_2"
}
]
},
{
"id": 3,
"codeName": "TRANSFER_LIQUIDS",
"name": "Transfer liquids",
"category": "PUMP",
"units": null,
"inputType": null,
"description": "Transfers liquids from first chamber to second",
"options": [
{
"id": 5,
"name": "Pump 1",
"codeName": "PUMP_1"
}
]
},
{
"id": 4,
"codeName": "UNLOAD",
"name": "Unload ingredient",
"category": "UNLOADER",
"units": null,
"inputType": null,
"description": "Unloads selected ingredient into chamber",
"options": [
{
"id": 6,
"name": "Fermentables",
"codeName": "FERMENTABLE"
},
{
"id": 7,
"name": "Yeast",
"codeName": "YEAST"
},
{
"id": 8,
"name": "Hops",
"codeName": "HOPS"
},
{
"id": 9,
"name": "Other",
"codeName": "OTHER"
}
]
},
{
"id": 5,
"codeName": "WAIT",
"name": "Wait",
"category": "SYSTEM",
"units": "Minutes",
"inputType": "float",
"description": "System will wait for given amount of minues",
"options": []
},
{
"id": 6,
"codeName": "MANUAL",
"name": "Manual step",
"category": "SYSTEM",
"units": null,
"inputType": "string",
"description": "System will wait for manual inervention",
"options": []
}
]

Výber všetkých receptov

Pri zapnutí si používateľ bude môcť vybrať, či chce použiť už vytvorený recept, alebo či chce vytvoriť nový recept.

Pokiaľ si vyberie použitie vytvoreného receptu, front-end pošle GET request na back-end URL:

GET /api/recipe

Ako odpoveď obdrží základné informácie (id, názov, čas vytvorenia) pre všetky recepty v JSON formáte:

[
{
"id": 3,
"name": "Smoky Grove Lichtenhainer",
"description": "Light, gently tart, and smoked—lichtenhainer is an unusual beer, yet surprisingly good for all seasons and one you’ll want to brew and enjoy often.",
"locked": false
},
{
"id": 4,
"name": "Burke-Gilman The Hopsplainer",
"description": "Courtesy of the brewing team at Burke-Gilman in Seattle, here is a homebrew-scale recipe for the double hazy IPA that won GABF gold in 2020.",
"locked": true
},
...
]

Výber jedného receptu

FE ponúkne používateľovi výber z prijatých receptov podľa názvu. Pri vybratí receptu sa odošle GET request na backend:

GET /api/recipe/{recipe-id}

Odpoveďou bude JSON so všetkými dátami receptu:

{
"id": 3,
"name": "Smoky Grove Lichtenhainer",
"description": "Light, gently tart, and smoked—lichtenhainer is an unusual beer, yet surprisingly good for all seasons and one you’ll want to brew and enjoy often.",
"locked": false,
"Ingredients": [
{
"id": 5,
"recipeId": 3,
"name": "American - Pale 2-Row",
"amount": 5.6,
"type": "Fermentable",
"units": "Kg"
},
{
"id": 6,
"recipeId": 3,
"name": "Fermentis - Safale - American Ale Yeast US-05",
"amount": 1,
"type": "Yeast",
"units": ""
},
{
"id": 7,
"recipeId": 3,
"name": "Magnum (Pellet)",
"amount": 1,
"type": "Hops",
"units": "oz"
},
{
"id": 8,
"recipeId": 3,
"name": "Crush whilrfoc Tablet",
"amount": 1,
"type": "Other",
"units": ""
}
],
"Instructions": [
{
"id": 11,
"recipeId": 3,
"templateId": 2,
"codeName": "SET_MOTOR_SPEED",
"params": 30,
"category": "MOTOR",
"optionCodeName": "MOTOR_1",
"blockId": 1,
"blockName": "Fermentation",
"ordering": 1
},
{
"id": 12,
"recipeId": 3,
"templateId": 1,
"codeName": "SET_TEMPERATURE",
"params": 85,
"category": "TEMPERATURE",
"optionCodeName": "TEMP_1",
"blockId": 1,
"blockName": "Fermentation",
"ordering": 2
},
{
"id": 13,
"recipeId": 3,
"templateId": 2,
"codeName": "SET_MOTOR_SPEED",
"params": 0,
"category": "MOTOR",
"optionCodeName": "MOTOR_1",
"blockId": 2,
"blockName": "Yeasting",
"ordering": 3
},
{
"id": 14,
"recipeId": 3,
"templateId": 1,
"codeName": "SET_TEMPERATURE",
"params": 23,
"category": "TEMPERATURE",
"optionCodeName": "TEMP_1",
"blockId": 2,
"blockName": "Yeasting",
"ordering": 4
}
]
}

Výber receptu na varenie

Pokiaľ je používateľ s vybraným receptom spokojný, klikne na tlačidlo "Vybrať recept". Recept sa následne načíta na hlavnú obrazovku a tiež sa odošle POST request na BE s vybraným receptom (aby BE vedel, že čo sa bude robiť):

POST /api/recipe/{recipe-id}/load

Pridanie nového receptu

Pokiaľ používateľ chce vytvoriť nový recept, pomocou obrazovky pre pridanie receptu vykliká všetky požadované kroky a klikne na tlačidlo "Pridať recept". Na BE sa odošle PUT request:

PUT /api/recipe
{
"name": "Perfect Northeast IPA (NEIPA)",
"description": "I have no idea what I'am doing",
"locked": false,
"Ingredients": [
{
"name": "American - Pale 2-Row",
"amount": 5.6,
"type": "Fermentable",
"units": "Kg"
},
{
"name": "Fermentis - Safale - American Ale Yeast US-05",
"amount": 1,
"type": "Yeast",
"units": ""
},
{
"name": "Magnum (Pellet)",
"amount": 1,
"type": "Hops",
"units": "oz"
},
{
"name": "Crush whilrfoc Tablet",
"amount": 1,
"type": "Other",
"units": ""
}
],
"Instructions": [
{
"templateId": 4,
"params": null,
"optionCodeName": "FERMENTABLE",
"blockName": "Fermentation",
"ordering": 4
},
{
"templateId": 1,
"params": "60",
"optionCodeName": "TEMP_1",
"blockName": "Fermentation",
"ordering": 3
},
{
"templateId": 5,
"params": "5",
"optionCodeName": null,
"blockName": "Yeasting",
"ordering": 2
},
{
"templateId": 2,
"params": "100",
"optionCodeName": "MOTOR_1",
"blockName": "Yeasting",
"ordering": 1
}
]
}

Ako odpoveď na FE príde JSON s vygenerovaným ID pridaného receptu:

200 OK
{
"id" : xxx
}

Po vytvorení receptu sa vrátime na výber receptov, kde bude už nový recept zobrazený.

Úprava existujúceho receptu

Pokiaľ používateľ chce upraviť existujúci recept, pomocou obrazovky pre úpravu receptu pozmení všetky požadované položky a klikne na tlačidlo "Uložiť recept" a odošle požiadavku na BE. Keďže potrebujem uchovať údaje pre potreby histórie varení, upravený recept sa uloží ako nový recept a pôvodný sa ďalej nebude zobrazovať medzi výberom recptov.

PUT /api/recipe/{recipe-id}/edit
{
"name": "New Perfect Northeast IPA (NEIPA)",
"description": "I have no idea what I'am doing",
"locked": false,
"Ingredients": [
{
"name": "American - Pale 2-Row",
"amount": 8.6,
"type": "Fermentable",
"units": "Kg"
},
{
"name": "Fermentis - Safale - American Ale Yeast US-05",
"amount": 2,
"type": "Yeast",
"units": ""
},
{
"name": "Magnum (Pellet)",
"amount": 0.5,
"type": "Hops",
"units": "oz"
},
{
"name": "Crush whilrfoc Tablet",
"amount": 1.5,
"type": "Other",
"units": ""
}
],
"Instructions": [
{
"templateId": 4,
"params": null,
"optionCodeName": "FERMENTABLE",
"blockName": "Fermentation",
"ordering": 4
},
{
"templateId": 1,
"params": "80",
"optionCodeName": "TEMP_1",
"blockName": "Fermentation",
"ordering": 3
},
{
"templateId": 5,
"params": "5",
"optionCodeName": null,
"blockName": "Yeasting",
"ordering": 2
},
{
"templateId": 2,
"params": "100",
"optionCodeName": "MOTOR_1",
"blockName": "Yeasting",
"ordering": 1
}
]
}

Ako odpoveď na FE príde JSON s vygenerovaným ID aktualizovaného receptu:

200 OK
{
"id" : xxx
}

Vymazanie receptu

Pokiaľ chce používateľ vymazať jeden z receptov, klikne na ten, ktorý chce vymazať a následne klikne na tlačidlo "Vymazať". Po kliknutí na tlačidlo sa zobrazí potvrdzovacie okno a po kliknutí tlačidla "Potvrdiť" sa pošle na BE POST request:

POST /api/recipe/{recipe-id}/delete

Ako odpoveď na FE príde JSON s ID vymazaného receptu:

200 OK
{
"id" : 3
}

Po vymazaní receptu sa obrazovka s receptami načíta znova a vymazaný recept už nebude zobrazovaný.

Začiatok varenia

Po vybratí receptu sa recept načíta na hlavnú obrazovku. Používateľ dostane príležitosť skontrolovať, či je recept správny. Pokiaľ je s receptom spokojný, spustí varenie. Pri spustení varenia sa na BE pošle PUT request:

PUT /api/brew/0/start
{
"recipeId": 123 // id vybraného receptu
}

FE čaká na odpoveď z BE, či sa všetko úspešne spustilo:

200 OK
{
"brewId" : xxx
}

FE si uloží ID varenia pre ďalšie dopyty.

Pokiaľ na BE nastane porucha alebo chyba pri spúšťaní, na FE pošle odpoveď:

500 SERVER ERROR
{
"error" : "Temp error message."
}

FE túto chybu následne ohlási používateľovi.

Periodické dopyty na back-end

Pokiaľ sa varenie spustí úspešne, FE prejde do módu, kde sa periodicky dopytuje BE na stav receptu. Každú 1 sekundu na BE odošle GET request na URL:

GET /api/data

Pokiaľ všetko prebieha v poriadku

V ideálnom prípade BE odpovie formou:

200 OK
{
"data": {
<podporované údaje>
},
"instruction" : {
"currentInstruction": 23,
"currentValue": 36.5,
"status": "IN_PROGRESS",
},
"brewStatus": "IN_PROGRESS"
}

FE túto odpoveď spracuje a obnoví obrazovku.

Pokiaľ nastane chyba

Pokiaľ došlo k chybe niekde v pipeline, BE odpovie formou:

500 SERVER ERROR
{
"error": "Temp error message.",
"module": {
"moduleId": 234,
"device": "MOTOR_1",
"category": "MOTOR",
"error": "Cannot communicate with device"
},
"instruction" : {
"currentInstruction": 23,
"currentValue": 36.5,
"status": "FAIL"
},
"brewStatus": "STOPPED"
}

Úspešné ukončenie varenia

Pokiaľ BE úspešne ukončil varenie, pri najbližšom GET dopyte (GET /api/data) BE pridá položku status: "FINISHED":

200 OK
{
...
...
"brewStatus": "FINISHED"
}

FE o tejto skutočnosti upovedomí používateľa a ukončí mód periodických dopytov.

Potvrdenie manuálnej inštrukcie

Keď nastane situácia, že treba vykonať manuálnu inštrukciu, systém bude čakať až kým používateľ nepotvrdí jej vykonanie.

POST /api/brew/{brewId}/instruction/{instructionId}/done
200 OK

Až po nasledujúcom dopyte v Periodické dopyty na back-end sa prejde na ďalšiu inštrukciu, keď nám BE pošle, že sme na nasledujúcej inštrukcii.

Úprava parametrov počas varenia

Pokiaľ nastane zmena parametrov nejakých krokov, ktoré ešte neboli vykonané, FE odošle POST request na BE:

POST /api/brew/{brewId}/instruction/{instructionId}
{
// celá inštrukcia s upravenými paremtrami, viď Štruktúra JSONu inštrukcie"
}

Pokiaľ úprava prebehne v poriadku, BE odpovie správou:

200 OK

Pokiaľ úpravu nebolo možné vykonať, BE odpovie správou:

400 BAD REQUEST
{
"error" : "Temp error message."
}

Note: je potrebné, aby FE po tomto POST requeste spustil timer na periodické dopyty odznova, aby sme sa vyhli nepríjemnostiam s asynchronicitou BE.

Pauza počas varenia

Na front-ende by mala byť možnosť pauznúť varenie používateľom. Používateľ klikne na tlačidlo "Pauza". FE sa opýta, či si je používateľ istý.

Po potvrdení je na BE odoslaný POST request:

POST /api/brew/0/pause

BE by mal zastaviť časovače na všetkých aktívnych procesoch a odpovedať formou:

200 OK

Pokiaľ pri zrušení nastane chyba, BE odpovie formou:

500 SERVER ERROR
{
"error" : "Temp error message."
}

Pokračovanie varenia

Ak chceme pokračovať vo varení, pošleme:

POST /api/brew/0/resume

Zrušenie varenia

Na front-ende by mala byť možnosť prerušiť varenie používateľom. Používateľ klikne na tlačidlo "Zrušiť varenie". FE sa opýta, či si je používateľ istý.

Po potvrdení je na BE odoslaný POST request:

POST /api/brew/0/abort

BE by mal zrušiť všetky procesy, správne vypnúť všetky zariadenia a odpovedať formou:

200 OK

Pokiaľ pri zrušení nastane chyba, BE odpovie formou:

500 SERVER ERROR
{
"error" : "Temp error message."
}

Now it's time to panic.

Resetovanie varenia po errore

Ak chceme pokračovať vo varení, po tom ako sa vyskytla chyba spojenia s modulmi , pošleme:

POST /api/brew/0/reset

História všetkých varení

Pre zobrazenie prehľadu všetkých varení na FE je vytvorený endpoint:

GET /api/brew

Ako odpoveď príde zoznam vštekých ukončených varení s id, (poznámky a vyhdonotenie sme zatiaľ neimplementovali, možno v budúcnosti), status ako sa varenie skončilo, meno použitého receptu pre varenie, a časy začiatku a skončenia varenia.

[
{
"id":1,
"notes":null,
"evaluation":null,
"endState":"Aborted",
"recipeName":"Smoky Grove Lichtenhainer",
"startedAt":"2022-04-07T16:12:03.011Z",
"finishedAt":"2022-04-07T16:12:47.442Z"
},
...
]

História konkrétneho varenia

Pre zobrazenie podrobného prehľadu varenia na FE je vytvorený endpoint:

GET /api/brew/{brewId}

Ako odpoveď príde JSON s údajmi o varení ako pri dopytovaní si prehľadu všetkých varení. Spolu s týmito údajmi prídu aj údaje o použitom recepte (rovnaké údaje ako pri dopytovaní si konkrétneho recptu na endpointe GET /api/recipe/{recipe-id}) a k tomu ešte aj záznamy z priebehu varenia. Časové údaje v týchto záznamoch sú relatívne k začiatku varenia.

Pod InstructionLogs sa nachádza zoznam záznamov o začatí vykonávania jednotlivých inštrukcií použitého receptu a o ich ukončení(v uvedenom príklade bol recept ukončený abortom počas vykonávania druhej inštrukcie, preto sa táto instšrukcia neukončila úspešne a nasledujúce sa ani nezačali vykonávať). Obsahuje identifikačné údaje varenia a inštrukcie ku ktorej patrí a údaje o úspešnom ukončení a relatívny čas začiatku vykonávania inštrukcie.

Pod StatusLogs sa nachádza zoznam záznamov o stave pivovaru a hodnotách nameraných na jednotlivých senzoroch (rovnaký formát ako pri dopyte na endpoint GET /api/data). Pre optimalizáciu výkonu a zjednodušenie zobrazenia údajov na FE posielame iba jeden záznam za minútu aj keď v skutočnosti má každé varenie oveľa viac záznamov.

{
"id":1,
"notes":null,
"evaluation":null,
"endState":"Aborted",
"recipeName":"Smoky Grove Lichtenhainer",
"startedAt":"2022-04-07T16:12:03.011Z",
"finishedAt":"2022-04-07T16:12:47.442Z",
"recipe":{
"name":"Smoky Grove Lichtenhainer",
"id":1,
"locked":true,
"description":"Light, gently tart, and smoked—lichtenhainer is an unusual beer, yet surprisingly good for all seasons and one you’ll want to brew and enjoy often.",
"Ingredients":[
{
"id":1,
"recipeId":1,
"name":"American - Pale 2-Row",
"amount":5.6,
"type":"Fermentable",
"units":"Kg",
"createdAt":"2022-04-07T14:45:04.034Z",
"updatedAt":"2022-04-07T14:45:04.037Z"
},
{
"id":2,
"recipeId":1,
"name":"Fermentis - Safale - American Ale Yeast US-05",
"amount":1,
"type":"Yeast",
"units":"",
"createdAt":"2022-04-07T14:45:04.034Z",
"updatedAt":"2022-04-07T14:45:04.037Z"
},
{
"id":3,
"recipeId":1,
"name":"Magnum (Pellet)",
"amount":1,
"type":"Hops",
"units":"oz",
"createdAt":"2022-04-07T14:45:04.034Z",
"updatedAt":"2022-04-07T14:45:04.037Z"
},
{
"id":4,
"recipeId":1,
"name":"Crush whilrfoc Tablet",
"amount":1,
"type":"Other",
"units":"",
"createdAt":"2022-04-07T14:45:04.034Z",
"updatedAt":"2022-04-07T14:45:04.037Z"
}
],
"Instructions":[
{
"id":4,
"recipeId":1,
"templateId":6,
"codeName":"SET_MOTOR_SPEED",
"param":"100",
"category":"MOTOR",
"optionCodeName":"MOTOR_1",
"blockId":2,
"blockName":"FIRST_BLOCK",
"ordering":1
},
{
"id":3,
"recipeId":1,
"templateId":2,
"codeName":"WAIT",
"param":"50000",
"category":"SYSTEM",
"optionCodeName":null,
"blockId":2,
"blockName":"FIRST_BLOCK",
"ordering":2
},
{
"id":2,
"recipeId":1,
"templateId":4,
"codeName":"SET_TEMPERATURE",
"param":"60",
"category":"TEMPERATURE",
"optionCodeName":"TEMP_1",
"blockId":1,
"blockName":"SECOND_BLOCK",
"ordering":3
},
{
"id":1,
"recipeId":1,
"templateId":5,
"codeName":"UNLOAD",
"param":null,
"category":"UNLOADER",
"optionCodeName":"FERMENTABLE",
"blockId":1,
"blockName":"SECOND_BLOCK",
"ordering":4
}
]
},
"InstructionLogs":[
{
"id":2,
"brewingId":1,
"instructionId":3,
"finished":false,
"startedAt":2999
},
{
"id":1,
"brewingId":1,
"instructionId":4,
"finished":true,
"startedAt":218
}
],
"StatusLogs":[
{
"id":1,
"brewingId":1,
"status":"IN_PROGRESS",
"params":{
"TEMPERATURE":[
{
"TEMP":16.2652657535844,
"REGULATION_ENABLED":false,
"STATE":"WAITING",
"DEVICE":"TEMP_1"
},
{
"TEMP":10.941566144455068,
"REGULATION_ENABLED":false,
"STATE":"WAITING",
"DEVICE":"TEMP_2"
}
],
"MOTOR":[
{
"SPEED":0,
"RPM":-0.15012981101345724,
"STATE":"WAITING",
"DEVICE":"MOTOR_1"
},
{
"SPEED":0,
"RPM":14.64062077202769,
"STATE":"WAITING",
"DEVICE":"MOTOR_2"
}
],
"UNLOADER":[
{
"UNLOADED":false,
"STATE":"WAITING",
"DEVICE":"FERMENTABLE"
},
{
"UNLOADED":false,
"STATE":"WAITING",
"DEVICE":"YEAST"
},
{
"UNLOADED":false,
"STATE":"WAITING",
"DEVICE":"HOPS"
},
{
"UNLOADED":false,
"STATE":"WAITING",
"DEVICE":"OTHER"
}
],
"PUMP":[
{
"ENABLED":false,
"STATE":"WAITING",
"DEVICE":"PUMP_1"
}
],
"SYSTEM":[
{
"REMAINING":0,
"STATE":"WAITING",
"DEVICE":"WAIT"
}
]
},
"createdAt":1382
},
{
"id":42,
"brewingId":1,
"status":"IN_PROGRESS",
"params":{
"TEMPERATURE":[
{
"TEMP":14.262489126700011,
"REGULATION_ENABLED":false,
"STATE":"WAITING",
"DEVICE":"TEMP_1"
},
{
"TEMP":7.213137158608217,
"REGULATION_ENABLED":false,
"STATE":"WAITING",
"DEVICE":"TEMP_2"
}
],
"MOTOR":[
{
"SPEED":100,
"RPM":90.88227550340005,
"STATE":"WAITING",
"DEVICE":"MOTOR_1"
},
{
"SPEED":0,
"RPM":12.901996647902722,
"STATE":"WAITING",
"DEVICE":"MOTOR_2"
}
],
"UNLOADER":[
{
"UNLOADED":false,
"STATE":"WAITING",
"DEVICE":"FERMENTABLE"
},
{
"UNLOADED":false,
"STATE":"WAITING",
"DEVICE":"YEAST"
},
{
"UNLOADED":false,
"STATE":"WAITING",
"DEVICE":"HOPS"
},
{
"UNLOADED":false,
"STATE":"WAITING",
"DEVICE":"OTHER"
}
],
"PUMP":[
{
"ENABLED":false,
"STATE":"WAITING",
"DEVICE":"PUMP_1"
}
],
"SYSTEM":[
{
"REMAINING":14,
"STATE":"IN_PROGRESS",
"DEVICE":"WAIT"
}
]
},
"createdAt":42498
}
]
}

Exportovanie logov - CSV

Pre export status logov počas varenia ako csv súboru je možné poslať request:

GET /api/brew/{brewId}/exportCsv

Následne sa stiahne csv súbor obsahujúci logy varenia.

Exportovanie logov - JSON

Pre export status logov počas varenia ako json súboru je možné poslať request:

GET /api/brew/{brewId}/exportJson

Následne sa stiahne json súbor obsahujúci logy varenia.

Vypnutie systému

Používateľ môže kliknúť na tlačidlo vypnutia systému. FE sa opýta, či si je používateľ istý.

Po potvrdení je na BE odoslaný POST request:

POST /api/shutdown

BE následne vypne celé RPI, na ktorom beží systém pivovaru.