Gå til innhold
  • Bli medlem
Støtt hjemmeautomasjon.no!

Lage plugin selv


Gjelsvik

Anbefalte innlegg

Kjøpte en Sensibo til  styre varmepumpa, den har en plugin tilgjengelig, men ikke i homeseer store. 

Innen jeg rakk å motta den så var HS3 ute med v. 3.12 og denne pluginen støtter ikke 3.12. Dvs jeg får ikke brukt sensibo i HS3.

 

Har nå lekt meg litt med vb.net og har fungere kode mot APIet til Sensibo. Jeg har sålangt kun hentet status ned. Ikke sendt endringer/kommandoer ut til enheten. Startet et nytt console.app prosjekt for å enklere teste dette underveis, men har en kopi av "HSPI_MoskusSample" som jeg tenkte å tilpasse etterhvert.

 

Utfordringen min nå er å håndtere verdiene jeg mottar, og tilegne devicer disse verdiene.

 

Noen som har lyst til å hjelpe til med dette?

 

koden min så langt.

Spoiler

Imports System.Text
Imports System.IO
Imports System.Threading
Imports System.Web
Imports System
Imports System.Net
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Module Module1

    Sub Main()

        Dim apikey As String = "sensurert"
        Dim podpath As String = "https://home.sensibo.com/api/v2/users/me/pods?fields=room,id&apiKey=" & apikey
        Console.WriteLine("Using apiKey: " & apikey)
        'obj = JsonConvert.DeserializeObject(Of JSON_result)

        Console.WriteLine("Connecting to " & podpath & "...")
        Using client As New Net.WebClient
            'Dim reqparm As New Specialized.NameValueCollection
            'reqparm.Add("param1", "somevalue")
            'reqparm.Add("param2", "othervalue")
            'Dim responsebytes = client.UploadValues(negerpath, "POST", reqparm)
            Dim pod_id As String = ""
            Dim pod_name As String = ""
            'Get pods
            Dim responsebytes = client.DownloadData(podpath)
            Dim responsebody = (New Text.UTF8Encoding).GetString(responsebytes)
            Dim podjson As JObject = JObject.Parse(responsebody)
            pod_id = podjson.SelectToken("result[0].id").ToString
            pod_name = podjson.SelectToken("result[0].room.name").ToString
            Console.WriteLine("-")
            Console.WriteLine("Connection: " & podjson.SelectToken("status").ToString)
            Console.WriteLine("Found device: " & pod_id & " (Room: " & pod_name & ")")
            Console.WriteLine("Getting status for device: " & pod_id)
            Console.WriteLine("-")

            'Get pods values.
            Dim measurepath As String = "https://home.sensibo.com/api/v2/pods/" & pod_id & "/measurements?fields=batteryVoltage,temperature,humidity,time&apiKey=" & apikey
            Dim measurebytes = client.DownloadData(measurepath)
            Dim measureresponse = (New Text.UTF8Encoding).GetString(measurebytes)
            Dim measurejson As JObject = JObject.Parse(measureresponse)
            Dim temp_val As String = measurejson.SelectToken("result[0].temperature").ToString
            Dim hum_val As String = measurejson.SelectToken("result[0].humidity").ToString
            Dim voltage As String = measurejson.SelectToken("result[0].batteryVoltage").ToString
            Dim timeago As String = measurejson.SelectToken("result[0].time.secondsAgo").ToString
            Dim timestamp As String = measurejson.SelectToken("result[0].time.time").ToString
            Console.WriteLine("Temperature: " & temp_val)
            Console.WriteLine("Humidity: " & hum_val)
            Console.WriteLine("Time ago: " & timeago)
            Console.WriteLine("Timestamp: " & timestamp)
            Console.WriteLine("Voltage: " & voltage)
            Console.WriteLine("-")



            Console.ReadKey()
        End Using






        'Public Class Result
        '   Public Property id As String
        'End Class

        'Public Class pods
        'Public Property status As String
        'Public Property result As Result()

        'End Class
    End Sub

End Module

 

 

sensibo-app.JPG

Lenke til kommentar
Del på andre sider

Ser jo bra ut! :)

Da trenger du en root device (som bl.a. lagrer IDen), 5 child devicer for output (temp, humid, etc) og tilsvarende for det du skal styre.

 

Hvilke controller har du?

 

 

Mitt hovedtips er å lage et enkelt Console applikasjon i VB.NET. Når du kan lese ut data med det og sende kommandoer til varmepumpa, så er du klar for å lage en plugin. :)

Lenke til kommentar
Del på andre sider

controller har jeg ikke begynt på enda..  Men man kan sette temp (Int 0-33)fanmode(heat, cool)  og fanspeed (low, medium, high, auto) 

 

Har nå alt klart ift å polle data, så er det det å få sendt kommandoene da.. 

 

Fant ikke ut hvordan jeg skal ta høyde for om en bruker har flere "pods" dvs om han styrer flere varmepumper.. 

Lenke til kommentar
Del på andre sider

Den ‎11‎.‎03‎.‎2017 klokken 22.53, Gjelsvik skrev:

Fant ikke ut hvordan jeg skal ta høyde for om en bruker har flere "pods" dvs om han styrer flere varmepumper.. 

Hvis du lagrer all nødvendig informasjonen i root, og henter accociated devices (altså child devices) fra den, så har du alt du trenger.

 

For hver poll kjører du da For each root in Roots som illustrert i "CheckAndCreateDevices()".

 

 

Her er min poll fra FitbitSeer:

    ''' <summary>
    ''' A timer to fetch new data every X minutes, configured in InitIO
    ''' </summary>
    ''' <remarks>By Moskus</remarks>
    Private Sub UpdateTimerTrigger(ByVal obj As Object)
        If Me.Settings.LogTimerElapsed Then Log("Timer elapsed. Updating Fitbit-data.")

        Dim devs = (From d In Devices()
                    Where d.Interface(hs) = Me.Name _
                    And d.DeviceType_Get(hs).Device_SubType_Description.ToLower = "root").ToList

        For Each d In devs
            Dim ref As Integer = d.Ref(hs)

            Dim t As New Thread(AddressOf UpdateFitbitData)
            t.Start(ref)
        Next
    End Sub
    
    Private Sub UpdateFitbitData(ByVal rootref As Integer)
        Dim f As FitbitSetup = FitbitSetup.GetRootData(rootref) 'FitbitSetup er min egen klasse for å lese ut og tolke verdier fra Fitbit
        If f IsNot Nothing Then
            f.UpdateData(rootref)
        End If

    End Sub

 

Lenke til kommentar
Del på andre sider

Du tenker da en root for pluginen generelt, der jeg lagrer f.eks id til hver enkelt "pod" jeg finner tilknyttet.
Deretter en root for hver pod, som har sine respektive childs for hver verdi (temp, fuktighet, instillt temperatur etc)?

 

Har nå finpusset litt på parsingen av json, så nå klarer jeg håndtere flere "pods" om noen har dette. 

Så er det det å lage tilhørende devicer, og lage en slags tabell (evt lagrer i PED) der man klarer å håndtere hvilken pod som har hvilken id i APIet, og hvilken childs som tilhører hvilken pod.

 

Så tar jeg actions/kontroll knappene helt til slutt. Tror det blir den største utfordringen. Men kikker litt på PED nå, og om jeg lagrer pod id for hver enkelt child så bør det være enkelt å håndtere kall mot api.

 

Egentlig skal jo mine root devices lages som en termostat. Det må jo være en egen deviceklasse som heter det? Jeg har target temp, følt temp, on/off kommandoer. Det ville i allefall vært det beste ift å bruke den videre i Imperihome osv..

Lenke til kommentar
Del på andre sider

32 minutter siden, Gjelsvik skrev:

Du tenker da en root for pluginen generelt, der jeg lagrer f.eks id til hver enkelt "pod" jeg finner tilknyttet.

Nei, jeg tenker en root pr pod, og ferdig med det. En root representerer en pod. Er det ingen roots har du ingen pod'er i HomeSeer. :) 

 

33 minutter siden, Gjelsvik skrev:

Deretter en root for hver pod, som har sine respektive childs for hver verdi (temp, fuktighet, instillt temperatur etc)?

Ja, hver root har sine respektive child-devices. :)

 

35 minutter siden, Gjelsvik skrev:

Så er det det å lage tilhørende devicer, og lage en slags tabell (evt lagrer i PED) der man klarer å håndtere hvilken pod som har hvilken id i APIet, og hvilken childs som tilhører hvilken pod.

HomeSeer lagrer assosiasjonene (altså hvis du har en root, får du device Ref til alle child devices), så det kan brukes direkte. :)

 

36 minutter siden, Gjelsvik skrev:

Det må jo være en egen deviceklasse som heter det?

Det er det. :) 

Lenke til kommentar
Del på andre sider

Ugg.. Må tenke litt på dette. 

Selv om HS vet hvilke child som tilhører hvilken root. Så må jeg programatisk finne en måte å gjøre det baklengs.

 

Hvis en child som har on/off status blir kontrollert. F.eks status blir satt til Off.

Så må jeg i pluginen hente ut hvilken root den tilhører. deretter et eller annet sted finne hvilken pod-id som tilhører denne rooten. (1:1 tabell i PED, evt bare bruke en ini fil?) Så utføre webrequest mot apiet, 

 

Lenke til kommentar
Del på andre sider

36 minutter siden, Gjelsvik skrev:

Hvis en child som har on/off status blir kontrollert. F.eks status blir satt til Off.

Så må jeg i pluginen hente ut hvilken root den tilhører. deretter et eller annet sted finne hvilken pod-id som tilhører denne rooten. (1:1 tabell i PED, evt bare bruke en ini fil?) Så utføre webrequest mot apiet, 

Riktig.

 

Dette hadde jeg gjort:

1. Du setter child'en for Status blir satt til "Off"

2. SetIOMulti() blir trigget, og får Device Ref til devicen Status og tilhørende CAPI-trigger.

3. Du henter ut root-devicen sin ref (child devices har kun én assosisert device) og henter ut IDen fra PED (f.eks) eller device_subtype, eller noe slikt.

4. Nå har du både pod-IDen og kommando og kan sende en web-request, gjerne i en ny tråd (for å ikke låse plugin'en din mens kommandoen blir utført).

5. Den nye tråden venter på svar (til en timeout; la oss si 5-10 sekunder). Hvis success, så bruker du den vanlige "hs.SetDeviceValue(REF_TIL_STATUS, ON_VALUE_FEKS_100, True)" :)

 

 

Lenke til kommentar
Del på andre sider

Takk igjen Moskus.

 

Da har jeg noe å gripe fatt på i kveld :) 

 

Vet du forresten om det er mulig i VB.net å ha en funksjon som returnerer to eller flere verdier? Tenker å skrive om litt på koden min slik at jeg har en funksjon for å hente ut alle pods (id`er) 

Deretter en annen funksjon som tar en ID som argument og returnerer et sett (liste eller array?)  med alle verdier. 

Lenke til kommentar
Del på andre sider

35 minutter siden, Gjelsvik skrev:

Vet du forresten om det er mulig i VB.net å ha en funksjon som returnerer to eller flere verdier? Tenker å skrive om litt på koden min slik at jeg har en funksjon for å hente ut alle pods (id`er) 

Du kan returnere en "List(Of T)" der T er en type som String, Double, etc. T kan til og med være din egen klasse hvis du ønsker det.

 

Tåpelig eksempel under. En funksjon tar imot en array av tall og dobler dem, og disse nye tallene blir returnert i en List(Of Double).

    Function DoubleTheseNumbers(ByVal numbers() As Double) As List(Of Double)
        Dim ret As New List(Of Double)
        For Each d In numbers
            ret.Add(d * 2)
        Next

        Return ret
    End Function

    Sub SomeSub()
        Dim nums() As Double = {0.1, 0.2, 0.3}
        Dim lst As List(Of Double) = DoubleTheseNumbers(nums)

        For Each d In lst
            Console.WriteLine(d)
        Next
    End Sub

... vil selvfølgelig gi:

Sitat

0,2

0,4

0,6

 

 

Hvis du sender inn en tom array av tall, får du en tom List(Of Double) tilbake, og dermed blir ingenting skrevet ut.

 

Det nydelige med denne måten å gjøre det på er at lister kan brukes sammen med Linq. Og Linq er fantastisk! :) 

 

Hvorfor er Linq så genialt? Jo, fordi du kan gjøre spørringer på (bl.a.) lister, og det er opphavet til Lamda-funksjoner. Dermed kan du f.eks. redusere koden i "SomeSub" over til dette (der vi har kombinerer List, Linq og Lambda-funksjoner):

DoubleTheseNumbers({0.1, 0.2, 0.3}).ForEach(Sub(x) Console.WriteLine(x))

.... som også vil gi:

 

Sitat

0,2

0,4

0,6

Lenke til kommentar
Del på andre sider

Woop woop

Mangler "bare" kontroll funksjonene nå :D

 

Endte opp med å lage en egen klasse, og så fant jeg ut av "List of T" kan være en liste med objekter av en klasse.. Så da kan jeg jo putte alt i en instans av klassen, putte den i en liste, og så flytte med meg listen rundt omkring for å oppdatere device med resultat fra json.

 

 

 

sese.JPG

  • Like 1
Lenke til kommentar
Del på andre sider

Høres bra ut! :D 

 

 

Den ‎13‎.‎03‎.‎2017 klokken 14.59, Moskus skrev:

Du kan returnere en "List(Of T)" der T er en type som String, Double, etc. T kan til og med være din egen klasse hvis du ønsker det.

 

7 timer siden, Gjelsvik skrev:

Endte opp med å lage en egen klasse, og så fant jeg ut av "List of T" kan være en liste med objekter av en klasse..

 

Lenke til kommentar
Del på andre sider

Bli med i samtalen

Du kan publisere innhold nå og registrere deg senere. Hvis du har en konto, logg inn nå for å poste med kontoen din.

Gjest
Skriv svar til emnet...

×   Du har limt inn tekst med formatering.   Lim inn uten formatering i stedet

  Du kan kun bruke opp til 75 smilefjes.

×   Lenken din har blitt bygget inn på siden automatisk.   Vis som en ordinær lenke i stedet

×   Tidligere tekst har blitt gjenopprettet.   Tøm tekstverktøy

×   Du kan ikke lime inn bilder direkte. Last opp eller legg inn bilder fra URL.

×
×
  • Opprett ny...

Viktig informasjon

Vi har plassert informasjonskapsler/cookies på din enhet for å gjøre denne siden bedre. Du kan justere dine innstillinger for informasjonskapsler, ellers vil vi anta at dette er ok for deg.