{"id":33,"date":"2011-09-11T00:53:41","date_gmt":"2011-09-11T04:53:41","guid":{"rendered":"http:\/\/www.cloppermillweather.org\/blog\/?p=33"},"modified":"2011-09-17T01:21:03","modified_gmt":"2011-09-17T05:21:03","slug":"software-update","status":"publish","type":"post","link":"https:\/\/www.cloppermillweather.org\/blog\/2011\/09\/11\/software-update\/","title":{"rendered":"Software Update"},"content":{"rendered":"<p>My next step was to modify my software so that it would work with the hub.\u00a0 In order to read a sensor, the software would need to know the switches to enable and disable for each sensor, and would need to enable those switches prior to reading the sensor.<\/p>\n<p>My first thought was to include that information in the configuration file.\u00a0 However this approach would be inflexible, and would not permit multiple hubs as I was only planned to include the information for one switch.<\/p>\n<p>My next idea was to search the network, locate the switch, and map out the path to each sensor.\u00a0 I got that working, but it still limited me to one switch as I was not searching each path for any additional switches.<\/p>\n<p>Further research revealed that there is a NetworkMonitor class included in the 1-Wire API that periodically traverses the 1-Wire net and sends a message whenever a a sensor appears or disappears on the network.\u00a0 It uses the Observer design pattern, where the application wanting to receive notifications provides a class instance with the callback methods to the monitor.\u00a0 The information in the callback includes the full path to the sensor through multiple switches if any.\u00a0 This sounded like exactly what I wanted.\u00a0 Support for multiple switches and the ability to dynamically update whenever a sensor was added, removed, or even moved from one port to another.<\/p>\n<p>Got it working fine in a stand alone program that just monitored the network.\u00a0 When I integrated the network monitor into my program the behavior was different.\u00a0 Every time it traversed the network it showed all the sensors as new.\u00a0 Then it would throw an exception after a few minutes and stop.\u00a0 Some kind of interaction between my code to read the bus and the network monitor.\u00a0 So I moved on to the approach I used as my final solution (for now).\u00a0 This was still my favorite approach, as it permits the network to be dynamic, adapting to sensors coming and going on the bus.\u00a0 I intend to revisit the idea sometime down the road.<\/p>\n<p>For my next attempt, at program start up I manually traversed the entire network, including any nested switches using a breadth first search algorithm.\u00a0 I created an OWPath object (a class provided in the 1-Wire API) for each sensor found on the net so that the path could be opened and closed when reading the sensor.\u00a0 It doesn&#8217;t dynamically adapt to sensors moving or coming and going while the application is running, but it works well for building a static map of the network.\u00a0 I will have to restart the application if the sensors change or move in order to build a new map.\u00a0 I also can log any sensors found on the bus but not in my configuration file, or sensors in the configuration file not found on the bus.\u00a0 I may come back to the NetworkMonitor approach again, but I&#8217;m satisfied for now.<\/p>\n<p>For anybody interested, here&#8217;s my code for traversing the 1-Wire network.\u00a0 There are a few things that are specific to my application, but the logic is hopefully clear enough to adapt.\u00a0 Sorry, but the formatting got a bit munged.<br \/>\n<code><\/p>\n<pre>\u00a0\u00a0\u00a0\r\n    private Hashtable&lt;String, OWPath&gt; walkNet(DSPortAdapter adapter)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0 \u00a0    \/\/ vector for holding a list of paths to be searched\r\n\u00a0\u00a0 \u00a0    Vector&lt;OWPath&gt; pathsToSearch = new Vector&lt;OWPath&gt;();\r\n\u00a0\u00a0 \u00a0    boolean searchResult = false;\r\n\r\n\u00a0\u00a0 \u00a0    \/\/ hash table for holding the OWPath objects for each\r\n        \/\/   device container.\r\n\u00a0\u00a0 \u00a0    Hashtable&lt;String, OWPath&gt; devicePathHash =\r\n            new Hashtable&lt;String, OWPath&gt;();\r\n\r\n\u00a0\u00a0 \u00a0    try\r\n\u00a0\u00a0 \u00a0    {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     \/\/ seed list with main branch\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     pathsToSearch.addElement(new OWPath(adapter));\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     \/\/ acquire the adapter\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     adapter.beginExclusive(true);\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     \/\/ setup the search\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     adapter.setSearchAllDevices();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     adapter.targetAllFamilies();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     adapter.setSpeed(DSPortAdapter.SPEED_REGULAR);\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     \/\/ walk path and get all devices on branch.\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     \/\/ if any switches are found, add them to the list\r\n            \/\/   of paths to search\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     \/\/ search through all of the paths\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     for (int i = 0; i &lt; pathsToSearch.size(); i++)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        \/\/ set searches to not use reset\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        adapter.setNoResetSearch();\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        \/\/ get the next path to search and open it\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        OWPath path = (OWPath)pathsToSearch.elementAt(i);\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        try\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         \/\/ try to open the current path\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         path.open();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        }\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        catch(Exception e)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         \/\/ if opening the path failed, log an error and\r\n                    \/\/    continue on to the next path\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         ErrorLog.logError(\"walkNet(): Error opening path \"\r\n                        + path.toString());\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         continue;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        }\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        \/\/ get the devices on the currently open path\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        searchResult = adapter.findFirstDevice();\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        \/\/ loop while devices found\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        while (searchResult)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         \/\/ get the 1-Wire address\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         String address = adapter.getAddressAsString();\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         \/\/ check if the device already exists in the hash\r\n                    \/\/    table of addresses\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         if (!devicePathHash.containsKey(address))\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0            OneWireContainer owc =\r\n                          adapter.getDeviceContainer(address);\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0            \/\/ check to see if it's a switch.\u00a0 If so, add\r\n                        \/\/    it to the paths to be searched\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0            \/\/\u00a0\u00a0 \u00a0if we haven't already searched it\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0            if (owc instanceof SwitchContainer)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0            {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0             SwitchContainer sc = (SwitchContainer)owc;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0             byte[] state = sc.readDevice();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0             for (int j = 0;\r\n                                   j &lt; sc.getNumberChannels(state); j++)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0             {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0                OWPath tmp = new OWPath(adapter, path);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0                tmp.add(owc, j);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0                if (!pathsToSearch.contains(tmp))\r\n                                {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0                 pathsToSearch.addElement(tmp);\r\n                                 }\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0             }\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0            }\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0            \/\/ save off the address and path\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0            synchronized(devicePathHash)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0            {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0             devicePathHash.put(address, path);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0            }\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         }\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         \/\/ check if the existing device moved\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         else if (!path.equals((OWPath)\r\n                                devicePathHash.get(address)))\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0            \/\/ if it has moved, add the new\r\n                        \/\/    address\/path pair\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0            synchronized(devicePathHash)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0            {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0             devicePathHash.put(address, path);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0            }\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         }\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         \/\/ find the next device on this branch\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         path.open();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0         searchResult = adapter.findNextDevice();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        }\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0        path.close();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     }\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     \/\/ clean up after ourselves\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     adapter.setSearchAllDevices();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     adapter.endExclusive();\r\n\u00a0\u00a0 \u00a0    }\r\n\u00a0\u00a0 \u00a0    catch (OneWireException e)\r\n\u00a0\u00a0 \u00a0    {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0     ErrorLog.logError(\"Error Serching the 1-Wire Bus\");\r\n\u00a0\u00a0 \u00a0    }\r\n\r\n\u00a0\u00a0 \u00a0    return devicePathHash;\r\n\r\n\u00a0\u00a0\u00a0 }<\/pre>\n<p><\/code><\/p>\n","protected":false},"excerpt":{"rendered":"<p>My next step was to modify my software so that it would work with the hub.\u00a0 In order to read a sensor, the software would need to know the switches to enable and disable for each sensor, and would need &hellip; <a href=\"https:\/\/www.cloppermillweather.org\/blog\/2011\/09\/11\/software-update\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-33","post","type-post","status-publish","format-standard","hentry","category-weather"],"_links":{"self":[{"href":"https:\/\/www.cloppermillweather.org\/blog\/wp-json\/wp\/v2\/posts\/33","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloppermillweather.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloppermillweather.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloppermillweather.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloppermillweather.org\/blog\/wp-json\/wp\/v2\/comments?post=33"}],"version-history":[{"count":0,"href":"https:\/\/www.cloppermillweather.org\/blog\/wp-json\/wp\/v2\/posts\/33\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.cloppermillweather.org\/blog\/wp-json\/wp\/v2\/media?parent=33"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloppermillweather.org\/blog\/wp-json\/wp\/v2\/categories?post=33"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloppermillweather.org\/blog\/wp-json\/wp\/v2\/tags?post=33"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}