11using Serilog ;
22using ZWaveDotNet . Entities ;
33using System . Reflection ;
4+ using ZWaveDotNet . CommandClasses ;
5+ using ZWaveDotNet . Enums ;
46using ZWaveDotNet . Entities . Enums ;
7+ using System . Xml . Linq ;
58
69namespace ExampleConsole
710{
811 public class TestConsole
912 {
1013 private static readonly string ? Version = Assembly . GetAssembly ( typeof ( Controller ) ) ! . GetName ( ) . Version ? . ToString ( 3 ) ;
1114 private static Controller ? controller ;
12- private static HashSet < ushort > InterviewList = new HashSet < ushort > ( ) ;
13- private static HashSet < ushort > ReadyList = new HashSet < ushort > ( ) ;
15+ private static readonly HashSet < ushort > InterviewList = new HashSet < ushort > ( ) ;
16+ private static readonly HashSet < ushort > ReadyList = new HashSet < ushort > ( ) ;
1417 private static RFRegion region = RFRegion . Unknown ;
18+ private static LinkedList < string > Reports = new LinkedList < string > ( ) ;
19+ private enum Mode { Display , Inclusion , Exclusion } ;
20+ private static Mode currentMode = Mode . Display ;
1521
16- static async Task Main ( )
22+ static async Task Main ( string [ ] args )
1723 {
1824 Log . Logger = new LoggerConfiguration ( ) . WriteTo . File ( "console.log" ) . CreateLogger ( ) ;
1925
@@ -30,6 +36,8 @@ static async Task Main()
3036 //Add event listeners before starting
3137 controller . NodeInfoUpdated += Controller_NodeInfoUpdated ;
3238 controller . NodeReady += Controller_NodeReady ;
39+ controller . NodeExcluded += Controller_NodeExcluded ;
40+ controller . InclusionStopped += Controller_InclusionStopped ;
3341
3442 //Start the controller interview
3543 Console . WriteLine ( "Interviewing Controller..." ) ;
@@ -42,15 +50,86 @@ static async Task Main()
4250 if ( File . Exists ( "nodecache.db" ) )
4351 await controller . ImportNodeDBAsync ( "nodecache.db" ) ;
4452
45- await MainLoop ( ) ;
53+ _ = Task . Factory . StartNew ( MainLoop ) ;
54+ await InputLoop ( ) ;
55+ }
56+
57+ private static void Controller_InclusionStopped ( object ? sender , EventArgs e )
58+ {
59+ currentMode = Mode . Display ;
60+ }
61+
62+ private static void Controller_NodeExcluded ( object ? sender , EventArgs e )
63+ {
64+ Node node = ( Node ) sender ! ;
65+ InterviewList . Remove ( node . ID ) ;
66+ ReadyList . Remove ( node . ID ) ;
67+ currentMode = Mode . Display ;
68+ }
69+
70+ private static async Task InputLoop ( )
71+ {
72+ while ( true )
73+ {
74+ ConsoleKeyInfo key = Console . ReadKey ( ) ;
75+ if ( key . Key == ConsoleKey . E )
76+ {
77+ currentMode = Mode . Exclusion ;
78+ await controller ! . StartExclusion ( ) ;
79+ PrintMain ( ) ;
80+ }
81+ else if ( key . Key == ConsoleKey . I )
82+ {
83+ currentMode = Mode . Inclusion ;
84+ await controller ! . StartInclusion ( InclusionStrategy . PreferS2 , 12345 ) ;
85+ PrintMain ( ) ;
86+ }
87+ else if ( key . Key == ConsoleKey . S )
88+ {
89+ if ( currentMode == Mode . Exclusion )
90+ await controller ! . StopExclusion ( ) ;
91+ else
92+ await controller ! . StopInclusion ( ) ;
93+ currentMode = Mode . Display ;
94+ PrintMain ( ) ;
95+ }
96+ }
4697 }
4798
4899 private static async void Controller_NodeReady ( object ? sender , EventArgs e )
49100 {
50- ushort id = ( ( Node ) sender ! ) . ID ;
51- ReadyList . Add ( id ) ;
52- InterviewList . Add ( id ) ;
101+ Node node = ( Node ) sender ! ;
102+ InterviewList . Add ( node . ID ) ;
103+ ReadyList . Add ( node . ID ) ;
53104 await controller ! . ExportNodeDBAsync ( "nodecache.db" ) ;
105+ AttachListeners ( node ) ;
106+ }
107+
108+ private static void AttachListeners ( Node node )
109+ {
110+ if ( node . HasCommandClass ( CommandClass . SensorMultiLevel ) )
111+ node . GetCommandClass < SensorMultiLevel > ( ) ! . Updated += Node_Updated ;
112+ if ( node . HasCommandClass ( CommandClass . Meter ) )
113+ node . GetCommandClass < Meter > ( ) ! . Updated += Node_Updated ;
114+ if ( node . HasCommandClass ( CommandClass . Notification ) && node . GetCommandClass < Notification > ( ) is Notification not ) //ZWave Weirdness
115+ not . Updated += Node_Updated ;
116+ if ( node . HasCommandClass ( CommandClass . Battery ) )
117+ node . GetCommandClass < Battery > ( ) ! . Status += Node_Updated ;
118+ if ( node . HasCommandClass ( CommandClass . SensorBinary ) )
119+ node . GetCommandClass < SensorBinary > ( ) ! . Updated += Node_Updated ;
120+ if ( node . HasCommandClass ( CommandClass . SensorAlarm ) )
121+ node . GetCommandClass < SensorAlarm > ( ) ! . Alarm += Node_Updated ;
122+ if ( node . HasCommandClass ( CommandClass . SwitchBinary ) )
123+ node . GetCommandClass < SwitchBinary > ( ) ! . SwitchReport += Node_Updated ;
124+ }
125+
126+ private static async Task Node_Updated ( Node sender , CommandClassEventArgs args )
127+ {
128+ if ( args . Report == null )
129+ return ;
130+ if ( Reports . Count > 10 )
131+ Reports . RemoveFirst ( ) ;
132+ Reports . AddLast ( $ "{ DateTime . Now . ToLongTimeString ( ) } Node { sender . ID } : { args . Report . ToString ( ) ! } ") ;
54133 }
55134
56135 private static async void Controller_NodeInfoUpdated ( object ? sender , ApplicationUpdateEventArgs e )
@@ -59,20 +138,17 @@ private static async void Controller_NodeInfoUpdated(object? sender, Application
59138 if ( node != null && ! InterviewList . Contains ( node . ID ) )
60139 {
61140 InterviewList . Add ( node . ID ) ;
62- CancellationTokenSource cts = new CancellationTokenSource ( 180000 ) ;
63- await Task . Factory . StartNew ( async ( ) => {
64- try
65- {
66- await node . Interview ( cts . Token ) ;
67- ReadyList . Add ( node . ID ) ;
68- await controller ! . ExportNodeDBAsync ( "nodecache.db" ) ;
69- }
70- catch ( Exception ex )
71- {
72- Log . Error ( ex , "Uncaught Exception in Node Interview" ) ;
73- }
74- } ) ;
75- }
141+ node . InterviewComplete += Node_InterviewComplete ;
142+ _ = Task . Run ( ( ) => node . Interview ( ) ) ;
143+ }
144+ }
145+
146+ private static async void Node_InterviewComplete ( object ? sender , EventArgs e )
147+ {
148+ Node node = ( Node ) sender ! ;
149+ ReadyList . Add ( node . ID ) ;
150+ await controller ! . ExportNodeDBAsync ( "nodecache.db" ) ;
151+ AttachListeners ( node ) ;
76152 }
77153
78154 private static async Task MainLoop ( )
@@ -87,7 +163,7 @@ private static async Task MainLoop()
87163 private static void PrintMain ( )
88164 {
89165 Console . Clear ( ) ;
90- Console . Write ( $ "ZWaveDotNet v{ Version } - Controller { controller ! . ControllerID } { ( controller ! . IsConnected ? "Connected" : "Disconnected" ) } ") ;
166+ Console . Write ( $ "ZWaveDotNet v{ Version } - Controller # { controller ! . ControllerID } { ( controller ! . IsConnected ? "Connected" : "Disconnected" ) } ") ;
91167 Console . Write ( $ " - v{ controller . APIVersion . Major } ({ region } )") ;
92168 Console . Write ( $ "{ ( controller ! . SupportsLongRange ? " [LR]" : "" ) } ") ;
93169 Console . Write ( $ "{ ( controller ! . Primary ? " [Primary]" : "" ) } ") ;
@@ -97,6 +173,24 @@ private static void PrintMain()
97173 Console . WriteLine ( $ "{ controller . Nodes . Count } Nodes Found:") ;
98174 foreach ( Node n in controller . Nodes . Values )
99175 Console . WriteLine ( n . ToString ( ) ) ;
176+ Console . WriteLine ( ) ;
177+ if ( currentMode == Mode . Display )
178+ {
179+ Console . WriteLine ( "Press I to enter Inclusion mode, E to enter Exclusion mode or S to Stop" ) ;
180+ Console . WriteLine ( "Last 10 Node Reports:" ) ;
181+ foreach ( string report in Reports )
182+ Console . WriteLine ( report ) ;
183+ }
184+ else if ( currentMode == Mode . Inclusion )
185+ {
186+ Console . WriteLine ( "- Inclusion Mode Active (Default PIN 12345) -" ) ;
187+ Console . WriteLine ( "Press the Pairing button on your device" ) ;
188+ }
189+ else
190+ {
191+ Console . WriteLine ( "- Exclusion Mode Active -" ) ;
192+ Console . WriteLine ( "Press the Pairing button on your device" ) ;
193+ }
100194 }
101195 }
102196}
0 commit comments