Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for youless.cs

(view source code of youless.cs as plain text)

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Net.NetworkInformation;
  8. using System.Reflection;
  9. using System.Text;
  10. using System.Text.RegularExpressions;
  11.  
  12.  
  13. namespace RobvanderWoude
  14. {
  15. 	internal class Youless
  16. 	{
  17. 		static readonly string progver = "1.00";
  18.  
  19.  
  20. 		static string address = "youless";
  21. 		static string ipaddress = string.Empty;
  22.  
  23.  
  24. 		static int Main( string[] args )
  25. 		{
  26. 			#region Initialize Variables
  27.  
  28. 			CultureInfo culture = CultureInfo.GetCultureInfo( "en-US" );
  29. 			CultureInfo.CurrentCulture = culture; // SETTING CurrentCulture requires .NET Framework 4.6
  30. 			string exepath = new Uri( Assembly.GetExecutingAssembly( ).CodeBase ).LocalPath;
  31. 			string configfile = Path.Combine( Directory.GetParent( exepath ).FullName, Path.GetFileNameWithoutExtension( exepath ) + ".ip" );
  32.  
  33. 			#endregion Initialize Variables
  34.  
  35.  
  36. 			#region Get Youless Address
  37.  
  38. 			if ( args.Contains( "/?" ) )
  39. 			{
  40. 				return ShowHelp( );
  41. 			}
  42. 			else if ( args.Length == 0 )
  43. 			{
  44. 				// Get the IP address for the default hostname "youless"
  45. 				ValidateAddress( address );
  46. 			}
  47. 			else if ( args.Length == 1 )
  48. 			{
  49. 				if ( ValidateAddress( args[0] ) )
  50. 				{
  51. 					address = args[0];
  52. 				}
  53. 			}
  54. 			else if ( args.Length > 1 )
  55. 			{
  56. 				return ShowHelp( );
  57. 			}
  58. 			else if ( File.Exists( configfile ) )
  59. 			{
  60. 				address = File.ReadAllText( configfile ).Trim( );
  61. 				if ( !ValidateAddress( address ) )
  62. 				{
  63. 					File.Delete( configfile );
  64. 					address = string.Empty;
  65. 				}
  66. 			}
  67.  
  68. 			if ( string.IsNullOrWhiteSpace( ipaddress ) )
  69. 			{
  70. 				while ( string.IsNullOrWhiteSpace( ipaddress ) )
  71. 				{
  72. 					address = PromptForIP( );
  73. 				}
  74. 			}
  75.  
  76. 			if ( !File.Exists( configfile ) )
  77. 			{
  78. 				File.WriteAllText( configfile, ipaddress );
  79. 			}
  80.  
  81. 			#endregion Get Youless Address
  82.  
  83.  
  84. 			#region Device Data
  85.  
  86. 			Console.WriteLine( );
  87.  
  88. 			string url = string.Format( "http://{0}/d", ipaddress );
  89. 			YoulessClass.fw = string.Empty;
  90. 			if ( !YoulessReadData( url ) )
  91. 			{
  92. 				Console.Error.WriteLine( "\nUitlezen Youless {0} niet gelukt", ipaddress );
  93. 				return -1;
  94. 			}
  95.  
  96. 			Console.WriteLine( "Youless model                :\t{0}", YoulessClass.model );
  97. 			if ( !string.IsNullOrWhiteSpace( YoulessClass.fw ) )
  98. 			{
  99. 				Console.WriteLine( "Youless firmware             :\t{0}", YoulessClass.fw );
  100. 			}
  101. 			Console.WriteLine( "Youless MAC adres            :\t{0}", YoulessClass.mac );
  102. 			Console.WriteLine( "Youless IP adres             :\t{0}", ipaddress );
  103.  
  104. 			#endregion Device Data
  105.  
  106.  
  107. 			#region Power Consumption Data
  108.  
  109. 			Console.WriteLine( );
  110.  
  111. 			url = string.Format( "http://{0}/e", ipaddress ); // URL for power consumption log
  112.  
  113. 			if ( YoulessReadData( url ) )
  114. 			{
  115. 				Console.WriteLine( "Tijdstip                     :\t{0}", YoulessClass.gts.ToString( "yyyy-MM-dd HH:mm" ) );
  116. 				Console.WriteLine( );
  117. 				Console.WriteLine( "Vermogen                     :\t{0} W", YoulessClass.pwr );
  118. 				Console.WriteLine( "P1 afname hoog tarief        :\t{0} kWh", YoulessClass.p1 );
  119. 				Console.WriteLine( "P1 afname laag tarief        :\t{0} kWh", YoulessClass.p2 );
  120. 				Console.WriteLine( "P1 teruglevering hoog tarief :\t{0} kWh", YoulessClass.n1 );
  121. 				Console.WriteLine( "P1 teruglevering laag tarief :\t{0} kWh", YoulessClass.n2 );
  122. 				Console.WriteLine( "Netto totaal verbruik        :\t{0} kWh", YoulessClass.net );
  123. 				Console.WriteLine( );
  124. 				Console.WriteLine( "Gas verbruik                 :\t{0} m\x00B3", YoulessClass.gas );
  125. 			}
  126. 			else
  127. 			{
  128. 				Console.Error.WriteLine( "\nUitlezen Youless {0} niet gelukt", ipaddress );
  129. 				return -1;
  130. 			}
  131.  
  132. 			#endregion Power Consumption Data
  133.  
  134.  
  135. 			return 0;
  136. 		}
  137.  
  138.  
  139. 		static PingReply Ping( string address )
  140. 		{
  141. 			Ping pingSender = new Ping( );
  142. 			PingOptions options = new PingOptions( );
  143. 			options.DontFragment = true;
  144. 			// Create a buffer of 32 bytes of data to be transmitted.
  145. 			string data = new string( 'a', 32 );
  146. 			byte[] buffer = Encoding.ASCII.GetBytes( data );
  147. 			int timeout = 120;
  148. 			return pingSender.Send( address, timeout, buffer, options );
  149. 		}
  150.  
  151.  
  152. 		static string PromptForIP( )
  153. 		{
  154. 			Console.Write( "Vul het IP-adres van de Youless in: " );
  155. 			string ip = Console.ReadLine( ).Trim( );
  156. 			if ( ValidateAddress( ip, true ) )
  157. 			{
  158. 				return ip;
  159. 			}
  160. 			else
  161. 			{
  162. 				return string.Empty;
  163. 			}
  164. 		}
  165.  
  166.  
  167. 		public static int ShowHelp( params string[] errmsg )
  168. 		{
  169. 			#region Error Message
  170.  
  171. 			if ( errmsg.Length > 0 )
  172. 			{
  173. 				List<string> errargs = new List<string>( errmsg );
  174. 				errargs.RemoveAt( 0 );
  175. 				Console.Error.WriteLine( );
  176. 				Console.ForegroundColor = ConsoleColor.Red;
  177. 				Console.Error.Write( "ERROR:\t" );
  178. 				Console.ForegroundColor = ConsoleColor.White;
  179. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  180. 				Console.ResetColor( );
  181. 			}
  182.  
  183. 			#endregion Error Message
  184.  
  185.  
  186. 			#region Help Text
  187.  
  188. 			/*
  189. 			Youless.exe,  Version 1.00
  190. 			Read data from a Youless LS120 energy monitor device
  191.  
  192. 			Usage:    Youless.exe  [ ip ]
  193.  
  194. 			Where:    ip     is the IP address of the Youless device
  195.  
  196. 			Notes:    If no IP address is specified, the program will try to resolve the
  197. 			          IP address for hostname "youless". If unsuccessful, you will be
  198. 			          prompted to enter it, and the address will be saved in a file
  199. 			          named Youless.cfg in the program's parent directory.
  200. 			          This program requires .NET Framework version 4.6.
  201. 			          Return code (\"ErrorLevel\") equals -1 in case of (command line)
  202. 			          errors, otherwise 0.
  203.  
  204. 			Written by Rob van der Woude
  205. 			https://www.robvanderwoude.com
  206. 			*/
  207.  
  208. 			#endregion Help Text
  209.  
  210.  
  211. 			#region Display Help Text
  212.  
  213. 			Console.Error.WriteLine( );
  214.  
  215. 			Console.Error.WriteLine( "Youless.exe,  Version {0}", progver );
  216.  
  217. 			Console.Error.WriteLine( "Read data from a Youless LS120 energy monitor device" );
  218.  
  219. 			Console.Error.WriteLine( );
  220.  
  221. 			Console.Error.Write( "Usage:    " );
  222. 			Console.ForegroundColor = ConsoleColor.White;
  223. 			Console.Error.WriteLine( "Youless.exe  [ ip ]" );
  224. 			Console.ResetColor( );
  225.  
  226. 			Console.Error.WriteLine( );
  227.  
  228. 			Console.Error.Write( "Where:    " );
  229. 			Console.ForegroundColor = ConsoleColor.White;
  230. 			Console.Error.Write( "ip" );
  231. 			Console.ResetColor( );
  232. 			Console.Error.WriteLine( "     is the IP address of the Youless device" );
  233.  
  234. 			Console.Error.WriteLine( );
  235.  
  236. 			Console.Error.WriteLine( "Notes:    If no IP address is specified, the program will try to resolve the" );
  237.  
  238. 			Console.Error.WriteLine( "          IP address for hostname \"youless\". If unsuccessful, you will be" );
  239.  
  240. 			Console.Error.WriteLine( "          prompted to enter it, and the address will be saved in a file" );
  241.  
  242. 			Console.Error.WriteLine( "          named Youless.ip in the program's parent directory." );
  243.  
  244. 			Console.Error.WriteLine( "          This program requires .NET Framework version 4.6." );
  245.  
  246. 			Console.Error.WriteLine( "          Return code (\"ErrorLevel\") equals -1 in case of (command line)" );
  247.  
  248. 			Console.Error.WriteLine( "          errors, otherwise 0." );
  249.  
  250. 			Console.Error.WriteLine( );
  251.  
  252. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  253.  
  254. 			Console.Error.WriteLine( "https://www.robvanderwoude.com" );
  255.  
  256. 			#endregion Display Help Text
  257.  
  258.  
  259. 			return -1;
  260. 		}
  261.  
  262.  
  263. 		static bool ValidateAddress( string address, bool iponly = false )
  264. 		{
  265. 			bool valid = true;
  266. 			if ( iponly )
  267. 			{
  268. 				Regex regex = new Regex( @"^(\d+(\.\d+){3}|[:a-f\d]{3,})$", RegexOptions.IgnoreCase );
  269. 				valid = regex.IsMatch( address );
  270. 			}
  271. 			if ( valid )
  272. 			{
  273. 				PingReply reply = Ping( address );
  274. 				valid = ( reply.Status == IPStatus.Success );
  275. 				if ( valid )
  276. 				{
  277. 					ipaddress = reply.Address.ToString( );
  278. 				}
  279. 				else
  280. 				{
  281. 					Console.Error.WriteLine( "Unable to reach {0}", address );
  282. 				}
  283. 			}
  284. 			return valid;
  285. 		}
  286.  
  287.  
  288. 		static bool YoulessReadData( string url )
  289. 		{
  290. 			try
  291. 			{
  292. 				using ( WebClient wc = new WebClient( ) )
  293. 				{
  294. 					string[] json = wc.DownloadString( url ).Split( "{}[],".ToCharArray( ), StringSplitOptions.RemoveEmptyEntries );
  295. 					foreach ( string keyval in json )
  296. 					{
  297. 						string key = keyval.Split( ":".ToCharArray( ) )[0].Trim( "\"\t ".ToCharArray( ) );
  298. 						string val = keyval.Split( ":".ToCharArray( ), 2 )[1].Trim( "\"\t ".ToCharArray( ) );
  299. 						switch ( key )
  300. 						{
  301. 							case "cs0":
  302. 								YoulessClass.cs0 = double.Parse( val );
  303. 								break;
  304. 							case "fw":
  305. 								YoulessClass.fw = val;
  306. 								break;
  307. 							case "gas":
  308. 								YoulessClass.gas = double.Parse( val );
  309. 								break;
  310. 							case "gts":
  311. 								string timestamp = string.Format( "20{0}-{1}-{2} {3}:{4}", val.Substring( 0, 2 ), val.Substring( 2, 2 ), val.Substring( 4, 2 ), val.Substring( 6, 2 ), val.Substring( 8, 2 ) );
  312. 								YoulessClass.gts = DateTime.Parse( timestamp );
  313. 								break;
  314. 							case "mac":
  315. 								YoulessClass.mac = val.Replace( ':', '-' ).ToUpper( );
  316. 								break;
  317. 							case "model":
  318. 								YoulessClass.model = val;
  319. 								break;
  320. 							case "n1":
  321. 								YoulessClass.n1 = double.Parse( val );
  322. 								break;
  323. 							case "n2":
  324. 								YoulessClass.n2 = double.Parse( val );
  325. 								break;
  326. 							case "net":
  327. 								YoulessClass.net = double.Parse( val );
  328. 								break;
  329. 							case "p1":
  330. 								YoulessClass.p1 = double.Parse( val );
  331. 								break;
  332. 							case "p2":
  333. 								YoulessClass.p2 = double.Parse( val );
  334. 								break;
  335. 							case "ps0":
  336. 								YoulessClass.ps0 = int.Parse( val );
  337. 								break;
  338. 							case "pwr":
  339. 								YoulessClass.pwr = int.Parse( val );
  340. 								break;
  341. 							case "tm":
  342. 								YoulessClass.tm = new DateTime( long.Parse( val ) );
  343. 								break;
  344. 							case "ts0":
  345. 								YoulessClass.ts0 = new DateTime( long.Parse( val ) );
  346. 								break;
  347. 							default:
  348. 								// invalid/unknown key
  349. 								return false;
  350. 						}
  351. 					}
  352. 				}
  353. 				return true;
  354. 			}
  355. 			catch ( Exception e )
  356. 			{
  357. 				Console.Error.WriteLine( e.Message );
  358. 				return false;
  359. 			}
  360. 		}
  361. 	}
  362.  
  363.  
  364. 	public static class YoulessClass
  365. 	{
  366. 		public static double cs0
  367. 		{
  368. 			get; set;
  369. 		}
  370.  
  371. 		public static string fw
  372. 		{
  373. 			get; set;
  374. 		}
  375.  
  376. 		public static double gas
  377. 		{
  378. 			get; set;
  379. 		}
  380.  
  381. 		public static DateTime gts
  382. 		{
  383. 			get; set;
  384. 		}
  385.  
  386. 		public static string mac
  387. 		{
  388. 			get; set;
  389. 		}
  390.  
  391. 		public static string model
  392. 		{
  393. 			get; set;
  394. 		}
  395.  
  396. 		public static double n1
  397. 		{
  398. 			get; set;
  399. 		}
  400.  
  401. 		public static double n2
  402. 		{
  403. 			get; set;
  404. 		}
  405.  
  406. 		public static double net
  407. 		{
  408. 			get; set;
  409. 		}
  410.  
  411. 		public static double p1
  412. 		{
  413. 			get; set;
  414. 		}
  415.  
  416. 		public static double p2
  417. 		{
  418. 			get; set;
  419. 		}
  420.  
  421. 		public static int ps0
  422. 		{
  423. 			get; set;
  424. 		}
  425.  
  426. 		public static int pwr
  427. 		{
  428. 			get; set;
  429. 		}
  430.  
  431. 		public static DateTime tm
  432. 		{
  433. 			get; set;
  434. 		}
  435.  
  436. 		public static DateTime ts0
  437. 		{
  438. 			get; set;
  439. 		}
  440. 	}
  441. }

page last modified: 2024-04-16; loaded in 0.0302 seconds