Parsing Vera User Data - Loadable as .NET Dataset

From MiOS
(Difference between revisions)
Jump to: navigation, search
(New page: There is most likely not an elegant way to dothis, but in case someone wants something similar feel free to use this. Please suggest if there are better ways of accomplishing this and if y...)
 
 
(11 intermediate revisions by 2 users not shown)
Line 1: Line 1:
There is most likely not an elegant way to dothis, but in case someone wants something similar feel free to use this. Please suggest if there are better ways of accomplishing this and if you happen to know so, update this page :)
+
[[Category:Development]][[Category:How_To]]
  
1. This will give you a single xml file you could load in .NET through Dataset.Readxml and you will get about 14 tables.  
+
This is most likely not an elegant way to do this, but in case someone wants something similar feel free to use this. Please suggest if there are better ways of accomplishing this and if you happen to know so, update this page :)
 +
 
 +
1. This will give you a single xml file you could load in .NET through Dataset.Readxml and you will get about 48tables.  
 
<br/>
 
<br/>
 
<br/>
 
<br/>
2. Devices have states and ControlURLs , these become a separate table with a new attribute added to refer what Device ID  a row in these tables would relate to the devices table.  
+
2. Nested tables like Devices have states and ControlURLs - these become a separate table with a new attribute added to refer what Device ID  a row in these tables would relate to the devices table.  
 
<br/>
 
<br/>
 
<br/>
 
<br/>
Line 10: Line 12:
  
 
<br/>
 
<br/>
 +
Using the functions below, a small .NET web app that shows Rooms/Scenes/Devices (Code for that below)  - Also see the forum post:
  
 +
http://forum.micasaverde.com/index.php?topic=7950.0 [http://forum.micasaverde.com/index.php?topic=7950.0]
  
----
+
Public Class _Default
 +
    Inherits System.Web.UI.Page
  
     Private Sub Parse_UserData_To_DataSet(ByVal OutputFolder As String, _
+
     Dim UserDataset As DataSet
                                          Optional ByVal veraURL As String = "http://myhome:49451")
+
    Dim ud As UserData
 
+
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim Entries As New ArrayList
+
         If Not Page.IsPostBack Then
        Dim ds As New DataSet
+
            If Session("UserData") Is Nothing Then
        Dim userDatajson As String = GetWebPageContent(veraURL & "/data_request?output_format=json&id=user_data")
+
                ud = New UserData
        Dim userData As String = GetWebPageContent(veraURL & "/data_request?output_format=xml&id=user_data")
+
                Session("UserData") = ud.Parse_UserData_To_DataSet("d:\test")
 
+
        'Create Root Data file
+
        Dim si As Integer = userData.IndexOf("<root")
+
        Dim ei As Integer = userData.IndexOf(">", si)
+
        Dim rootstr As String = userData.Substring(si, ei - si + 1)
+
        rootstr = rootstr.Replace(vbLf, "") & "</root>"
+
         Dim fo As New IO.StreamWriter(OutputFolder & "\root.xml")
+
        fo.WriteLine(rootstr)
+
        fo.Close()
+
 
+
        Entries.Add("root")
+
        'create rest of it!
+
        Dim jo As New JSONObject(userDatajson)
+
        For Each s As KeyValuePair(Of String, String) In jo._properties
+
            si = userData.IndexOf("<" & s.Key & ">")
+
            ei = userData.IndexOf("</" & s.Key & ">")
+
            If si >= 0 AndAlso ei > 0 Then
+
                Dim thisEntry As String = userData.Substring(si, ei - si + ("</" & s.Key & ">").Length)
+
                Dim fname As String = OutputFolder & "\" & s.Key & ".xml"
+
                Dim fo1 As New IO.StreamWriter(fname)
+
                fo1.WriteLine(thisEntry)
+
                fo1.Close()
+
                Entries.Add(s.Key)
+
 
             End If
 
             End If
         Next
+
         End If
 
+
         UserDataset = Session("UserData")
         'Put all the tables in a single dataset
+
        GetData()
        Dim finalDS As New DataSet
+
    End Sub
        For Each s As String In Entries
+
            Dim fname As String = OutputFolder & "\" & s & ".xml"
+
            ds = New DataSet
+
            ds.ReadXml(fname)
+
            Try
+
                ds.Tables(0).TableName = s
+
                finalDS.Tables.Add(ds.Tables(0).Copy)
+
                finalDS.Tables(finalDS.Tables.Count - 1).TableName = s
+
            Catch ex As Exception
+
            End Try
+
  
 +
    Sub GetData()
 +
        Dim RoomsTable As DataTable = UserDataset.Tables("rooms")
 +
        Me.RoomsGrid.DataSource = RoomsTable
 +
        Me.RoomsGrid.DataBind()
 +
        RoomsGrid.ShowHeader = False
 +
        Dim ScenesTable As DataTable = UserDataset.Tables("scenes")
 +
        Me.ScenesGrid.DataSource = ScenesTable
 +
        Me.ScenesGrid.DataBind()
 +
        ScenesGrid.ShowHeader = False
 +
        Dim DevicesTable As DataTable = UserDataset.Tables("devices")
 +
        Dim drRemove As DataRow() = DevicesTable.Select("invisible=1")
 +
        For Each dr As DataRow In drRemove
 +
            DevicesTable.Rows.Remove(dr)
 
         Next
 
         Next
 
+
         Me.DevicesGrid.DataSource = DevicesTable
        'devices have controlURL & states
+
         Me.DevicesGrid.DataBind()
        DeviceParse(OutputFolder)
+
         DevicesGrid.ShowHeader = False
 
+
        ds = New DataSet
+
         ds.ReadXml(OutputFolder & "\states.xml")
+
         Try
+
            ds.Tables(0).TableName = "states"
+
            finalDS.Tables.Add(ds.Tables(0).Copy)
+
            finalDS.Tables(finalDS.Tables.Count - 1).TableName = "states"
+
        Catch ex As Exception
+
        End Try
+
        ds = New DataSet
+
         ds.ReadXml(OutputFolder & "\ControlURLs.xml")
+
        Try
+
            ds.Tables(0).TableName = "ControlURLs"
+
            finalDS.Tables.Add(ds.Tables(0).Copy)
+
            finalDS.Tables(finalDS.Tables.Count - 1).TableName = "ControlURLs"
+
        Catch ex As Exception
+
            MsgBox(ex.Message)
+
        End Try
+
 
+
        finalDS.WriteXml(OutputFolder & "\UserData.xml")
+
 
+
 
     End Sub
 
     End Sub
  
 +
End Class
  
    Sub DeviceParse(ByVal OutputFolder As String)
+
<br/>
        'ControlURLs
+
So, This is more like it!!!
        'states
+
<br/>
        Dim filename As String = OutputFolder & "\devices.xml"
+
        Dim ControlURL As String = "<ControlURLs>" & vbCrLf
+
        Dim States As String = "<states>" & vbCrLf
+
  
        Dim ServiceID As Integer = 1
+
Dim masterDs As New DataSet
  
 +
    Sub Parse_UserData_To_DataSet(ByVal OutputFolder As String, _
 +
                                          Optional ByVal veraURL As String = "http://myhome:49451")
 +
        'Parse XML and create XML files to load in to dataset directly
 
         Dim settings As New XmlReaderSettings()
 
         Dim settings As New XmlReaderSettings()
 
         settings.DtdProcessing = DtdProcessing.Parse
 
         settings.DtdProcessing = DtdProcessing.Parse
 
+
         Dim reader As XmlReader = XmlReader.Create(veraURL & "/data_request?output_format=xml&id=user_data", settings)
         Dim reader As XmlReader = XmlReader.Create(filename, settings)
+
 
         Dim doc As New XmlDocument()
 
         Dim doc As New XmlDocument()
 
         doc.Load(reader)
 
         doc.Load(reader)
 
         Dim root As XmlNode = doc.DocumentElement
 
         Dim root As XmlNode = doc.DocumentElement
         Dim ienum As IEnumerator = root.GetEnumerator()
+
         Dim ParseNodeEnum As IEnumerator = root.GetEnumerator
        Dim device As XmlNode
+
         While (ParseNodeEnum.MoveNext)
         While (ienum.MoveNext())
+
             Dim NodeRow As XmlNode = ParseNodeEnum.Current
            device = CType(ienum.Current, XmlNode)
+
             ParseElements(NodeRow, Nothing)
             Dim DeviceID As String = device.Attributes.GetNamedItem("id").InnerText
+
        End While
 
+
    End Sub
            Dim DeviceDetails As XmlNode
+
            Dim devenum As IEnumerator = device.GetEnumerator
+
             While (devenum.MoveNext)
+
                DeviceDetails = CType(devenum.Current, XmlNode)
+
 
+
                Dim devChildNode As XmlNode
+
                Dim childEnum As IEnumerator = DeviceDetails.GetEnumerator
+
                While childEnum.MoveNext
+
                    devChildNode = CType(childEnum.Current, XmlNode)
+
                    Dim DeviceIDAttr As XmlAttribute = doc.CreateAttribute("DeviceID")
+
                    DeviceIDAttr.InnerText = DeviceID
+
                    devChildNode.Attributes.Append(DeviceIDAttr)
+
                    If devChildNode.OuterXml.StartsWith("<state") Then
+
                        States &= devChildNode.OuterXml & vbCrLf
+
                    Else
+
                        Dim serviceIDstr As String = "<service_" & ServiceID
+
                        Dim strtoWrite As String = devChildNode.OuterXml.Replace(serviceIDstr, "<service ID=""" & ServiceID & """ ")
+
                        strtoWrite = strtoWrite.Replace("</service_" & ServiceID & ">", "</service>")
+
                        ControlURL &= strtoWrite & vbCrLf
+
                        ServiceID += 1
+
                    End If
+
                End While
+
  
 +
    Sub ParseElements(ByVal ParseNode As XmlNode, ByVal ParentRow As DataRow)
 +
        Dim dt As DataTable = CreateTable(ParseNode, ParentRow)
 +
        Dim ParseNodeEnum As IEnumerator = ParseNode.GetEnumerator
 +
        While (ParseNodeEnum.MoveNext)
 +
            Dim NodeRow As XmlNode = ParseNodeEnum.Current
 +
            Dim dr As DataRow = dt.NewRow
 +
            'Add Attributes as columns to Datatable
 +
            Dim ienum As IEnumerator = NodeRow.Attributes.GetEnumerator()
 +
            While ienum.MoveNext
 +
                Dim atr As XmlAttribute = ienum.Current
 +
                If dt.Columns.Contains(atr.Name) = False Then dt.Columns.Add(atr.Name)
 +
                dr(atr.Name) = atr.Value
 
             End While
 
             End While
 +
            If Not IsNothing(ParentRow) Then
 +
                Dim ParentColumn As String = ParentRow.Table.TableName & "_OurID"
 +
                If dt.Columns.Contains(ParentColumn) Then dr(ParentColumn) = ParentRow(ParentColumn)
 +
            End If
 +
            dt.Rows.Add(dr)
 +
            For Each x As XmlNode In NodeRow.ChildNodes
 +
                ParseElements(x, dr)
 +
            Next
 
         End While
 
         End While
 
+
         If Not masterDs.Tables.Contains(ParseNode.Name) Then masterDs.Tables.Add(dt)
         States &= "</states>"
+
        ControlURL &= "</ControlURLs>"
+
 
+
        Dim fout As New IO.StreamWriter(OutputFolder & "\states.xml")
+
        fout.Write(States)
+
        fout.Close()
+
        fout = New IO.StreamWriter(OutputFolder & "\controlurls.xml")
+
        fout.Write(ControlURL)
+
        fout.Close()
+
 
+
 
     End Sub
 
     End Sub
  
     Private Function GetWebPageContent(ByVal strURL As String) As String
+
     Function CreateTable(ByVal Node As XmlNode, ByVal ParentRow As DataRow) As DataTable
         Dim retVal As String = ""
+
         Dim dt As DataTable
         Try
+
         If masterDs.Tables.Contains(Node.Name) Then
             Dim srRead As System.IO.StreamReader = New System.IO.StreamReader(System.Net.WebRequest.Create(strURL).GetResponse.GetResponseStream)
+
             dt = masterDs.Tables(Node.Name)
            retVal = srRead.ReadToEnd
+
            Return dt
         Catch ex As Exception
+
        End If
             retVal = "Hmm.."
+
        dt = New DataTable(Node.Name)
         End Try
+
        'Add primary key col
         Return retVal
+
        Dim KeyColumn As String = Node.Name & "_OurID"
 +
        dt.Columns.Add(New DataColumn(KeyColumn, GetType(System.Int32)))
 +
        dt.Columns(0).AutoIncrement = True
 +
        dt.Constraints.Add(dt.TableName & "PrimaryID", dt.Columns(0), True)
 +
        'Add parent ref column
 +
         If Not IsNothing(ParentRow) Then
 +
             Dim ParentColumn As String = ParentRow.Table.TableName & "_OurID"
 +
            dt.Columns.Add(New DataColumn(ParentColumn, GetType(System.Int32)))
 +
         End If
 +
         Return dt
 
     End Function
 
     End Function

Latest revision as of 03:17, 15 June 2013


This is most likely not an elegant way to do this, but in case someone wants something similar feel free to use this. Please suggest if there are better ways of accomplishing this and if you happen to know so, update this page :)

1. This will give you a single xml file you could load in .NET through Dataset.Readxml and you will get about 48tables.

2. Nested tables like Devices have states and ControlURLs - these become a separate table with a new attribute added to refer what Device ID a row in these tables would relate to the devices table.

Parse.jpg


Using the functions below, a small .NET web app that shows Rooms/Scenes/Devices (Code for that below) - Also see the forum post:

http://forum.micasaverde.com/index.php?topic=7950.0 [1]

Public Class _Default

   Inherits System.Web.UI.Page
   Dim UserDataset As DataSet
   Dim ud As UserData
   Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
       If Not Page.IsPostBack Then
           If Session("UserData") Is Nothing Then
               ud = New UserData
               Session("UserData") = ud.Parse_UserData_To_DataSet("d:\test")
           End If
       End If
       UserDataset = Session("UserData")
       GetData()
   End Sub
   Sub GetData()
       Dim RoomsTable As DataTable = UserDataset.Tables("rooms")
       Me.RoomsGrid.DataSource = RoomsTable
       Me.RoomsGrid.DataBind()
       RoomsGrid.ShowHeader = False
       Dim ScenesTable As DataTable = UserDataset.Tables("scenes")
       Me.ScenesGrid.DataSource = ScenesTable
       Me.ScenesGrid.DataBind()
       ScenesGrid.ShowHeader = False
       Dim DevicesTable As DataTable = UserDataset.Tables("devices")
       Dim drRemove As DataRow() = DevicesTable.Select("invisible=1")
       For Each dr As DataRow In drRemove
           DevicesTable.Rows.Remove(dr)
       Next
       Me.DevicesGrid.DataSource = DevicesTable
       Me.DevicesGrid.DataBind()
       DevicesGrid.ShowHeader = False
   End Sub

End Class


So, This is more like it!!!

Dim masterDs As New DataSet
   Sub Parse_UserData_To_DataSet(ByVal OutputFolder As String, _
                                         Optional ByVal veraURL As String = "http://myhome:49451")
       'Parse XML and create XML files to load in to dataset directly
       Dim settings As New XmlReaderSettings()
       settings.DtdProcessing = DtdProcessing.Parse
       Dim reader As XmlReader = XmlReader.Create(veraURL & "/data_request?output_format=xml&id=user_data", settings)
       Dim doc As New XmlDocument()
       doc.Load(reader)
       Dim root As XmlNode = doc.DocumentElement
       Dim ParseNodeEnum As IEnumerator = root.GetEnumerator
       While (ParseNodeEnum.MoveNext)
           Dim NodeRow As XmlNode = ParseNodeEnum.Current
           ParseElements(NodeRow, Nothing)
       End While
   End Sub
   Sub ParseElements(ByVal ParseNode As XmlNode, ByVal ParentRow As DataRow)
       Dim dt As DataTable = CreateTable(ParseNode, ParentRow)
       Dim ParseNodeEnum As IEnumerator = ParseNode.GetEnumerator
       While (ParseNodeEnum.MoveNext)
           Dim NodeRow As XmlNode = ParseNodeEnum.Current
           Dim dr As DataRow = dt.NewRow
           'Add Attributes as columns to Datatable
           Dim ienum As IEnumerator = NodeRow.Attributes.GetEnumerator()
           While ienum.MoveNext
               Dim atr As XmlAttribute = ienum.Current
               If dt.Columns.Contains(atr.Name) = False Then dt.Columns.Add(atr.Name)
               dr(atr.Name) = atr.Value
           End While
           If Not IsNothing(ParentRow) Then
               Dim ParentColumn As String = ParentRow.Table.TableName & "_OurID"
               If dt.Columns.Contains(ParentColumn) Then dr(ParentColumn) = ParentRow(ParentColumn)
           End If
           dt.Rows.Add(dr)
           For Each x As XmlNode In NodeRow.ChildNodes
               ParseElements(x, dr)
           Next
       End While
       If Not masterDs.Tables.Contains(ParseNode.Name) Then masterDs.Tables.Add(dt)
   End Sub
   Function CreateTable(ByVal Node As XmlNode, ByVal ParentRow As DataRow) As DataTable
       Dim dt As DataTable
       If masterDs.Tables.Contains(Node.Name) Then
           dt = masterDs.Tables(Node.Name)
           Return dt
       End If
       dt = New DataTable(Node.Name)
       'Add primary key col
       Dim KeyColumn As String = Node.Name & "_OurID"
       dt.Columns.Add(New DataColumn(KeyColumn, GetType(System.Int32)))
       dt.Columns(0).AutoIncrement = True
       dt.Constraints.Add(dt.TableName & "PrimaryID", dt.Columns(0), True)
       'Add parent ref column
       If Not IsNothing(ParentRow) Then
           Dim ParentColumn As String = ParentRow.Table.TableName & "_OurID"
           dt.Columns.Add(New DataColumn(ParentColumn, GetType(System.Int32)))
       End If
       Return dt
   End Function
Personal tools