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

Device Change (History) to InfluxDB


torhaala

Anbefalte innlegg

Hei,

 

Tenkte at dette kunne være av interesse for noen; direkte logging av all device history til InfluxDB

 

Etter å ha prøvd litt forskjellige løsninger på logging av device history til db, blant annet 'Device History to Graphite' fra Grøtan (funker bra fra HS3/HomeTroller sin side, men i docker på min NAS ble python prosessen til Carbon litt vel CPU sulten) og logging via MQTT plugin og Telegraf til InfluxDB, kom jeg over scriptet under fra denne topic'en på HS forumet https://forums.homeseer.com/showthread.php?t=194145

 

Dette scriptet logger automatisk alle device changes (minus de du definerer som eksluders og timers) direkte til InfluxDB uten å gå via MQTT e.l. Fungerer veldig fint hos meg, men pass på at det ikke brukes komma i device name da dette lager problemer med stringen som blir postet til InfluxDB.

 

Har med dette disabled Device History og bruker nå mindre ressurser en tidligere på HomeTrolleren, videre så kjører jeg en enkelt docker container på NAS'en med InfluxDB og Grafana, noe som nesten ikke tar noen ressurser i det hele tatt.

 

Man kan også enkelt sette opp f.eks Telegraf på HS3 maskinen og logge cpu/mem usage osv.. for oss som ikke kan bruke Jon00 sitt script for windows

 

Scriptet:

'VB.Net script to write Homeseer 3 values to InfluxDB
'Created by Brian based on code found on the Homeseer forums. No warranty. Use at your own risk.
'Uncomment the log statements if you're having problems to try to track down the error.

'Installation Instrustions: 
'	0: Install InfluxDB & get it running
'	1: Modify the variables below to fit your system.
'	2: Add this line to Homeseer\Scripts\Startup.vb
'    hs.RegisterStatusChangeCB("L2DB-influxdb.vb","Main")
'	3: Restart Homeseer

Imports System.Core
Imports System.Web
Imports System.Net
Imports System.IO
Imports System.Text

Public Sub Main(ByVal Parms As Object)

    '==========================================================
    'Modify these to fit your system
    Dim INFLUX_DB_SERVER_IP = "x.x.x.x"
    Dim INFLUX_DB_SERVER_PORT = "8086"
    Dim INFLUX_DB_DATABASE_NAME = "DBNAME"
    Dim SKIP_LIST = "" 'comma separated list of device references to skip logging
    '==========================================================

    Dim device_name, device_location, device_location2, deviceObj, device_type, problem
    Dim dev_address As String
    Dim device_value As Double
    Dim devRef As Integer
	
	
'    hs.WriteLog("L2DB-InfluxDB", "Script running")

	'Get device info from Homeseer
    dev_address = Parms(1) 'address of device. 
    device_value = Parms(2) 'new value of device
    devRef = Parms(4) 'Device reference of the device 
    deviceObj = hs.GetDeviceByRef(devRef)
    device_name = deviceObj.name(hs)
    device_location = deviceObj.location(hs)
    device_location2 = deviceObj.location2(hs)
    device_type = deviceObj.Device_Type_String(hs)

	If device_type = "Timer" Then 'Don't log timers
		Exit Sub
	End If
	
	If SKIP_LIST <> "" Then 
		Dim skips = SKIP_LIST.split(New Char() {","c})
		Dim skip as String
		For Each skip in Skips
			If devref = skip
				Exit Sub
			End If
		Next
	End If
	
	hs.WriteLog("L2DB-InfluxDB", "Logging to Database: Reference: " & devref & " Address: " & dev_address & ", Device Name: " & device_name & ", New Value: " & device_value)

	'Build the post data string
	Dim postdata as String = devref
	If device_name <> "" Then 
		postdata = postdata & ",name=" & device_name
	End If
	If device_location <> "" Then 
		postdata = postdata & ",location=" & device_location
	End If
	If device_location2 <> "" Then 
		postdata = postdata & ",location2=" & device_location2
	End If
	If device_type <> "" Then 'Types are optional and not all devices have them
		postdata = postdata & ",type=" & device_type
	End If
	If dev_address <> "" Then 'Addresses are optional and not all devices have them
		postdata = postdata & ",address=" & dev_address
	End If

    ' !! Using commas in the HS3 device names will cause influxdb to return an error when posting the data
    postdata = postdata.Replace(" ", "\ ")
    postdata = postdata & " value=" & device_value

    '    hs.WriteLog("L2DB-InfluxDB", postdata)

    'Set up the Webrequest
    Dim url = "http://" & INFLUX_DB_SERVER_IP & ":" & INFLUX_DB_SERVER_PORT & "/write?db=" & INFLUX_DB_DATABASE_NAME
	Dim httpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)

	'Dim httpWebRequest = DirectCast(WebRequest.Create("https://requestb.in/XXXXXXX"), HttpWebRequest)  'For testing- to see what the request contains
	
	httpWebRequest.ContentType = "application/x-www-form-urlencoded"
	httpWebRequest.Method = "POST"
	Dim encoding As New System.Text.UTF8Encoding

	'Make the request to the database
	Try
		Dim data As Byte() = encoding.GetBytes(postdata)
		httpWebRequest.ContentLength = data.Length
		Dim myStream As Stream = httpWebRequest.GetRequestStream()
        
		If data.Length > 0 Then
			myStream.Write(data, 0, data.Length)
			myStream.Close()
		End If
	Catch ex As Exception
		hs.WriteLog("L2DB-InfluxDB", "Error: " & ex.ToString())
	End Try
	
	Try
		Dim httpResponse = DirectCast(HttpWebRequest.GetResponse(), HttpWebResponse)
        Dim myReader As StreamReader
        Dim myStream As Stream
        myStream = httpResponse.GetResponseStream()
		myReader = New StreamReader(myStream) 
		Dim responseText = myReader.ReadToEnd()
        '       hs.WriteLog("L2DB-InfluxDB", "Response: " & responseText)

    Catch ex As Exception
		hs.WriteLog("L2DB-InfluxDB", "Error: " & ex.ToString())
		hs.WriteLog("L2DB-InfluxDB", "Request was: " & postdata)
	End Try

End Sub

 

Endret av torhaala
Corrections
  • Like 3
Lenke til kommentar
Del på andre sider

  • 2 uker senere...

Det var jo veldig likt dette fra homeseer.com forumet, men mulig det er du som er "bdc" på det forumet?

https://forums.homeseer.com/showthread.php?t=194145

 

 

Jeg har fiklet litt på tilsvarende script, bare at mot mysql. (fikk aldri influx til å gjøre som jeg ville mot grafana)

Men har et spm ift "hs.RegisterStatusChangeCB" som utløser scriptet. Denne callbacken skal kjøres hver gang en device endres.

Jeg ønsker kontinuerlige grafer, også når en device verdi ikke er endret. Så har derfor satt opp en jevnlig event som bare tar "get-set" på samme verdi som den allerede har. Dette gjør at "Last update" endres, og homeseer registrerer at verdi er satt på nytt. MEN dette er tydeligvis ikke nok til å trigge hs.RegisterStatusChangeCB.. 

Finnes det noen god løsning? Jeg har trikset det til med verdi = verdi + 0.001, slik at det faktisk er en endring, og da trigges callback, og verdi skrives til mysql.

Lenke til kommentar
Del på andre sider

9 hours ago, Gjelsvik said:

Det var jo veldig likt dette fra homeseer.com forumet, men mulig det er du som er "bdc" på det forumet?

https://forums.homeseer.com/showthread.php?t=194145

 

 

Jeg har fiklet litt på tilsvarende script, bare at mot mysql. (fikk aldri influx til å gjøre som jeg ville mot grafana)

Men har et spm ift "hs.RegisterStatusChangeCB" som utløser scriptet. Denne callbacken skal kjøres hver gang en device endres.

Jeg ønsker kontinuerlige grafer, også når en device verdi ikke er endret. Så har derfor satt opp en jevnlig event som bare tar "get-set" på samme verdi som den allerede har. Dette gjør at "Last update" endres, og homeseer registrerer at verdi er satt på nytt. MEN dette er tydeligvis ikke nok til å trigge hs.RegisterStatusChangeCB.. 

Finnes det noen god løsning? Jeg har trikset det til med verdi = verdi + 0.001, slik at det faktisk er en endring, og da trigges callback, og verdi skrives til mysql.

 

Jeg er ikke bdc nei, og det er helt likt det fra homeseer forumet.. derfor jeg linket til den tråden i innlegget mitt ;) Tenkte bare at dette var interessant for noen.

 

Jeg er ikke sikkert ift spm ditt ang trigging av statuschange. Med grafana så setter jeg opp slik at den fyller inn null values med previous value og da har ikke dette vært noe problem egentlig.

Lenke til kommentar
Del på andre sider

Hvor i grafana gjør du det? Kan teste det.

 

F.eks grafen på elbil batteriet mitt blir litt feil.

Batteriet får 100% kl 04 om natta. Neste endring er første gang den rapporterer ny batteristatus, der status ikke er 100%. Så det er når jeg er på vei til jobb f.eks kl 7.30

Og la oss si at batteristatus er 90% kl 08.

 

Nå vil grafen skrå ned fra kl 04 til kl 08, slik at det ser ut som at batteriet har tappet seg hele morgenen. Dette er fordi homeseer ikke trigges når en verdi bli satt, men ikke endres. Jeg vil jo gjerne ha datapunkter i databasen, selv om verdien ikke nødvendigvis har endret seg.

 

 

df.PNG

Endret av Gjelsvik
Lenke til kommentar
Del på andre sider

12 minutes ago, Gjelsvik said:

Dette er fordi homeseer ikke trigges når en verdi bli satt, men ikke endres

Dette mener jeg du kan styre selv. Du kan gå inn på enheten og fjerne haken for at den ikke skal oppdatere hvis verdien er det samme.

  • Like 1
Lenke til kommentar
Del på andre sider

Ja, men det gjelder bare kolonnen som heter "Last Change"

Har slått på logging i scriptet som trigges av hs.RegisterStatusChangeDB() og det blir ikke trigget om man setter en devicestatus til samme verdi som den har.

 

f.eks med 

hs.setDeviceValueByRef(465, hs.DeviceValueEx(465), True)

Endret av Gjelsvik
Lenke til kommentar
Del på andre sider

8 hours ago, Gjelsvik said:

Hvor i grafana gjør du det? Kan teste det.

 

F.eks grafen på elbil batteriet mitt blir litt feil.

Batteriet får 100% kl 04 om natta. Neste endring er første gang den rapporterer ny batteristatus, der status ikke er 100%. Så det er når jeg er på vei til jobb f.eks kl 7.30

Og la oss si at batteristatus er 90% kl 08.

 

Nå vil grafen skrå ned fra kl 04 til kl 08, slik at det ser ut som at batteriet har tappet seg hele morgenen. Dette er fordi homeseer ikke trigges når en verdi bli satt, men ikke endres. Jeg vil jo gjerne ha datapunkter i databasen, selv om verdien ikke nødvendigvis har endret seg.

 

 

df.PNG

 

Hmm ok, ser hvor du vil hen men ikke sikker det vil bli så fine grafer (blir noe firkantet) av det jeg tenkte på; under Metrics hvor du definerer de forskjellige query'ene kan du sette Group By: time ($interval) fill (previous).

 

Lenke til kommentar
Del på andre sider

Fant ikke noen options under Metric, bare text feltet for queryen. Og query validerer ikke om jeg legger til "Group By: time ($interval) fill (previous)"  

Men har løst det ved å kjøre scriptet fra homeseer med jevne mellomrom, fremfor å la det trigges av devicechange. Grafene bli litt firkantet akkurat i dette tilfellet med batterinivå, men det er jo slik batteriet oppfører seg. En graf som "skrår" ned midt på natten er jo misvisende all den tid batteriet faktisk er fulladet hele natten.

Lenke til kommentar
Del på andre sider

Fint du fikk det til.

 

Kopierte inn teksten fra en av mine queries bare i tilfelle det skulle være til nytte (hvor 200 er deviceid):

SELECT mean("value") FROM "200" WHERE $timeFilter GROUP BY time($interval) fill(previous)

Lenke til kommentar
Del på andre sider

Jeg prøvde denne ikveld, den logget 1 device, også kom det bare feilmeldinger for hver eneste device change etterpå :(

 

Error: System.Net.WebException: The operation has timed out at Microsoft.VisualBasic.CompilerServices.Symbols.Container.Inv okeMethod(Method TargetProcedure, Object[] Arguments, Boolean[] CopyBack, BindingFlags Flags) at Microsoft.VisualBasic.CompilerServices.NewLateBinding.Object LateGet(Object Instance, Type Type, String MemberName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean[] CopyBack) at Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateGe t(Object Instance, Type Type, String MemberName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean[] CopyBack) at scriptcode9.VBWrapper.Main(Object Parms)

Endret av Actibus
Lenke til kommentar
Del på andre sider

  • 3 uker senere...
On 02/05/2018 at 21:48, Actibus said:

Jeg prøvde denne ikveld, den logget 1 device, også kom det bare feilmeldinger for hver eneste device change etterpå :(

 

Error: System.Net.WebException: The operation has timed out at Microsoft.VisualBasic.CompilerServices.Symbols.Container.Inv okeMethod(Method TargetProcedure, Object[] Arguments, Boolean[] CopyBack, BindingFlags Flags) at Microsoft.VisualBasic.CompilerServices.NewLateBinding.Object LateGet(Object Instance, Type Type, String MemberName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean[] CopyBack) at Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateGe t(Object Instance, Type Type, String MemberName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean[] CopyBack) at scriptcode9.VBWrapper.Main(Object Parms)

Du kan øke timeouten:

	Dim data As Byte() = encoding.GetBytes(postdata)
	httpWebRequest.ContentLength = data.Length
	httpWebRequest.Timeout = 5000
	Dim myStream As Stream = httpWebRequest.GetRequestStream()

Det måtte jeg gjøre når influx kjørte på en annen maskin.

Lenke til kommentar
Del på andre sider

  • 2 måneder senere...

Jeg har også litt utfordringer med det scriptet. Devicene som logges logges kun innimellom, jeg jeg har flust med feilmeldinger :/

 

På 5/18/2018 den 23.30, Actibus skrev:

Takk, men endte opp med å lage et eget script og logge til en SQL database istedenfor, mer kjent territorium for meg 1f609.png

....du har ikke lyst til å dele det scriptet? *plystre* :P

 

Lenke til kommentar
Del på andre sider

22 timer siden, Julius skrev:

Jeg endte med å plasere influxdb på samme maskin. Ingen grunn til at det skulle time ut, men det gjorde det.

Jeg kjører alt på samme maskin, men sliter fortsatt med å få inn data i databasen - antagelig pga timeout.

Bruker du eksakt samme script som i første post, eller har du gjort noen modifikasjoner?

Lenke til kommentar
Del på andre sider

'VB.Net script to write Homeseer 3 values to InfluxDB
'Created by Brian based on code found on the Homeseer forums. No warranty. Use at your own risk.
'Uncomment the log statements if you're having problems to try to track down the error.

'Installation Instrustions: 
'	0: Install InfluxDB & get it running
'	1: Modify the variables below to fit your system.
'	2: Add this line to Homeseer\Scripts\Startup.vb
'    hs.RegisterStatusChangeCB("L2DB-influxdb.vb","Main")
'	3: Restart Homeseer

Imports System.Core
Imports System.Web
Imports System.Net
Imports System.IO
Imports System.Text

Public Sub Main(ByVal Parms As Object)
	'==========================================================
	'Modify these to fit your system
	dim INFLUX_DB_SERVER_IP = "127.0.0.1"
	dim INFLUX_DB_SERVER_PORT = "8086"
	dim INFLUX_DB_DATABASE_NAME = "homeseer"
	dim SKIP_LIST = "" 'comma separated list of device references to skip logging
	'==========================================================

	dim device_name, device_location, device_location2, deviceObj, device_type, problem
	dim dev_address as string
    Dim device_value As Double
    Dim devRef As Integer	
	
	'Get device info from Homeseer
    dev_address = Parms(1) 'address of device. 
    device_value = Parms(2) 'new value of device
    devRef = Parms(4) 'Device reference of the device 
    deviceObj = hs.GetDeviceByRef(devRef)
    device_name = deviceObj.name(hs)
    device_location = deviceObj.location(hs)
    device_location2 = deviceObj.location2(hs)
    device_type = deviceObj.Device_Type_String(hs)

	If device_type = "Timer" Then 'Don't log timers
		Exit Sub
	End If
	
	If SKIP_LIST <> "" Then 
		Dim skips = SKIP_LIST.split(New Char() {","c})
		Dim skip as String
		For Each skip in Skips
			If devref = skip
				Exit Sub
			End If
		Next
	End If
	
	'Build the post data string
	Dim postdata as String = ""
	If device_location2 <> "" Then 
		postdata = postdata & device_location2
	End If
	If device_location <> "" Then 
		postdata = postdata & "_" & device_location
	End If
	If device_name <> "" Then 
		postdata = postdata & "_" & device_name
	End If
	
	postdata = postdata.Replace(" ", "_")
	postdata = postdata & " value=" & device_value
	
'	hs.WriteLog("L2DB-InfluxDB", postdata)
	
	'Set up the Webrequest
	Dim url = "http://" & INFLUX_DB_SERVER_IP & ":" & INFLUX_DB_SERVER_PORT & "/write?db=" & INFLUX_DB_DATABASE_NAME
	Dim httpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)

	'Dim httpWebRequest = DirectCast(WebRequest.Create("https://requestb.in/XXXXXXX"), HttpWebRequest)  'For testing- to see what the request contains
	
	httpWebRequest.ContentType = "application/x-www-form-urlencoded"
	httpWebRequest.Method = "POST"
	Dim encoding As New System.Text.UTF8Encoding

	'Make the request to the database
	Try
		hs.WriteLog("L2DB-InfluxDB", "Logging to Database: Reference: " & devref & " Address: " & dev_address & ", Device Name: " & device_name & ", New Value: " & device_value & ", Server: " & INFLUX_DB_SERVER_IP & ", post: " & postdata)
		Dim data As Byte() = encoding.GetBytes(postdata)
		httpWebRequest.ContentLength = data.Length
		httpWebRequest.Timeout = 1000
		Dim myStream As Stream = httpWebRequest.GetRequestStream()
        
		If data.Length > 0 Then
			myStream.Write(data, 0, data.Length)
			myStream.Close()
		End If

		Try
			Dim httpResponse = DirectCast(HttpWebRequest.GetResponse(), HttpWebResponse) 
			dim myReader As StreamReader 
			dim responseStream as Stream
			responseStream = httpResponse.GetResponseStream()
			myReader = New StreamReader(responseStream) 
			Dim responseText = myReader.ReadToEnd() 
	'		hs.WriteLog("L2DB-InfluxDB", "Response: " & responseText) 

		Catch ex As Exception
			hs.WriteLog("L2DB-InfluxDB", "Error: " & ex.ToString())
			hs.WriteLog("L2DB-InfluxDB", "Request was: " & postdata)
		End Try
	Catch ex As Exception
		hs.WriteLog("L2DB-InfluxDB", "Error: " & ex.ToString())
	End Try
	

End Sub

Litt mod, men ikke mye. Liker best floor_room_name som id slik at det blir lettere å finne i grafana. Jeg starta også på skratch med ny db.

Endret av Julius
Lenke til kommentar
Del på andre sider

Ser da meget bra ut Julius.

 

Sliter du forresten fortsatt med timeouts? Jeg har hatt det en gang, etter at NAS'en som kjører InfluxDB restartet. Selv etter at DB'en var oppe å kjørte fortsatte dette. Det ble løst ved å ha DB kjørende og så restarte HS. Utover dette har det fungert upåklagelig i ca 3 måneder nå (HS på en HomeTroller SEL og InfluxDB i en docker container på Synology NAS). Mulig noen eldre versjoner av Mono lager litt krøll hvis dette kjøres på linux?

Lenke til kommentar
Del på andre sider

På 27.7.2018 den 17.14, pingla skrev:

Jeg har også litt utfordringer med det scriptet. Devicene som logges logges kun innimellom, jeg jeg har flust med feilmeldinger :/

 

....du har ikke lyst til å dele det scriptet? *plystre* :P

 

 

Public Sub Main(ByVal Parms As Object)
       
        Dim devValue As String = hs.DeviceVSP_GetStatus(Parms, hs.DeviceValueEx(Parms), ePairStatusControl.Status)
        Dim devName As String = Nothing
        Dim dev As Scheduler.Classes.DeviceClass
        dev = hs.GetDeviceByRef(Parms)
        devName = dev.Name(hs)
        Dim devTime As DateTime
        devTime = DateTime.Now


 Dim devValue2 As String = devValue.Remove(devValue.Length - 3)
 Dim devValueInt As Integer = Convert.ToInt32(devValue2)

        'If devValue2.Length > 2 Then
        
        hs.WriteLog("WriteToSql - Device# "+ Parms, devValue)
        

        Dim myconnect As New System.Data.SqlClient.SqlConnection
        myconnect.ConnectionString = "Data Source=tcp:server,49172;Initial Catalog=HomeSeer;Persist Security Info=True;User ID=HS;Password=xxxx"


        Dim mycommand As System.Data.SqlClient.SqlCommand = New System.Data.SqlClient.SqlCommand()
        mycommand.Connection = myconnect
        mycommand.CommandText = "INSERT INTO dbo.devLog (devRef, devName, devValue, devTime, devValueInt) VALUES (@Parms, @devName, @devValue, GETUTCDATE(), @devValueInt)"
        myconnect.Open()

        Try
            mycommand.Parameters.Add("@Parms", SqlDbType.Int).Value = Parms
            mycommand.Parameters.Add("@devName", SqlDbType.NVarChar).Value = devName
            mycommand.Parameters.Add("@devValue", SqlDbType.VarChar).Value = devValue.Remove(devValue.Length - 3)
            mycommand.Parameters.Add("@devValueInt", SqlDbType.Int).Value = devValueInt
            mycommand.Parameters.Add("@devTime", SqlDbType.VarChar).Value = devTime
            mycommand.ExecuteNonQuery()
            'MsgBox("Success")
        Catch ex As System.Data.SqlClient.SqlException
            'MsgBox(ex.Message)
        End Try
        myconnect.Close()

        ''
'End If
    
    End Sub

 

 

Trigger denne hver gang jeg leser av forbruket via HAN porten 

Lenke til kommentar
Del på andre sider

2 hours ago, torhaala said:

Ser da meget bra ut Julius.

 

Sliter du forresten fortsatt med timeouts? Jeg har hatt det en gang, etter at NAS'en som kjører InfluxDB restartet. Selv etter at DB'en var oppe å kjørte fortsatte dette. Det ble løst ved å ha DB kjørende og så restarte HS. Utover dette har det fungert upåklagelig i ca 3 måneder nå (HS på en HomeTroller SEL og InfluxDB i en docker container på Synology NAS). Mulig noen eldre versjoner av Mono lager litt krøll hvis dette kjøres på linux?

 

Jeg kjører windows, men jeg fant nettopp ut at jeg muligens hadde en deffekt switch i nettverket mitt. Det kan ha vært årsaken til mine timeouts.

Lenke til kommentar
Del på andre sider

  • 2 måneder senere...

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.