Modeller
En modell är formen på en sak i Yggio: de fält REST-API:et accepterar när du skapar eller uppdaterar den, och de fält det returnerar när du läser den. API:et validerar varje anrop mot de här schemana, så en kropp som inte stämmer avvisas innan något sparas.
Entiteter av dessa modeller kan hämtas, skapas, ändras och raderas via REST-API:et.
Varje skapad modellentitet får ett _id för referenser. Ett Id är en 24 tecken lång hexsträng
(t.ex. 507f1f77bcf86cd799439011).
Modellerna
| Modell | Vad det är |
|---|---|
| User | Ett konto |
| Usergroup | En uppsättning användare |
| Iotnode | En enhet, fysisk eller virtuell. Den centrala modellen |
| Connector | En länk till en nätverksserver eller ett externt system som enheter kommer in genom |
| Calculation | Ett härlett värde beräknat från enhetsdata |
| Åtkomsträttighet | Vem som når en resurs, och på vilken nivå |
| Channel | En utgående prenumeration som skickar uppdateringar till din tjänst |
| BasicCredentialsSet | Ett par av användarnamn och lösenord som integrationer använder |
| ReservedMqttTopic | Ett MQTT-topic reserverat till ett credentials set |
| Location | En plats på kartan som grupperar enheter. Utfasad |
Andra modeller finns och nås via API:et - dashboards, geofences, enhetsgrupper, rapporter, regler, bilder, organisationer och fler. De följer samma konventioner som de nedan. Var och en av dem är också en resurs som bär åtkomsträttigheter; Åtkomsträttigheter listar hela uppsättningen resurstyper.
Det fullständiga schemat
Den här sidan beskriver de fält du kommer att använda mest. Det fullständiga schemat för varje endpoint finns i Swagger UI. Det underhålls vid sidan av API:et i stället för att genereras ur det, så det kan släpa efter en ny ändring - om ett anrop beter sig annorlunda än vad Swagger visar är det den körande endpointen som gäller.
Swagger är också snabbaste sättet att se vad ett visst anrop avvisar: fäll ut endpointen, läs modellen under Request body, och använd Try it out mot ditt eget konto.
User
En användare är ett konto. Det används för autentisering och för åtkomstkontroll till andra resurser. Konton ligger i Keycloak, inloggningstjänsten Yggio använder, vilket är varför fältnamnen nedan följer Keycloaks stil snarare än Yggios vanliga.
{
username: String, // obligatoriskt
email: String,
firstName: String,
lastName: String,
phoneNumber: String, // E.164-format, t.ex. +46701234567
enabled: Boolean,
requiredActions: [String],
attributes: {
globalVisibility: String, // 'true' eller 'false', inte en boolean
language: String,
organization: [String],
roles: [String]
}
}
username är det enda obligatoriska fältet vid skapande.
phoneNumber måste vara i E.164-format.
enabled styr om kontot får logga in. Att inaktivera ett konto tar inte bort det.
requiredActions listar åtgärder Keycloak tvingar fram vid nästa inloggning, som att sätta ett
lösenord.
attributes innehåller de Yggio-specifika tilläggen. Observera att globalVisibility ligger här och
inte på toppnivå, och lagras som strängen 'true' eller 'false' snarare än som en boolean. Det
styr om användarnamnet går att söka fram av andra Yggio-användare.
Det finns inget password-fält, och ingen publik endpoint för att sätta ett. Lösenord ligger i
Keycloak och sätts antingen av Keycloak självt vid inloggning, via requiredActions, eller av Yggio
när en organisation skapar eller återställer en medlem.
Usergroup
En användargrupp är en uppsättning användare. Den används till två saker: att ge åtkomsträttigheter till flera personer samtidigt, och att filtrera vilka appar dess medlemmar ser.
Själva gruppen är ett litet objekt:
{
_id: Id,
name: String, // obligatoriskt, 2 till 60 tecken
owner: Id // obligatoriskt
}
name måste vara mellan 2 och 60 tecken.
owner refererar till användaren som äger gruppen. När en grupp skapas är ägaren den användare som
skapade den.
Medlemmar och appfiltret är inte fält på det här objektet. De hanteras via egna endpoints, så ett skapa-anrop som innehåller dem gör inte det man tror:
| Vad | Hur |
|---|---|
| Lägga till en medlem | POST /usergroups/{groupId}/members |
| Ta bort en medlem | DELETE /usergroups/{groupId}/members/{memberId} |
| Läsa medlemmarna | GET gruppen med includeMembers=true |
| Sätta appfiltret | PUT /usergroups/{groupId}/app-filter |
| Tillåta en app | POST /usergroups/{groupId}/app-filter |
| Ta bort en app | DELETE /usergroups/{groupId}/app-filter/{appId} |
Iotnode
En iotnod är oftast en representation av en fysisk enhet. Den kan dock även vara en virtuell enhet.
Iotnod-modellen är medvetet öppen. Bara några få fält är fasta; allt annat en enhet rapporterar lagras bredvid dem som fält på toppnivå. Det är det som låter en modell bära en temperatursensor, en personräknare och en vattenmätare utan ett schema per enhetstyp.
{
_id: Id, // tilldelas av Yggio
name: String, // obligatoriskt vid skapande, icke-tomt
description: String,
category: String,
connector: Id, // connectorn enheten kommer in genom
reportedAt: Date,
updatedAt: Date,
rabbitRouting: Object,
// ...plus varje fält enhetens översättare producerade
}
name är obligatoriskt och måste vara en icke-tom sträng. Det får inte innehålla sekvensen ~||~,
som Yggio använder internt som avskiljare.
description är för visningsändamål.
category används för att gruppera iotnoder så att de blir enkla att filtrera.
connector refererar till connectorn enheten kommer in genom. Den kan anges som ett id
eller som ett objekt med ett _id.
reportedAt är en tidsstämpel som anger när iotnoden senast fick en rapport från den fysiska
enheten.
updatedAt är en tidsstämpel som anger när något attribut senast uppdaterades (t.ex. namn, värde).
rabbitRouting används bara internt och bör inte ändras av externa utvecklare.
Datafälten
Mätfälten på en iotnod är inte en del av den här modellen. De skrivs av enhetens
översättare, som avkodar den råa payloaden till Yggios
kanoniska datamodell - temperature, relativeHumidity, batteryVoltage, co2 och så vidare, var
och en med deklarerad typ, enhet och storhet.
Det spelar roll när du utvecklar mot API:et: förvänta dig inte en fast uppsättning värdefält, och hitta inte på egna namn för värden en översättare redan producerar. Översättar-API:et täcker fältreferensen.
Eftersom modellen accepterar okända fält lagras ett felstavat fältnamn i stället för att avvisas. En enhet som verkar sakna ett värde är värd att kontrollera för det först.
Connector
En connector är länken mellan Yggio och systemet enheter kommer in genom: en LoRaWAN-nätverksserver som ChirpStack eller Netmore, ett tillverkarmoln, eller ett generiskt HTTP- eller MQTT-flöde. Yggio stödjer 26 integrationer.
{
_id: Id,
name: String, // obligatoriskt
integration: String, // obligatoriskt - vilken integration det är
flowIdentifier: String, // valfritt, väljer ett eget flöde
retentionPolicy: String,
protocols: Object, // protokollspecifika inställningar
uplink: {protocol: String},
downlink: {protocol: String},
// ...plus fält unika för integrationen
}
integration väljer typen och avgör vilka ytterligare fält som gäller, så resten av kroppen skiljer
sig per integration. Läs den exakta formen för den du använder under Connectors i Swagger, och se
Connectorer för vad var och en gör.
Calculation
En beräkning härleder ett värde ur enhetsdata och skriver tillbaka det som ett fält, så att det kan ritas i diagram, rapporteras på och larmas om som vilket annat värde som helst.
Det finns två former, som väljs med type:
type | Vad den gör |
|---|---|
lastValue | Aggregerar det senaste värdet från en eller flera källenheter |
window | Aggregerar ett fönster av avläsningar från en enda källa över tid |
Båda bär en source (vad som ska läsas), en destination (var resultatet ska skrivas),
aggregeringsmetoden, och ett valfritt schema för automatisk uppdatering. Den fullständiga fältlistan
för varje form finns i Swagger under Calculations, som CalculationLastValue och
CalculationWindowed.
Åtkomsträttighet
En åtkomsträttighet ger ett subjekt en åtkomstnivå till en resurs. Den är inte ett fält på resursen;
den är en egen post, som skapas och tas bort via /access-rights.
{
resourceType: String, // 'device', 'dashboard', 'image', ...
resourceId: Id, // resursens _id, 24 tecken hex
subjectType: String, // 'singleton', 'group' eller 'orgUnit'
subjectId: Id, // ett Keycloak-UUID för 'singleton', ett 24 tecken hex-_id för 'group'
scope: [String] // 'admin', 'write', 'read', 'peek'
}
subjectType är singleton för en enskild användare, group för en användargrupp, eller orgUnit
för en organisationsenhet. Singleton är åtkomstmotorns begrepp: varje användare mappas på en grupp om
en, vilket är det som gör att användare, grupper och enheter kan ges åtkomst genom samma mekanism.
Kontrollpanelen skickar singleton, och user accepteras som alias för det.
De två sorternas id går inte att byta ut mot varandra. En användare identifieras med sitt
Keycloak-id, som är ett UUID; en grupp med sitt eget _id, en 24 tecken lång hexsträng som varje
annat Yggio-resurs-id.
En endpoint avviker från detta. GET /access-rights/subject/{id} tar bara user eller group i sin
query-parameter subjectType, och har user som standard.
Varje resurstyp i Yggio kan bära åtkomsträttigheter, även de som saknar gränssnitt för det. Se Åtkomsträttigheter för resurstyperna och vad varje nivå tillåter.
Channel
En channel skickar uppdateringar till en extern tjänst när enhetsdata ändras. Meddelandet bär enheten samt vilka attribut som uppdaterades.
{
name: String,
// exakt ett mål
iotnode: Id,
deviceGroup: Id,
// exakt ett protokoll
http: {url: String, headers: Object},
mqtt: {type: String, recipient: Id},
azureIotHub: {connectionString: String},
desigoCC: {...},
deltaControls: {...},
vyer: {...}
}
Två regler kontrolleras vid skapande, och båda är en vanlig orsak till ett avvisat anrop:
- Exakt ett mål. Antingen
iotnodeellerdeviceGroup, aldrig båda och aldrig ingendera. En channel på en enhetsgrupp följer gruppen, så enheter som läggs till senare täcks utan en ny channel. - Exakt ett protokoll. Att sätta inget, eller fler än ett, avvisas med ett meddelande som namnger dem den hittade. De sex ovan är de som protokollväljaren erbjuder.
name är valfritt.
http.url måste vara en giltig URL. Meddelanden POSTas dit.
http.headers är ett valfritt objekt med ytterligare HTTP-headers som skickas med varje anrop. För
Basic Auth, inkludera en Authorization-header satt till Basic <base64>, där <base64> är
Base64-kodningen av username:password. En Authorization-header är skrivskyddad utåt: den
accepteras vid skapande och uppdatering men returneras aldrig av API:et.
mqtt.type är antingen keycloakUser eller basicCredentialsSet, och mqtt.recipient är id:t för
vilken av de två det är.
BasicCredentialsSet
Ett BasicCredentialsSet är ett par av användarnamn och lösenord som en enhet eller en integration autentiserar med. Det används när man publicerar MQTT-meddelanden till Yggio, och som mottagare för en MQTT-channel.
{
username: String, // obligatoriskt
password: String // obligatoriskt
}
username får inte vara ett UUID; den formen är reserverad och avvisas.
password saltas och hashas på vägen in, och returneras aldrig av API:et.
ReservedMqttTopic
Ett ReservedMqttTopic reserverar ett MQTT-topic och parar det med ett BasicCredentialsSet, så att bara den behörigheten kan publicera till det.
{
topic: String, // obligatoriskt
basicCredentialsSetId: Id // obligatoriskt
}
basicCredentialsSetId måste referera till ett credentials set som finns; skapa-anropet kontrollerar
det.
topic valideras, och tre regler avgör om det accepteras:
- Det får inte börja med
/. - Det måste börja med ett av de tillåtna rot-topicen:
yggio/generic/v2,yggio/axis/v1,yggio/beijerix/v1,yggio/hubitat/v1elleryggio/push/v1. - Det måste lägga till ett undertopic under den roten. Roten i sig är ingen reservation.
Så yggio/generic/v2/min-byggnad accepteras, medan yggio/generic/v2 och min-byggnad/sensorer
inte gör det. Felmeddelandet namnger de tillåtna rötterna.
Location (utfasad)
Location-modellen ligger bakom Location Manager, som är utfasad. Den dokumenteras här för dem som fortfarande använder den. Bygg inga nya integrationer på den. Den grupperar iotnoder och binder dem till en plats på världskartan.
Location-datastruktur:
{
name: String, // obligatoriskt
description: String,
user: Id, // obligatoriskt
lat: Number, // obligatoriskt
lng: Number, // obligatoriskt
icon: String,
defaultLayer: LocationLayer, // obligatoriskt
layers: [LocationLayer],
version: Number
}
name är obligatoriskt och valideras mot en teckenuppsättning: bokstäver, siffror, de svenska
tecknen åäöÅÄÖ, mellanslag, understreck och bindestreck. Andra tecken avvisas med "is not a valid
location name".
description är för visningsändamål.
user refererar till användaren som skapade platsen, och är obligatoriskt.
lat och lng är obligatoriska koordinater för var platsen ligger i världen.
defaultLayer är obligatoriskt och är lagret som visas först när man går in på en plats. layers
håller resten. Se LocationLayer nedan.
LocationLayer
LocationLayer används för att gruppera objekt (iotnoder) på en plats. Till exempel: om en plats är en byggnad kan ett locationLayer ses som en våning i den byggnaden.
{
name: String,
items: [LocationItem],
image: String, // sökväg till bakgrundsbilden
left: Number, // bildens position, 0 till 100
top: Number,
width: Number, // bildens storlek, 50 till 200
height: Number
}
name accepterar samma teckenuppsättning som platsens namn.
image är bakgrundsritningen objekten placeras på, till exempel en planritning, och left, top,
width och height placerar och storleksätter den.
LocationItem
LocationItem är ett omslag för en enskild iotnod på en plats.
{
deviceId: Id, // obligatoriskt
type: String,
size: String,
top: Number,
left: Number,
valueDisplay: String,
locationItemControl: {icon: String}
}
deviceId refererar till en iotnod, och är det enda obligatoriska fältet.
top och left placerar objektet på lagret, och size, type och valueDisplay styr hur det
ritas och vilket värde det visar.